contrib/packaging/hgpackaging/py2exe.py
author Gregory Szorc <gregory.szorc@gmail.com>
Thu, 07 Mar 2019 15:43:54 -0800
changeset 41915 a2e191a937a9
parent 41914 contrib/packaging/hgpackaging/inno.py@7d1211168863
child 41916 260305e8ddbd
permissions -rw-r--r--
packaging: extract py2exe functionality to own module py2exe builds are shared between Inno Setup and WIX. We'll want the logic for performing py2exe builds to be reusable across the code for both installers. This commit extracts the py2exe-specific functionality into its own module. There's definitely room to customize things further. This will be done in future commits, as necessary. (I'm not even sure what customizations WIX will require yet. Presumably a lot.) Differential Revision: https://phab.mercurial-scm.org/D6091
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
41915
a2e191a937a9 packaging: extract py2exe functionality to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41914
diff changeset
     1
# py2exe.py - Functionality for performing py2exe builds.
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     2
#
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     3
# Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     4
#
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     7
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     8
# no-check-code because Python 3 native.
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     9
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    10
import os
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    11
import pathlib
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    12
import subprocess
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    13
41911
dc7827a9ba64 packaging: move Inno Setup core logic into a module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41910
diff changeset
    14
from .downloads import (
dc7827a9ba64 packaging: move Inno Setup core logic into a module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41910
diff changeset
    15
    download_entry,
dc7827a9ba64 packaging: move Inno Setup core logic into a module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41910
diff changeset
    16
)
dc7827a9ba64 packaging: move Inno Setup core logic into a module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41910
diff changeset
    17
from .util import (
dc7827a9ba64 packaging: move Inno Setup core logic into a module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41910
diff changeset
    18
    extract_tar_to_directory,
dc7827a9ba64 packaging: move Inno Setup core logic into a module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41910
diff changeset
    19
    extract_zip_to_directory,
41914
7d1211168863 packaging: extract python exe info to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41913
diff changeset
    20
    python_exe_info,
41911
dc7827a9ba64 packaging: move Inno Setup core logic into a module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41910
diff changeset
    21
)
dc7827a9ba64 packaging: move Inno Setup core logic into a module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41910
diff changeset
    22
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    23
41915
a2e191a937a9 packaging: extract py2exe functionality to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41914
diff changeset
    24
def build_py2exe(source_dir: pathlib.Path, build_dir: pathlib.Path,
a2e191a937a9 packaging: extract py2exe functionality to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41914
diff changeset
    25
                 python_exe: pathlib.Path, build_name: str,
a2e191a937a9 packaging: extract py2exe functionality to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41914
diff changeset
    26
                 venv_requirements_txt: pathlib.Path):
a2e191a937a9 packaging: extract py2exe functionality to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41914
diff changeset
    27
    """Build Mercurial with py2exe.
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    28
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    29
    Build files will be placed in ``build_dir``.
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    30
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    31
    py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    32
    for finding the Python 2.7 toolchain. So, we require the environment
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    33
    to already be configured with an active toolchain.
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    34
    """
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    35
    if 'VCINSTALLDIR' not in os.environ:
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    36
        raise Exception('not running from a Visual C++ build environment; '
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    37
                        'execute the "Visual C++ <version> Command Prompt" '
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    38
                        'application shortcut or a vcsvarsall.bat file')
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    39
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    40
    # Identity x86/x64 and validate the environment matches the Python
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    41
    # architecture.
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    42
    vc_x64 = r'\x64' in os.environ['LIB']
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    43
41914
7d1211168863 packaging: extract python exe info to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41913
diff changeset
    44
    py_info = python_exe_info(python_exe)
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    45
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    46
    if vc_x64:
41914
7d1211168863 packaging: extract python exe info to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41913
diff changeset
    47
        if py_info['arch'] != '64bit':
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    48
            raise Exception('architecture mismatch: Visual C++ environment '
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    49
                            'is configured for 64-bit but Python is 32-bit')
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    50
    else:
41914
7d1211168863 packaging: extract python exe info to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41913
diff changeset
    51
        if py_info['arch'] != '32bit':
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    52
            raise Exception('architecture mismatch: Visual C++ environment '
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    53
                            'is configured for 32-bit but Python is 64-bit')
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    54
41914
7d1211168863 packaging: extract python exe info to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41913
diff changeset
    55
    if py_info['py3']:
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    56
        raise Exception('Only Python 2 is currently supported')
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    57
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    58
    build_dir.mkdir(exist_ok=True)
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    59
41909
1e8fb6522fee packaging: move DOWNLOADS dict to hgpackaging.downloads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41908
diff changeset
    60
    gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
1e8fb6522fee packaging: move DOWNLOADS dict to hgpackaging.downloads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41908
diff changeset
    61
    gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
1e8fb6522fee packaging: move DOWNLOADS dict to hgpackaging.downloads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41908
diff changeset
    62
    virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
1e8fb6522fee packaging: move DOWNLOADS dict to hgpackaging.downloads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41908
diff changeset
    63
    py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    64
41915
a2e191a937a9 packaging: extract py2exe functionality to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41914
diff changeset
    65
    venv_path = build_dir / ('venv-%s-%s' % (build_name,
a2e191a937a9 packaging: extract py2exe functionality to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41914
diff changeset
    66
                                             'x64' if vc_x64 else 'x86'))
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    67
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    68
    gettext_root = build_dir / (
41909
1e8fb6522fee packaging: move DOWNLOADS dict to hgpackaging.downloads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41908
diff changeset
    69
        'gettext-win-%s' % gettext_entry['version'])
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    70
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    71
    if not gettext_root.exists():
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    72
        extract_zip_to_directory(gettext_pkg, gettext_root)
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    73
        extract_zip_to_directory(gettext_dep_pkg, gettext_root)
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    74
41912
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    75
    # This assumes Python 2. We don't need virtualenv on Python 3.
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    76
    virtualenv_src_path = build_dir / (
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    77
        'virtualenv-%s' % virtualenv_entry['version'])
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    78
    virtualenv_py = virtualenv_src_path / 'virtualenv.py'
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    79
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    80
    if not virtualenv_src_path.exists():
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    81
        extract_tar_to_directory(virtualenv_pkg, build_dir)
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    82
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    83
    py2exe_source_path = build_dir / ('py2exe-%s' % py2exe_entry['version'])
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    84
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    85
    if not py2exe_source_path.exists():
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    86
        extract_zip_to_directory(py2exe_pkg, build_dir)
d4bf73ea06de packaging: extract virtualenv and py2exe to build directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41911
diff changeset
    87
41913
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
    88
    if not venv_path.exists():
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
    89
        print('creating virtualenv with dependencies')
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
    90
        subprocess.run(
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
    91
            [str(python_exe), str(virtualenv_py), str(venv_path)],
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
    92
            check=True)
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
    93
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
    94
    venv_python = venv_path / 'Scripts' / 'python.exe'
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
    95
    venv_pip = venv_path / 'Scripts' / 'pip.exe'
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    96
41915
a2e191a937a9 packaging: extract py2exe functionality to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41914
diff changeset
    97
    subprocess.run([str(venv_pip), 'install', '-r', str(venv_requirements_txt)],
41913
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
    98
                   check=True)
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    99
41913
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   100
    # Force distutils to use VC++ settings from environment, which was
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   101
    # validated above.
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   102
    env = dict(os.environ)
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   103
    env['DISTUTILS_USE_SDK'] = '1'
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   104
    env['MSSdk'] = '1'
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   105
41913
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   106
    py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   107
    if not py2exe_py_path.exists():
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   108
        print('building py2exe')
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   109
        subprocess.run([str(venv_python), 'setup.py', 'install'],
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   110
                       cwd=py2exe_source_path,
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   111
                       env=env,
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   112
                       check=True)
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   113
41913
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   114
    # Register location of msgfmt and other binaries.
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   115
    env['PATH'] = '%s%s%s' % (
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   116
        env['PATH'], os.pathsep, str(gettext_root / 'bin'))
41853
d7dc4ac1ff84 inno: script to automate building Inno installer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   117
41913
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   118
    print('building Mercurial')
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   119
    subprocess.run(
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   120
        [str(venv_python), 'setup.py',
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   121
         'py2exe', '-b', '3' if vc_x64 else '2',
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   122
         'build_doc', '--html'],
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   123
        cwd=str(source_dir),
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   124
        env=env,
5e923355c595 packaging: don't use temporary directory
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41912
diff changeset
   125
        check=True)