20 from .downloads import download_entry |
20 from .downloads import download_entry |
21 from .py2exe import ( |
21 from .py2exe import ( |
22 build_py2exe, |
22 build_py2exe, |
23 stage_install, |
23 stage_install, |
24 ) |
24 ) |
|
25 from .pyoxidizer import run_pyoxidizer |
25 from .util import ( |
26 from .util import ( |
26 extract_zip_to_directory, |
27 extract_zip_to_directory, |
27 normalize_windows_version, |
28 normalize_windows_version, |
28 process_install_rules, |
29 process_install_rules, |
29 sign_with_signtool, |
30 sign_with_signtool, |
282 el.appendChild(shortcut) |
283 el.appendChild(shortcut) |
283 |
284 |
284 return doc.toprettyxml() |
285 return doc.toprettyxml() |
285 |
286 |
286 |
287 |
287 def build_installer( |
288 def build_installer_py2exe( |
288 source_dir: pathlib.Path, |
289 source_dir: pathlib.Path, |
289 python_exe: pathlib.Path, |
290 python_exe: pathlib.Path, |
290 msi_name='mercurial', |
291 msi_name='mercurial', |
291 version=None, |
292 version=None, |
292 extra_packages_script=None, |
293 extra_packages_script=None, |
293 extra_wxs: typing.Optional[typing.Dict[str, str]] = None, |
294 extra_wxs: typing.Optional[typing.Dict[str, str]] = None, |
294 extra_features: typing.Optional[typing.List[str]] = None, |
295 extra_features: typing.Optional[typing.List[str]] = None, |
295 signing_info: typing.Optional[typing.Dict[str, str]] = None, |
296 signing_info: typing.Optional[typing.Dict[str, str]] = None, |
296 ): |
297 ): |
297 """Build a WiX MSI installer. |
298 """Build a WiX MSI installer using py2exe. |
298 |
299 |
299 ``source_dir`` is the path to the Mercurial source tree to use. |
300 ``source_dir`` is the path to the Mercurial source tree to use. |
300 ``arch`` is the target architecture. either ``x86`` or ``x64``. |
301 ``arch`` is the target architecture. either ``x86`` or ``x64``. |
301 ``python_exe`` is the path to the Python executable to use/bundle. |
302 ``python_exe`` is the path to the Python executable to use/bundle. |
302 ``version`` is the Mercurial version string. If not defined, |
303 ``version`` is the Mercurial version string. If not defined, |
353 source_dir, |
354 source_dir, |
354 build_dir, |
355 build_dir, |
355 staging_dir, |
356 staging_dir, |
356 arch, |
357 arch, |
357 version=version, |
358 version=version, |
|
359 python2=True, |
|
360 msi_name=msi_name, |
|
361 extra_wxs=extra_wxs, |
|
362 extra_features=extra_features, |
|
363 signing_info=signing_info, |
|
364 ) |
|
365 |
|
366 |
|
367 def build_installer_pyoxidizer( |
|
368 source_dir: pathlib.Path, |
|
369 target_triple: str, |
|
370 msi_name='mercurial', |
|
371 version=None, |
|
372 extra_wxs: typing.Optional[typing.Dict[str, str]] = None, |
|
373 extra_features: typing.Optional[typing.List[str]] = None, |
|
374 signing_info: typing.Optional[typing.Dict[str, str]] = None, |
|
375 ): |
|
376 """Build a WiX MSI installer using PyOxidizer.""" |
|
377 hg_build_dir = source_dir / "build" |
|
378 build_dir = hg_build_dir / ("wix-%s" % target_triple) |
|
379 staging_dir = build_dir / "stage" |
|
380 |
|
381 arch = "x64" if "x86_64" in target_triple else "x86" |
|
382 |
|
383 build_dir.mkdir(parents=True, exist_ok=True) |
|
384 run_pyoxidizer(source_dir, build_dir, staging_dir, target_triple) |
|
385 |
|
386 # We also install some extra files. |
|
387 process_install_rules(EXTRA_INSTALL_RULES, source_dir, staging_dir) |
|
388 |
|
389 # And remove some files we don't want. |
|
390 for f in STAGING_REMOVE_FILES: |
|
391 p = staging_dir / f |
|
392 if p.exists(): |
|
393 print('removing %s' % p) |
|
394 p.unlink() |
|
395 |
|
396 return run_wix_packaging( |
|
397 source_dir, |
|
398 build_dir, |
|
399 staging_dir, |
|
400 arch, |
|
401 version, |
|
402 python2=False, |
358 msi_name=msi_name, |
403 msi_name=msi_name, |
359 extra_wxs=extra_wxs, |
404 extra_wxs=extra_wxs, |
360 extra_features=extra_features, |
405 extra_features=extra_features, |
361 signing_info=signing_info, |
406 signing_info=signing_info, |
362 ) |
407 ) |
366 source_dir: pathlib.Path, |
411 source_dir: pathlib.Path, |
367 build_dir: pathlib.Path, |
412 build_dir: pathlib.Path, |
368 staging_dir: pathlib.Path, |
413 staging_dir: pathlib.Path, |
369 arch: str, |
414 arch: str, |
370 version: str, |
415 version: str, |
|
416 python2: bool, |
371 msi_name: typing.Optional[str] = "mercurial", |
417 msi_name: typing.Optional[str] = "mercurial", |
372 extra_wxs: typing.Optional[typing.Dict[str, str]] = None, |
418 extra_wxs: typing.Optional[typing.Dict[str, str]] = None, |
373 extra_features: typing.Optional[typing.List[str]] = None, |
419 extra_features: typing.Optional[typing.List[str]] = None, |
374 signing_info: typing.Optional[typing.Dict[str, str]] = None, |
420 signing_info: typing.Optional[typing.Dict[str, str]] = None, |
375 ): |
421 ): |
404 wix_path = build_dir / ('wix-%s' % wix_entry['version']) |
450 wix_path = build_dir / ('wix-%s' % wix_entry['version']) |
405 |
451 |
406 if not wix_path.exists(): |
452 if not wix_path.exists(): |
407 extract_zip_to_directory(wix_pkg, wix_path) |
453 extract_zip_to_directory(wix_pkg, wix_path) |
408 |
454 |
409 ensure_vc90_merge_modules(build_dir) |
455 if python2: |
|
456 ensure_vc90_merge_modules(build_dir) |
410 |
457 |
411 source_build_rel = pathlib.Path(os.path.relpath(source_dir, build_dir)) |
458 source_build_rel = pathlib.Path(os.path.relpath(source_dir, build_dir)) |
412 |
459 |
413 defines = {'Platform': arch} |
460 defines = {'Platform': arch} |
414 |
461 |
423 run_candle(wix_path, build_dir, source, rel_path, defines=defines) |
470 run_candle(wix_path, build_dir, source, rel_path, defines=defines) |
424 |
471 |
425 source = wix_dir / 'mercurial.wxs' |
472 source = wix_dir / 'mercurial.wxs' |
426 defines['Version'] = version |
473 defines['Version'] = version |
427 defines['Comments'] = 'Installs Mercurial version %s' % version |
474 defines['Comments'] = 'Installs Mercurial version %s' % version |
428 defines['VCRedistSrcDir'] = str(build_dir) |
475 |
|
476 if python2: |
|
477 defines["PythonVersion"] = "2" |
|
478 defines['VCRedistSrcDir'] = str(build_dir) |
|
479 else: |
|
480 defines["PythonVersion"] = "3" |
|
481 |
|
482 if (staging_dir / "lib").exists(): |
|
483 defines["MercurialHasLib"] = "1" |
|
484 |
429 if extra_features: |
485 if extra_features: |
430 assert all(';' not in f for f in extra_features) |
486 assert all(';' not in f for f in extra_features) |
431 defines['MercurialExtraFeatures'] = ';'.join(extra_features) |
487 defines['MercurialExtraFeatures'] = ';'.join(extra_features) |
432 |
488 |
433 run_candle(wix_path, build_dir, source, source_build_rel, defines=defines) |
489 run_candle(wix_path, build_dir, source, source_build_rel, defines=defines) |