diff --git a/contrib/packaging/hgpackaging/wix.py b/contrib/packaging/hgpackaging/wix.py --- a/contrib/packaging/hgpackaging/wix.py +++ b/contrib/packaging/hgpackaging/wix.py @@ -12,6 +12,7 @@ import re import subprocess import tempfile +import typing import xml.dom.minidom from .downloads import ( @@ -178,7 +179,8 @@ def build_installer(source_dir: pathlib.Path, python_exe: pathlib.Path, msi_name='mercurial', version=None, post_build_fn=None, - extra_prebuild_script=None): + extra_prebuild_script=None, + extra_wxs:typing.Optional[typing.Dict[str,str]]=None): """Build a WiX MSI installer. ``source_dir`` is the path to the Mercurial source tree to use. @@ -190,6 +192,7 @@ Mercurial but before invoking WiX. It can be used to e.g. facilitate signing. It is passed the paths to the Mercurial source, build, and dist directories and the resolved Mercurial version. + ``extra_wxs`` is a dict of {wxs_name: working_dir_for_wxs_build}. """ arch = 'x64' if r'\x64' in os.environ.get('LIB', '') else 'x86' @@ -231,6 +234,9 @@ wxs_source_dir = source_dir / rel_path run_candle(wix_path, build_dir, wxs, wxs_source_dir, defines=defines) + for source, rel_path in sorted((extra_wxs or {}).items()): + run_candle(wix_path, build_dir, source, rel_path, defines=defines) + # candle.exe doesn't like when we have an open handle on the file. # So use TemporaryDirectory() instead of NamedTemporaryFile(). with tempfile.TemporaryDirectory() as td: @@ -265,6 +271,11 @@ assert source.endswith('.wxs') args.append(str(build_dir / ('%s.wixobj' % source[:-4]))) + for source, rel_path in sorted((extra_wxs or {}).items()): + assert source.endswith('.wxs') + source = os.path.basename(source) + args.append(str(build_dir / ('%s.wixobj' % source[:-4]))) + args.extend([ str(build_dir / 'library.wixobj'), str(build_dir / 'mercurial.wixobj'), @@ -282,7 +293,8 @@ def build_signed_installer(source_dir: pathlib.Path, python_exe: pathlib.Path, name: str, version=None, subject_name=None, cert_path=None, cert_password=None, - timestamp_url=None, extra_prebuild_script=None): + timestamp_url=None, extra_prebuild_script=None, + extra_wxs=None): """Build an installer with signed executables.""" post_build_fn = make_post_build_signing_fn( @@ -295,7 +307,8 @@ info = build_installer(source_dir, python_exe=python_exe, msi_name=name.lower(), version=version, post_build_fn=post_build_fn, - extra_prebuild_script=extra_prebuild_script) + extra_prebuild_script=extra_prebuild_script, + extra_wxs=extra_wxs) description = '%s %s' % (name, version) diff --git a/contrib/packaging/wix/build.py b/contrib/packaging/wix/build.py --- a/contrib/packaging/wix/build.py +++ b/contrib/packaging/wix/build.py @@ -36,6 +36,8 @@ help='Version string to use') parser.add_argument('--extra-prebuild-script', help='Extra script to run after creating virtualenv.') + parser.add_argument('--extra-wxs', + help='CSV of path_to_wxs_file=working_dir_for_wxs_file') args = parser.parse_args() @@ -58,6 +60,9 @@ if args.extra_prebuild_script: kwargs['extra_prebuild_script'] = args.extra_prebuild_script + if args.extra_wxs: + kwargs['extra_wxs'] = dict( + thing.split("=") for thing in args.extra_wxs.split(',')) if args.sign_sn or args.sign_cert: fn = build_signed_installer