##// END OF EJS Templates
packaging: remove hg-ssh.8.html from Inno installer...
Gregory Szorc -
r44005:a2f28a87 default
parent child Browse files
Show More
@@ -1,214 +1,226 b''
1 # py2exe.py - Functionality for performing py2exe builds.
1 # py2exe.py - Functionality for performing py2exe builds.
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 subprocess
12 import subprocess
13
13
14 from .downloads import download_entry
14 from .downloads import download_entry
15 from .util import (
15 from .util import (
16 extract_tar_to_directory,
16 extract_tar_to_directory,
17 extract_zip_to_directory,
17 extract_zip_to_directory,
18 process_install_rules,
18 process_install_rules,
19 python_exe_info,
19 python_exe_info,
20 )
20 )
21
21
22
22
23 STAGING_RULES = [
23 STAGING_RULES = [
24 ('contrib/bash_completion', 'Contrib/'),
24 ('contrib/bash_completion', 'Contrib/'),
25 ('contrib/hgk', 'Contrib/hgk.tcl'),
25 ('contrib/hgk', 'Contrib/hgk.tcl'),
26 ('contrib/hgweb.fcgi', 'Contrib/'),
26 ('contrib/hgweb.fcgi', 'Contrib/'),
27 ('contrib/hgweb.wsgi', 'Contrib/'),
27 ('contrib/hgweb.wsgi', 'Contrib/'),
28 ('contrib/logo-droplets.svg', 'Contrib/'),
28 ('contrib/logo-droplets.svg', 'Contrib/'),
29 ('contrib/mercurial.el', 'Contrib/'),
29 ('contrib/mercurial.el', 'Contrib/'),
30 ('contrib/mq.el', 'Contrib/'),
30 ('contrib/mq.el', 'Contrib/'),
31 ('contrib/tcsh_completion', 'Contrib/'),
31 ('contrib/tcsh_completion', 'Contrib/'),
32 ('contrib/tcsh_completion_build.sh', 'Contrib/'),
32 ('contrib/tcsh_completion_build.sh', 'Contrib/'),
33 ('contrib/vim/*', 'Contrib/Vim/'),
33 ('contrib/vim/*', 'Contrib/Vim/'),
34 ('contrib/win32/postinstall.txt', 'ReleaseNotes.txt'),
34 ('contrib/win32/postinstall.txt', 'ReleaseNotes.txt'),
35 ('contrib/win32/ReadMe.html', 'ReadMe.html'),
35 ('contrib/win32/ReadMe.html', 'ReadMe.html'),
36 ('contrib/xml.rnc', 'Contrib/'),
36 ('contrib/xml.rnc', 'Contrib/'),
37 ('contrib/zsh_completion', 'Contrib/'),
37 ('contrib/zsh_completion', 'Contrib/'),
38 ('dist/hg.exe', './'),
38 ('dist/hg.exe', './'),
39 ('dist/lib/*.dll', 'lib/'),
39 ('dist/lib/*.dll', 'lib/'),
40 ('dist/lib/*.pyd', 'lib/'),
40 ('dist/lib/*.pyd', 'lib/'),
41 ('dist/lib/library.zip', 'lib/'),
41 ('dist/lib/library.zip', 'lib/'),
42 ('dist/Microsoft.VC*.CRT.manifest', './'),
42 ('dist/Microsoft.VC*.CRT.manifest', './'),
43 ('dist/msvc*.dll', './'),
43 ('dist/msvc*.dll', './'),
44 ('dist/python*.dll', './'),
44 ('dist/python*.dll', './'),
45 ('doc/*.html', 'doc/'),
45 ('doc/*.html', 'doc/'),
46 ('doc/style.css', 'doc/'),
46 ('doc/style.css', 'doc/'),
47 ('mercurial/help/**/*.txt', 'help/'),
47 ('mercurial/help/**/*.txt', 'help/'),
48 ('mercurial/default.d/*.rc', 'hgrc.d/'),
48 ('mercurial/default.d/*.rc', 'hgrc.d/'),
49 ('mercurial/locale/**/*', 'locale/'),
49 ('mercurial/locale/**/*', 'locale/'),
50 ('mercurial/templates/**/*', 'Templates/'),
50 ('mercurial/templates/**/*', 'Templates/'),
51 ('CONTRIBUTORS', 'Contributors.txt'),
51 ('CONTRIBUTORS', 'Contributors.txt'),
52 ('COPYING', 'Copying.txt'),
52 ('COPYING', 'Copying.txt'),
53 ]
53 ]
54
54
55 # List of paths to exclude from the staging area.
56 STAGING_EXCLUDES = [
57 'doc/hg-ssh.8.html',
58 ]
59
55
60
56 def build_py2exe(
61 def build_py2exe(
57 source_dir: pathlib.Path,
62 source_dir: pathlib.Path,
58 build_dir: pathlib.Path,
63 build_dir: pathlib.Path,
59 python_exe: pathlib.Path,
64 python_exe: pathlib.Path,
60 build_name: str,
65 build_name: str,
61 venv_requirements_txt: pathlib.Path,
66 venv_requirements_txt: pathlib.Path,
62 extra_packages=None,
67 extra_packages=None,
63 extra_excludes=None,
68 extra_excludes=None,
64 extra_dll_excludes=None,
69 extra_dll_excludes=None,
65 extra_packages_script=None,
70 extra_packages_script=None,
66 ):
71 ):
67 """Build Mercurial with py2exe.
72 """Build Mercurial with py2exe.
68
73
69 Build files will be placed in ``build_dir``.
74 Build files will be placed in ``build_dir``.
70
75
71 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
76 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
72 for finding the Python 2.7 toolchain. So, we require the environment
77 for finding the Python 2.7 toolchain. So, we require the environment
73 to already be configured with an active toolchain.
78 to already be configured with an active toolchain.
74 """
79 """
75 if 'VCINSTALLDIR' not in os.environ:
80 if 'VCINSTALLDIR' not in os.environ:
76 raise Exception(
81 raise Exception(
77 'not running from a Visual C++ build environment; '
82 'not running from a Visual C++ build environment; '
78 'execute the "Visual C++ <version> Command Prompt" '
83 'execute the "Visual C++ <version> Command Prompt" '
79 'application shortcut or a vcsvarsall.bat file'
84 'application shortcut or a vcsvarsall.bat file'
80 )
85 )
81
86
82 # Identity x86/x64 and validate the environment matches the Python
87 # Identity x86/x64 and validate the environment matches the Python
83 # architecture.
88 # architecture.
84 vc_x64 = r'\x64' in os.environ['LIB']
89 vc_x64 = r'\x64' in os.environ['LIB']
85
90
86 py_info = python_exe_info(python_exe)
91 py_info = python_exe_info(python_exe)
87
92
88 if vc_x64:
93 if vc_x64:
89 if py_info['arch'] != '64bit':
94 if py_info['arch'] != '64bit':
90 raise Exception(
95 raise Exception(
91 'architecture mismatch: Visual C++ environment '
96 'architecture mismatch: Visual C++ environment '
92 'is configured for 64-bit but Python is 32-bit'
97 'is configured for 64-bit but Python is 32-bit'
93 )
98 )
94 else:
99 else:
95 if py_info['arch'] != '32bit':
100 if py_info['arch'] != '32bit':
96 raise Exception(
101 raise Exception(
97 'architecture mismatch: Visual C++ environment '
102 'architecture mismatch: Visual C++ environment '
98 'is configured for 32-bit but Python is 64-bit'
103 'is configured for 32-bit but Python is 64-bit'
99 )
104 )
100
105
101 if py_info['py3']:
106 if py_info['py3']:
102 raise Exception('Only Python 2 is currently supported')
107 raise Exception('Only Python 2 is currently supported')
103
108
104 build_dir.mkdir(exist_ok=True)
109 build_dir.mkdir(exist_ok=True)
105
110
106 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
111 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
107 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
112 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
108 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
113 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
109 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
114 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
110
115
111 venv_path = build_dir / (
116 venv_path = build_dir / (
112 'venv-%s-%s' % (build_name, 'x64' if vc_x64 else 'x86')
117 'venv-%s-%s' % (build_name, 'x64' if vc_x64 else 'x86')
113 )
118 )
114
119
115 gettext_root = build_dir / ('gettext-win-%s' % gettext_entry['version'])
120 gettext_root = build_dir / ('gettext-win-%s' % gettext_entry['version'])
116
121
117 if not gettext_root.exists():
122 if not gettext_root.exists():
118 extract_zip_to_directory(gettext_pkg, gettext_root)
123 extract_zip_to_directory(gettext_pkg, gettext_root)
119 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
124 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
120
125
121 # This assumes Python 2. We don't need virtualenv on Python 3.
126 # This assumes Python 2. We don't need virtualenv on Python 3.
122 virtualenv_src_path = build_dir / (
127 virtualenv_src_path = build_dir / (
123 'virtualenv-%s' % virtualenv_entry['version']
128 'virtualenv-%s' % virtualenv_entry['version']
124 )
129 )
125 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
130 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
126
131
127 if not virtualenv_src_path.exists():
132 if not virtualenv_src_path.exists():
128 extract_tar_to_directory(virtualenv_pkg, build_dir)
133 extract_tar_to_directory(virtualenv_pkg, build_dir)
129
134
130 py2exe_source_path = build_dir / ('py2exe-%s' % py2exe_entry['version'])
135 py2exe_source_path = build_dir / ('py2exe-%s' % py2exe_entry['version'])
131
136
132 if not py2exe_source_path.exists():
137 if not py2exe_source_path.exists():
133 extract_zip_to_directory(py2exe_pkg, build_dir)
138 extract_zip_to_directory(py2exe_pkg, build_dir)
134
139
135 if not venv_path.exists():
140 if not venv_path.exists():
136 print('creating virtualenv with dependencies')
141 print('creating virtualenv with dependencies')
137 subprocess.run(
142 subprocess.run(
138 [str(python_exe), str(virtualenv_py), str(venv_path)], check=True
143 [str(python_exe), str(virtualenv_py), str(venv_path)], check=True
139 )
144 )
140
145
141 venv_python = venv_path / 'Scripts' / 'python.exe'
146 venv_python = venv_path / 'Scripts' / 'python.exe'
142 venv_pip = venv_path / 'Scripts' / 'pip.exe'
147 venv_pip = venv_path / 'Scripts' / 'pip.exe'
143
148
144 subprocess.run(
149 subprocess.run(
145 [str(venv_pip), 'install', '-r', str(venv_requirements_txt)], check=True
150 [str(venv_pip), 'install', '-r', str(venv_requirements_txt)], check=True
146 )
151 )
147
152
148 # Force distutils to use VC++ settings from environment, which was
153 # Force distutils to use VC++ settings from environment, which was
149 # validated above.
154 # validated above.
150 env = dict(os.environ)
155 env = dict(os.environ)
151 env['DISTUTILS_USE_SDK'] = '1'
156 env['DISTUTILS_USE_SDK'] = '1'
152 env['MSSdk'] = '1'
157 env['MSSdk'] = '1'
153
158
154 if extra_packages_script:
159 if extra_packages_script:
155 more_packages = set(
160 more_packages = set(
156 subprocess.check_output(extra_packages_script, cwd=build_dir)
161 subprocess.check_output(extra_packages_script, cwd=build_dir)
157 .split(b'\0')[-1]
162 .split(b'\0')[-1]
158 .strip()
163 .strip()
159 .decode('utf-8')
164 .decode('utf-8')
160 .splitlines()
165 .splitlines()
161 )
166 )
162 if more_packages:
167 if more_packages:
163 if not extra_packages:
168 if not extra_packages:
164 extra_packages = more_packages
169 extra_packages = more_packages
165 else:
170 else:
166 extra_packages |= more_packages
171 extra_packages |= more_packages
167
172
168 if extra_packages:
173 if extra_packages:
169 env['HG_PY2EXE_EXTRA_PACKAGES'] = ' '.join(sorted(extra_packages))
174 env['HG_PY2EXE_EXTRA_PACKAGES'] = ' '.join(sorted(extra_packages))
170 hgext3rd_extras = sorted(
175 hgext3rd_extras = sorted(
171 e for e in extra_packages if e.startswith('hgext3rd.')
176 e for e in extra_packages if e.startswith('hgext3rd.')
172 )
177 )
173 if hgext3rd_extras:
178 if hgext3rd_extras:
174 env['HG_PY2EXE_EXTRA_INSTALL_PACKAGES'] = ' '.join(hgext3rd_extras)
179 env['HG_PY2EXE_EXTRA_INSTALL_PACKAGES'] = ' '.join(hgext3rd_extras)
175 if extra_excludes:
180 if extra_excludes:
176 env['HG_PY2EXE_EXTRA_EXCLUDES'] = ' '.join(sorted(extra_excludes))
181 env['HG_PY2EXE_EXTRA_EXCLUDES'] = ' '.join(sorted(extra_excludes))
177 if extra_dll_excludes:
182 if extra_dll_excludes:
178 env['HG_PY2EXE_EXTRA_DLL_EXCLUDES'] = ' '.join(
183 env['HG_PY2EXE_EXTRA_DLL_EXCLUDES'] = ' '.join(
179 sorted(extra_dll_excludes)
184 sorted(extra_dll_excludes)
180 )
185 )
181
186
182 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
187 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
183 if not py2exe_py_path.exists():
188 if not py2exe_py_path.exists():
184 print('building py2exe')
189 print('building py2exe')
185 subprocess.run(
190 subprocess.run(
186 [str(venv_python), 'setup.py', 'install'],
191 [str(venv_python), 'setup.py', 'install'],
187 cwd=py2exe_source_path,
192 cwd=py2exe_source_path,
188 env=env,
193 env=env,
189 check=True,
194 check=True,
190 )
195 )
191
196
192 # Register location of msgfmt and other binaries.
197 # Register location of msgfmt and other binaries.
193 env['PATH'] = '%s%s%s' % (
198 env['PATH'] = '%s%s%s' % (
194 env['PATH'],
199 env['PATH'],
195 os.pathsep,
200 os.pathsep,
196 str(gettext_root / 'bin'),
201 str(gettext_root / 'bin'),
197 )
202 )
198
203
199 print('building Mercurial')
204 print('building Mercurial')
200 subprocess.run(
205 subprocess.run(
201 [str(venv_python), 'setup.py', 'py2exe', 'build_doc', '--html'],
206 [str(venv_python), 'setup.py', 'py2exe', 'build_doc', '--html'],
202 cwd=str(source_dir),
207 cwd=str(source_dir),
203 env=env,
208 env=env,
204 check=True,
209 check=True,
205 )
210 )
206
211
207
212
208 def stage_install(source_dir: pathlib.Path, staging_dir: pathlib.Path):
213 def stage_install(source_dir: pathlib.Path, staging_dir: pathlib.Path):
209 """Copy all files to be installed to a directory.
214 """Copy all files to be installed to a directory.
210
215
211 This allows packaging to simply walk a directory tree to find source
216 This allows packaging to simply walk a directory tree to find source
212 files.
217 files.
213 """
218 """
214 process_install_rules(STAGING_RULES, source_dir, staging_dir)
219 process_install_rules(STAGING_RULES, source_dir, staging_dir)
220
221 # Purge any files we don't want to be there.
222 for f in STAGING_EXCLUDES:
223 p = staging_dir / f
224 if p.exists():
225 print('removing %s' % p)
226 p.unlink()
General Comments 0
You need to be logged in to leave comments. Login now