##// END OF EJS Templates
packaging: extract python exe info to own function...
Gregory Szorc -
r42080:7d121116 default
parent child Browse files
Show More
@@ -1,167 +1,158
1 1 # inno.py - Inno Setup functionality.
2 2 #
3 3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 # no-check-code because Python 3 native.
9 9
10 10 import os
11 11 import pathlib
12 12 import shutil
13 13 import subprocess
14 14
15 15 from .downloads import (
16 16 download_entry,
17 17 )
18 18 from .util import (
19 19 extract_tar_to_directory,
20 20 extract_zip_to_directory,
21 21 find_vc_runtime_files,
22 python_exe_info,
22 23 )
23 24
24 25
25 PRINT_PYTHON_INFO = '''
26 import platform, sys; print("%s:%d" % (platform.architecture()[0], sys.version_info[0]))
27 '''.strip()
28
29
30 26 def build(source_dir: pathlib.Path, build_dir: pathlib.Path,
31 27 python_exe: pathlib.Path, iscc_exe: pathlib.Path,
32 28 version=None):
33 29 """Build the Inno installer.
34 30
35 31 Build files will be placed in ``build_dir``.
36 32
37 33 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
38 34 for finding the Python 2.7 toolchain. So, we require the environment
39 35 to already be configured with an active toolchain.
40 36 """
41 37 if not iscc_exe.exists():
42 38 raise Exception('%s does not exist' % iscc_exe)
43 39
44 40 if 'VCINSTALLDIR' not in os.environ:
45 41 raise Exception('not running from a Visual C++ build environment; '
46 42 'execute the "Visual C++ <version> Command Prompt" '
47 43 'application shortcut or a vcsvarsall.bat file')
48 44
49 45 # Identity x86/x64 and validate the environment matches the Python
50 46 # architecture.
51 47 vc_x64 = r'\x64' in os.environ['LIB']
52 48
53 res = subprocess.run(
54 [str(python_exe), '-c', PRINT_PYTHON_INFO],
55 capture_output=True, check=True)
56
57 py_arch, py_version = res.stdout.decode('utf-8').split(':')
58 py_version = int(py_version)
49 py_info = python_exe_info(python_exe)
59 50
60 51 if vc_x64:
61 if py_arch != '64bit':
52 if py_info['arch'] != '64bit':
62 53 raise Exception('architecture mismatch: Visual C++ environment '
63 54 'is configured for 64-bit but Python is 32-bit')
64 55 else:
65 if py_arch != '32bit':
56 if py_info['arch'] != '32bit':
66 57 raise Exception('architecture mismatch: Visual C++ environment '
67 58 'is configured for 32-bit but Python is 64-bit')
68 59
69 if py_version != 2:
60 if py_info['py3']:
70 61 raise Exception('Only Python 2 is currently supported')
71 62
72 63 build_dir.mkdir(exist_ok=True)
73 64
74 65 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
75 66 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
76 67 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
77 68 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
78 69
79 70 venv_path = build_dir / ('venv-inno-%s' % ('x64' if vc_x64 else 'x86'))
80 71
81 72 gettext_root = build_dir / (
82 73 'gettext-win-%s' % gettext_entry['version'])
83 74
84 75 if not gettext_root.exists():
85 76 extract_zip_to_directory(gettext_pkg, gettext_root)
86 77 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
87 78
88 79 # This assumes Python 2. We don't need virtualenv on Python 3.
89 80 virtualenv_src_path = build_dir / (
90 81 'virtualenv-%s' % virtualenv_entry['version'])
91 82 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
92 83
93 84 if not virtualenv_src_path.exists():
94 85 extract_tar_to_directory(virtualenv_pkg, build_dir)
95 86
96 87 py2exe_source_path = build_dir / ('py2exe-%s' % py2exe_entry['version'])
97 88
98 89 if not py2exe_source_path.exists():
99 90 extract_zip_to_directory(py2exe_pkg, build_dir)
100 91
101 92 if not venv_path.exists():
102 93 print('creating virtualenv with dependencies')
103 94 subprocess.run(
104 95 [str(python_exe), str(virtualenv_py), str(venv_path)],
105 96 check=True)
106 97
107 98 venv_python = venv_path / 'Scripts' / 'python.exe'
108 99 venv_pip = venv_path / 'Scripts' / 'pip.exe'
109 100
110 101 requirements_txt = (source_dir / 'contrib' / 'packaging' /
111 102 'inno' / 'requirements.txt')
112 103 subprocess.run([str(venv_pip), 'install', '-r', str(requirements_txt)],
113 104 check=True)
114 105
115 106 # Force distutils to use VC++ settings from environment, which was
116 107 # validated above.
117 108 env = dict(os.environ)
118 109 env['DISTUTILS_USE_SDK'] = '1'
119 110 env['MSSdk'] = '1'
120 111
121 112 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
122 113 if not py2exe_py_path.exists():
123 114 print('building py2exe')
124 115 subprocess.run([str(venv_python), 'setup.py', 'install'],
125 116 cwd=py2exe_source_path,
126 117 env=env,
127 118 check=True)
128 119
129 120 # Register location of msgfmt and other binaries.
130 121 env['PATH'] = '%s%s%s' % (
131 122 env['PATH'], os.pathsep, str(gettext_root / 'bin'))
132 123
133 124 print('building Mercurial')
134 125 subprocess.run(
135 126 [str(venv_python), 'setup.py',
136 127 'py2exe', '-b', '3' if vc_x64 else '2',
137 128 'build_doc', '--html'],
138 129 cwd=str(source_dir),
139 130 env=env,
140 131 check=True)
141 132
142 133 # hg.exe depends on VC9 runtime DLLs. Copy those into place.
143 134 for f in find_vc_runtime_files(vc_x64):
144 135 if f.name.endswith('.manifest'):
145 136 basename = 'Microsoft.VC90.CRT.manifest'
146 137 else:
147 138 basename = f.name
148 139
149 140 dest_path = source_dir / 'dist' / basename
150 141
151 142 print('copying %s to %s' % (f, dest_path))
152 143 shutil.copyfile(f, dest_path)
153 144
154 145 print('creating installer')
155 146
156 147 args = [str(iscc_exe)]
157 148
158 149 if vc_x64:
159 150 args.append('/dARCH=x64')
160 151
161 152 if version:
162 153 args.append('/dVERSION=%s' % version)
163 154
164 155 args.append('/Odist')
165 156 args.append('contrib/packaging/inno/mercurial.iss')
166 157
167 158 subprocess.run(args, cwd=str(source_dir), check=True)
@@ -1,48 +1,73
1 1 # util.py - Common packaging utility code.
2 2 #
3 3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 # no-check-code because Python 3 native.
9 9
10 import distutils.version
10 11 import os
11 12 import pathlib
13 import subprocess
12 14 import tarfile
13 15 import zipfile
14 16
15 17
16 18 def extract_tar_to_directory(source: pathlib.Path, dest: pathlib.Path):
17 19 with tarfile.open(source, 'r') as tf:
18 20 tf.extractall(dest)
19 21
20 22
21 23 def extract_zip_to_directory(source: pathlib.Path, dest: pathlib.Path):
22 24 with zipfile.ZipFile(source, 'r') as zf:
23 25 zf.extractall(dest)
24 26
25 27
26 28 def find_vc_runtime_files(x64=False):
27 29 """Finds Visual C++ Runtime DLLs to include in distribution."""
28 30 winsxs = pathlib.Path(os.environ['SYSTEMROOT']) / 'WinSxS'
29 31
30 32 prefix = 'amd64' if x64 else 'x86'
31 33
32 34 candidates = sorted(p for p in os.listdir(winsxs)
33 35 if p.lower().startswith('%s_microsoft.vc90.crt_' % prefix))
34 36
35 37 for p in candidates:
36 38 print('found candidate VC runtime: %s' % p)
37 39
38 40 # Take the newest version.
39 41 version = candidates[-1]
40 42
41 43 d = winsxs / version
42 44
43 45 return [
44 46 d / 'msvcm90.dll',
45 47 d / 'msvcp90.dll',
46 48 d / 'msvcr90.dll',
47 49 winsxs / 'Manifests' / ('%s.manifest' % version),
48 50 ]
51
52
53 PRINT_PYTHON_INFO = '''
54 import platform; print("%s:%s" % (platform.architecture()[0], platform.python_version()))
55 '''.strip()
56
57
58 def python_exe_info(python_exe: pathlib.Path):
59 """Obtain information about a Python executable."""
60
61 res = subprocess.run(
62 [str(python_exe), '-c', PRINT_PYTHON_INFO],
63 capture_output=True, check=True)
64
65 arch, version = res.stdout.decode('utf-8').split(':')
66
67 version = distutils.version.LooseVersion(version)
68
69 return {
70 'arch': arch,
71 'version': version,
72 'py3': version >= distutils.version.LooseVersion('3'),
73 }
General Comments 0
You need to be logged in to leave comments. Login now