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