automation: support building Python 3 MSI installers
This is very similar to what we just did for Inno.
Differential Revision: https://phab.mercurial-scm.org/D8484
--- a/contrib/automation/hgautomation/cli.py Fri Apr 24 12:11:08 2020 -0700
+++ b/contrib/automation/hgautomation/cli.py Fri Apr 24 12:37:43 2020 -0700
@@ -92,7 +92,13 @@
def build_wix(
- hga: HGAutomation, aws_region, arch, revision, version, base_image_name
+ hga: HGAutomation,
+ aws_region,
+ python_version,
+ arch,
+ revision,
+ version,
+ base_image_name,
):
c = hga.aws_connection(aws_region)
image = aws.ensure_windows_dev_ami(c, base_image_name=base_image_name)
@@ -103,10 +109,15 @@
windows.synchronize_hg(SOURCE_ROOT, revision, instance)
- for a in arch:
- windows.build_wix_installer(
- instance.winrm_client, a, DIST_PATH, version=version
- )
+ for py_version in python_version:
+ for a in arch:
+ windows.build_wix_installer(
+ instance.winrm_client,
+ py_version,
+ a,
+ DIST_PATH,
+ version=version,
+ )
def build_windows_wheel(
@@ -163,12 +174,9 @@
windows.build_inno_installer(
winrm_client, py_version, arch, DIST_PATH, version=version
)
-
- for arch in ('x86', 'x64'):
- windows.purge_hg(winrm_client)
- windows.build_wix_installer(
- winrm_client, arch, DIST_PATH, version=version
- )
+ windows.build_wix_installer(
+ winrm_client, py_version, arch, DIST_PATH, version=version
+ )
def terminate_ec2_instances(hga: HGAutomation, aws_region):
@@ -379,6 +387,14 @@
sp = subparsers.add_parser('build-wix', help='Build WiX installer(s)')
sp.add_argument(
+ '--python-version',
+ help='Which version of Python to target',
+ choices={2, 3},
+ type=int,
+ nargs='*',
+ default=[3],
+ )
+ sp.add_argument(
'--arch',
help='Architecture to build for',
choices={'x86', 'x64'},
--- a/contrib/automation/hgautomation/windows.py Fri Apr 24 12:11:08 2020 -0700
+++ b/contrib/automation/hgautomation/windows.py Fri Apr 24 12:37:43 2020 -0700
@@ -95,7 +95,17 @@
}}
'''
-BUILD_WIX = r'''
+BUILD_WIX_PYTHON3 = r'''
+$Env:RUSTUP_HOME = "C:\hgdev\rustup"
+$Env:CARGO_HOME = "C:\hgdev\cargo"
+Set-Location C:\hgdev\src
+C:\hgdev\python37-x64\python.exe contrib\packaging\packaging.py wix --pyoxidizer-target {pyoxidizer_target} --version {version}
+if ($LASTEXITCODE -ne 0) {{
+ throw "process exited non-0: $LASTEXITCODE"
+}}
+'''
+
+BUILD_WIX_PYTHON2 = r'''
Set-Location C:\hgdev\src
$python = "C:\hgdev\python27-{arch}\python.exe"
C:\hgdev\python37-x64\python.exe contrib\packaging\packaging.py wix --python $python {extra_args}
@@ -122,8 +132,11 @@
EXE_FILENAME_PYTHON2_X64 = 'Mercurial-{version}-x64-python2.exe'
EXE_FILENAME_PYTHON3_X86 = 'Mercurial-{version}-x86.exe'
EXE_FILENAME_PYTHON3_X64 = 'Mercurial-{version}-x64.exe'
-X86_MSI_FILENAME = 'mercurial-{version}-x86-python2.msi'
-X64_MSI_FILENAME = 'mercurial-{version}-x64-python2.msi'
+
+MSI_FILENAME_PYTHON2_X86 = 'mercurial-{version}-x86-python2.msi'
+MSI_FILENAME_PYTHON2_X64 = 'mercurial-{version}-x64-python2.msi'
+MSI_FILENAME_PYTHON3_X86 = 'mercurial-{version}-x86.msi'
+MSI_FILENAME_PYTHON3_X64 = 'mercurial-{version}-x64.msi'
MERCURIAL_SCM_BASE_URL = 'https://mercurial-scm.org/release/windows'
@@ -147,11 +160,21 @@
'Mercurial {version} Inno Setup installer - x64 Windows (Python 3) '
'- does not require admin rights'
)
-X86_MSI_DESCRIPTION = (
- 'Mercurial {version} MSI installer - x86 Windows ' '- requires admin rights'
+MSI_PYTHON2_X86_DESCRIPTION = (
+ 'Mercurial {version} MSI installer - x86 Windows (Python 2) '
+ '- requires admin rights'
+)
+MSI_PYTHON2_X64_DESCRIPTION = (
+ 'Mercurial {version} MSI installer - x64 Windows (Python 2) '
+ '- requires admin rights'
)
-X64_MSI_DESCRIPTION = (
- 'Mercurial {version} MSI installer - x64 Windows ' '- requires admin rights'
+MSI_PYTHON3_X86_DESCRIPTION = (
+ 'Mercurial {version} MSI installer - x86 Windows (Python 3) '
+ '- requires admin rights'
+)
+MSI_PYTHON3_X64_DESCRIPTION = (
+ 'Mercurial {version} MSI installer - x64 Windows (Python 3) '
+ '- requires admin rights'
)
@@ -375,20 +398,44 @@
def build_wix_installer(
- winrm_client, arch: str, dest_path: pathlib.Path, version=None
+ winrm_client,
+ python_version: int,
+ arch: str,
+ dest_path: pathlib.Path,
+ version=None,
):
"""Build the WiX installer on a remote machine.
Using a WinRM client, remote commands are executed to build a WiX installer.
"""
- print('Building WiX installer for %s' % arch)
- extra_args = []
- if version:
- extra_args.extend(['--version', version])
+ print('Building WiX installer for Python %d %s' % (python_version, arch))
+
+ if python_version == 3:
+ # TODO fix this limitation in packaging code
+ if not version:
+ raise Exception(
+ "version string is required when building for Python 3"
+ )
- ps = get_vc_prefix(arch) + BUILD_WIX.format(
- arch=arch, extra_args=' '.join(extra_args)
- )
+ if arch == "x86":
+ target_triple = "i686-pc-windows-msvc"
+ elif arch == "x64":
+ target_triple = "x86_64-pc-windows-msvc"
+ else:
+ raise Exception("unhandled arch: %s" % arch)
+
+ ps = BUILD_WIX_PYTHON3.format(
+ pyoxidizer_target=target_triple, version=version,
+ )
+ else:
+ extra_args = []
+ if version:
+ extra_args.extend(['--version', version])
+
+ ps = get_vc_prefix(arch) + BUILD_WIX_PYTHON2.format(
+ arch=arch, extra_args=' '.join(extra_args)
+ )
+
run_powershell(winrm_client, ps)
copy_latest_dist(winrm_client, '*.msi', dest_path)
@@ -439,8 +486,10 @@
dist_path / EXE_FILENAME_PYTHON2_X64.format(version=version),
dist_path / EXE_FILENAME_PYTHON3_X86.format(version=version),
dist_path / EXE_FILENAME_PYTHON3_X64.format(version=version),
- dist_path / X86_MSI_FILENAME.format(version=version),
- dist_path / X64_MSI_FILENAME.format(version=version),
+ dist_path / MSI_FILENAME_PYTHON2_X86.format(version=version),
+ dist_path / MSI_FILENAME_PYTHON2_X64.format(version=version),
+ dist_path / MSI_FILENAME_PYTHON3_X86.format(version=version),
+ dist_path / MSI_FILENAME_PYTHON3_X64.format(version=version),
)
@@ -449,8 +498,10 @@
python2_x64_exe_filename = EXE_FILENAME_PYTHON2_X64.format(version=version)
python3_x86_exe_filename = EXE_FILENAME_PYTHON3_X86.format(version=version)
python3_x64_exe_filename = EXE_FILENAME_PYTHON3_X64.format(version=version)
- x86_msi_filename = X86_MSI_FILENAME.format(version=version)
- x64_msi_filename = X64_MSI_FILENAME.format(version=version)
+ python2_x86_msi_filename = MSI_FILENAME_PYTHON2_X86.format(version=version)
+ python2_x64_msi_filename = MSI_FILENAME_PYTHON2_X64.format(version=version)
+ python3_x86_msi_filename = MSI_FILENAME_PYTHON3_X86.format(version=version)
+ python3_x64_msi_filename = MSI_FILENAME_PYTHON3_X64.format(version=version)
entries = (
(
@@ -485,15 +536,29 @@
'10',
version,
X86_USER_AGENT_PATTERN,
- '%s/%s' % (MERCURIAL_SCM_BASE_URL, x86_msi_filename),
- X86_MSI_DESCRIPTION.format(version=version),
+ '%s/%s' % (MERCURIAL_SCM_BASE_URL, python3_x86_msi_filename),
+ MSI_PYTHON3_X86_DESCRIPTION.format(version=version),
),
(
'10',
version,
X64_USER_AGENT_PATTERN,
- '%s/%s' % (MERCURIAL_SCM_BASE_URL, x64_msi_filename),
- X64_MSI_DESCRIPTION.format(version=version),
+ '%s/%s' % (MERCURIAL_SCM_BASE_URL, python3_x64_msi_filename),
+ MSI_PYTHON3_X64_DESCRIPTION.format(version=version),
+ ),
+ (
+ '9',
+ version,
+ X86_USER_AGENT_PATTERN,
+ '%s/%s' % (MERCURIAL_SCM_BASE_URL, python2_x86_msi_filename),
+ MSI_PYTHON2_X86_DESCRIPTION.format(version=version),
+ ),
+ (
+ '9',
+ version,
+ X64_USER_AGENT_PATTERN,
+ '%s/%s' % (MERCURIAL_SCM_BASE_URL, python2_x64_msi_filename),
+ MSI_PYTHON2_X64_DESCRIPTION.format(version=version),
),
)