diff --git a/contrib/automation/hgautomation/cli.py b/contrib/automation/hgautomation/cli.py --- a/contrib/automation/hgautomation/cli.py +++ b/contrib/automation/hgautomation/cli.py @@ -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'}, diff --git a/contrib/automation/hgautomation/windows.py b/contrib/automation/hgautomation/windows.py --- a/contrib/automation/hgautomation/windows.py +++ b/contrib/automation/hgautomation/windows.py @@ -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), ), )