##// END OF EJS Templates
packaging: move Inno Setup core logic into a module...
Gregory Szorc -
r42077:dc7827a9 default
parent child Browse files
Show More
@@ -1,23 +1,27 b''
1 #!/usr/bin/env python3
1 # inno.py - Inno Setup functionality.
2 # build.py - Inno installer build script.
3 #
2 #
4 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
5 #
4 #
6 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
8
7
9 # This script automates the building of the Inno MSI installer for Mercurial.
10
11 # no-check-code because Python 3 native.
8 # no-check-code because Python 3 native.
12
9
13 import argparse
14 import os
10 import os
15 import pathlib
11 import pathlib
16 import shutil
12 import shutil
17 import subprocess
13 import subprocess
18 import sys
19 import tempfile
14 import tempfile
20
15
16 from .downloads import (
17 download_entry,
18 )
19 from .util import (
20 extract_tar_to_directory,
21 extract_zip_to_directory,
22 find_vc_runtime_files,
23 )
24
21
25
22 PRINT_PYTHON_INFO = '''
26 PRINT_PYTHON_INFO = '''
23 import platform, sys; print("%s:%d" % (platform.architecture()[0], sys.version_info[0]))
27 import platform, sys; print("%s:%d" % (platform.architecture()[0], sys.version_info[0]))
@@ -35,17 +39,8 b' def build(source_dir: pathlib.Path, buil'
35 for finding the Python 2.7 toolchain. So, we require the environment
39 for finding the Python 2.7 toolchain. So, we require the environment
36 to already be configured with an active toolchain.
40 to already be configured with an active toolchain.
37 """
41 """
38 from hgpackaging.downloads import (
42 if not iscc_exe.exists():
39 download_entry,
43 raise Exception('%s does not exist' % iscc_exe)
40 )
41 from hgpackaging.util import (
42 extract_tar_to_directory,
43 extract_zip_to_directory,
44 find_vc_runtime_files,
45 )
46
47 if not iscc.exists():
48 raise Exception('%s does not exist' % iscc)
49
44
50 if 'VCINSTALLDIR' not in os.environ:
45 if 'VCINSTALLDIR' not in os.environ:
51 raise Exception('not running from a Visual C++ build environment; '
46 raise Exception('not running from a Visual C++ build environment; '
@@ -172,33 +167,3 b' def build(source_dir: pathlib.Path, buil'
172 args.append('contrib/packaging/inno/mercurial.iss')
167 args.append('contrib/packaging/inno/mercurial.iss')
173
168
174 subprocess.run(args, cwd=str(source_dir), check=True)
169 subprocess.run(args, cwd=str(source_dir), check=True)
175
176
177 if __name__ == '__main__':
178 parser = argparse.ArgumentParser()
179
180 parser.add_argument('--python',
181 required=True,
182 help='path to python.exe to use')
183 parser.add_argument('--iscc',
184 help='path to iscc.exe to use')
185 parser.add_argument('--version',
186 help='Mercurial version string to use '
187 '(detected from __version__.py if not defined')
188
189 args = parser.parse_args()
190
191 if args.iscc:
192 iscc = pathlib.Path(args.iscc)
193 else:
194 iscc = (pathlib.Path(os.environ['ProgramFiles(x86)']) / 'Inno Setup 5' /
195 'ISCC.exe')
196
197 here = pathlib.Path(os.path.abspath(os.path.dirname(__file__)))
198 source_dir = here.parent.parent.parent
199 build_dir = source_dir / 'build'
200
201 sys.path.insert(0, str(source_dir / 'contrib' / 'packaging'))
202
203 build(source_dir, build_dir, pathlib.Path(args.python), iscc,
204 version=args.version)
@@ -13,165 +13,7 b''
13 import argparse
13 import argparse
14 import os
14 import os
15 import pathlib
15 import pathlib
16 import shutil
17 import subprocess
18 import sys
16 import sys
19 import tempfile
20
21
22 PRINT_PYTHON_INFO = '''
23 import platform, sys; print("%s:%d" % (platform.architecture()[0], sys.version_info[0]))
24 '''.strip()
25
26
27 def build(source_dir: pathlib.Path, build_dir: pathlib.Path,
28 python_exe: pathlib.Path, iscc_exe: pathlib.Path,
29 version=None):
30 """Build the Inno installer.
31
32 Build files will be placed in ``build_dir``.
33
34 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
35 for finding the Python 2.7 toolchain. So, we require the environment
36 to already be configured with an active toolchain.
37 """
38 from hgpackaging.downloads import (
39 download_entry,
40 )
41 from hgpackaging.util import (
42 extract_tar_to_directory,
43 extract_zip_to_directory,
44 find_vc_runtime_files,
45 )
46
47 if not iscc.exists():
48 raise Exception('%s does not exist' % iscc)
49
50 if 'VCINSTALLDIR' not in os.environ:
51 raise Exception('not running from a Visual C++ build environment; '
52 'execute the "Visual C++ <version> Command Prompt" '
53 'application shortcut or a vcsvarsall.bat file')
54
55 # Identity x86/x64 and validate the environment matches the Python
56 # architecture.
57 vc_x64 = r'\x64' in os.environ['LIB']
58
59 res = subprocess.run(
60 [str(python_exe), '-c', PRINT_PYTHON_INFO],
61 capture_output=True, check=True)
62
63 py_arch, py_version = res.stdout.decode('utf-8').split(':')
64 py_version = int(py_version)
65
66 if vc_x64:
67 if py_arch != '64bit':
68 raise Exception('architecture mismatch: Visual C++ environment '
69 'is configured for 64-bit but Python is 32-bit')
70 else:
71 if py_arch != '32bit':
72 raise Exception('architecture mismatch: Visual C++ environment '
73 'is configured for 32-bit but Python is 64-bit')
74
75 if py_version != 2:
76 raise Exception('Only Python 2 is currently supported')
77
78 build_dir.mkdir(exist_ok=True)
79
80 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
81 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
82 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
83 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
84
85 venv_path = build_dir / ('venv-inno-%s' % ('x64' if vc_x64 else 'x86'))
86
87 gettext_root = build_dir / (
88 'gettext-win-%s' % gettext_entry['version'])
89
90 if not gettext_root.exists():
91 extract_zip_to_directory(gettext_pkg, gettext_root)
92 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
93
94 with tempfile.TemporaryDirectory() as td:
95 td = pathlib.Path(td)
96
97 # This assumes Python 2.
98 extract_tar_to_directory(virtualenv_pkg, td)
99 extract_zip_to_directory(py2exe_pkg, td)
100
101 virtualenv_src_path = td / ('virtualenv-%s' %
102 virtualenv_entry['version'])
103 py2exe_source_path = td / ('py2exe-%s' %
104 py2exe_entry['version'])
105
106 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
107
108 if not venv_path.exists():
109 print('creating virtualenv with dependencies')
110 subprocess.run(
111 [str(python_exe), str(virtualenv_py), str(venv_path)],
112 check=True)
113
114 venv_python = venv_path / 'Scripts' / 'python.exe'
115 venv_pip = venv_path / 'Scripts' / 'pip.exe'
116
117 requirements_txt = (source_dir / 'contrib' / 'packaging' /
118 'inno' / 'requirements.txt')
119 subprocess.run([str(venv_pip), 'install', '-r', str(requirements_txt)],
120 check=True)
121
122 # Force distutils to use VC++ settings from environment, which was
123 # validated above.
124 env = dict(os.environ)
125 env['DISTUTILS_USE_SDK'] = '1'
126 env['MSSdk'] = '1'
127
128 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
129 if not py2exe_py_path.exists():
130 print('building py2exe')
131 subprocess.run([str(venv_python), 'setup.py', 'install'],
132 cwd=py2exe_source_path,
133 env=env,
134 check=True)
135
136 # Register location of msgfmt and other binaries.
137 env['PATH'] = '%s%s%s' % (
138 env['PATH'], os.pathsep, str(gettext_root / 'bin'))
139
140 print('building Mercurial')
141 subprocess.run(
142 [str(venv_python), 'setup.py',
143 'py2exe', '-b', '3' if vc_x64 else '2',
144 'build_doc', '--html'],
145 cwd=str(source_dir),
146 env=env,
147 check=True)
148
149 # hg.exe depends on VC9 runtime DLLs. Copy those into place.
150 for f in find_vc_runtime_files(vc_x64):
151 if f.name.endswith('.manifest'):
152 basename = 'Microsoft.VC90.CRT.manifest'
153 else:
154 basename = f.name
155
156 dest_path = source_dir / 'dist' / basename
157
158 print('copying %s to %s' % (f, dest_path))
159 shutil.copyfile(f, dest_path)
160
161 print('creating installer')
162
163 args = [str(iscc_exe)]
164
165 if vc_x64:
166 args.append('/dARCH=x64')
167
168 if version:
169 args.append('/dVERSION=%s' % version)
170
171 args.append('/Odist')
172 args.append('contrib/packaging/inno/mercurial.iss')
173
174 subprocess.run(args, cwd=str(source_dir), check=True)
175
17
176
18
177 if __name__ == '__main__':
19 if __name__ == '__main__':
@@ -200,5 +42,7 b" if __name__ == '__main__':"
200
42
201 sys.path.insert(0, str(source_dir / 'contrib' / 'packaging'))
43 sys.path.insert(0, str(source_dir / 'contrib' / 'packaging'))
202
44
45 from hgpackaging.inno import build
46
203 build(source_dir, build_dir, pathlib.Path(args.python), iscc,
47 build(source_dir, build_dir, pathlib.Path(args.python), iscc,
204 version=args.version)
48 version=args.version)
@@ -13,6 +13,7 b' New errors are not allowed. Warnings are'
13 > -X mercurial/thirdparty \
13 > -X mercurial/thirdparty \
14 > | sed 's-\\-/-g' | "$check_code" --warnings --per-file=0 - || false
14 > | sed 's-\\-/-g' | "$check_code" --warnings --per-file=0 - || false
15 Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob)
15 Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob)
16 Skipping contrib/packaging/hgpackaging/inno.py it has no-che?k-code (glob)
16 Skipping contrib/packaging/hgpackaging/util.py it has no-che?k-code (glob)
17 Skipping contrib/packaging/hgpackaging/util.py it has no-che?k-code (glob)
17 Skipping contrib/packaging/inno/build.py it has no-che?k-code (glob)
18 Skipping contrib/packaging/inno/build.py it has no-che?k-code (glob)
18 Skipping i18n/polib.py it has no-che?k-code (glob)
19 Skipping i18n/polib.py it has no-che?k-code (glob)
General Comments 0
You need to be logged in to leave comments. Login now