##// END OF EJS Templates
packaging: extract py2exe functionality to own module...
Gregory Szorc -
r42081:a2e191a9 default
parent child Browse files
Show More
@@ -1,158 +1,70 b''
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 from .downloads import (
16 download_entry,
15 from .py2exe import (
16 build_py2exe,
17 17 )
18 18 from .util import (
19 extract_tar_to_directory,
20 extract_zip_to_directory,
21 19 find_vc_runtime_files,
22 python_exe_info,
23 20 )
24 21
25 22
26 23 def build(source_dir: pathlib.Path, build_dir: pathlib.Path,
27 24 python_exe: pathlib.Path, iscc_exe: pathlib.Path,
28 25 version=None):
29 26 """Build the Inno installer.
30 27
31 28 Build files will be placed in ``build_dir``.
32 29
33 30 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
34 31 for finding the Python 2.7 toolchain. So, we require the environment
35 32 to already be configured with an active toolchain.
36 33 """
37 34 if not iscc_exe.exists():
38 35 raise Exception('%s does not exist' % iscc_exe)
39 36
40 if 'VCINSTALLDIR' not in os.environ:
41 raise Exception('not running from a Visual C++ build environment; '
42 'execute the "Visual C++ <version> Command Prompt" '
43 'application shortcut or a vcsvarsall.bat file')
44
45 # Identity x86/x64 and validate the environment matches the Python
46 # architecture.
47 vc_x64 = r'\x64' in os.environ['LIB']
48
49 py_info = python_exe_info(python_exe)
50
51 if vc_x64:
52 if py_info['arch'] != '64bit':
53 raise Exception('architecture mismatch: Visual C++ environment '
54 'is configured for 64-bit but Python is 32-bit')
55 else:
56 if py_info['arch'] != '32bit':
57 raise Exception('architecture mismatch: Visual C++ environment '
58 'is configured for 32-bit but Python is 64-bit')
59
60 if py_info['py3']:
61 raise Exception('Only Python 2 is currently supported')
62
63 build_dir.mkdir(exist_ok=True)
64
65 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
66 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
67 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
68 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
69
70 venv_path = build_dir / ('venv-inno-%s' % ('x64' if vc_x64 else 'x86'))
71
72 gettext_root = build_dir / (
73 'gettext-win-%s' % gettext_entry['version'])
74
75 if not gettext_root.exists():
76 extract_zip_to_directory(gettext_pkg, gettext_root)
77 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
78
79 # This assumes Python 2. We don't need virtualenv on Python 3.
80 virtualenv_src_path = build_dir / (
81 'virtualenv-%s' % virtualenv_entry['version'])
82 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
83
84 if not virtualenv_src_path.exists():
85 extract_tar_to_directory(virtualenv_pkg, build_dir)
86
87 py2exe_source_path = build_dir / ('py2exe-%s' % py2exe_entry['version'])
88
89 if not py2exe_source_path.exists():
90 extract_zip_to_directory(py2exe_pkg, build_dir)
91
92 if not venv_path.exists():
93 print('creating virtualenv with dependencies')
94 subprocess.run(
95 [str(python_exe), str(virtualenv_py), str(venv_path)],
96 check=True)
97
98 venv_python = venv_path / 'Scripts' / 'python.exe'
99 venv_pip = venv_path / 'Scripts' / 'pip.exe'
37 vc_x64 = r'\x64' in os.environ.get('LIB', '')
100 38
101 39 requirements_txt = (source_dir / 'contrib' / 'packaging' /
102 40 'inno' / 'requirements.txt')
103 subprocess.run([str(venv_pip), 'install', '-r', str(requirements_txt)],
104 check=True)
105 41
106 # Force distutils to use VC++ settings from environment, which was
107 # validated above.
108 env = dict(os.environ)
109 env['DISTUTILS_USE_SDK'] = '1'
110 env['MSSdk'] = '1'
111
112 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
113 if not py2exe_py_path.exists():
114 print('building py2exe')
115 subprocess.run([str(venv_python), 'setup.py', 'install'],
116 cwd=py2exe_source_path,
117 env=env,
118 check=True)
119
120 # Register location of msgfmt and other binaries.
121 env['PATH'] = '%s%s%s' % (
122 env['PATH'], os.pathsep, str(gettext_root / 'bin'))
123
124 print('building Mercurial')
125 subprocess.run(
126 [str(venv_python), 'setup.py',
127 'py2exe', '-b', '3' if vc_x64 else '2',
128 'build_doc', '--html'],
129 cwd=str(source_dir),
130 env=env,
131 check=True)
42 build_py2exe(source_dir, build_dir, python_exe, 'inno',
43 requirements_txt)
132 44
133 45 # hg.exe depends on VC9 runtime DLLs. Copy those into place.
134 46 for f in find_vc_runtime_files(vc_x64):
135 47 if f.name.endswith('.manifest'):
136 48 basename = 'Microsoft.VC90.CRT.manifest'
137 49 else:
138 50 basename = f.name
139 51
140 52 dest_path = source_dir / 'dist' / basename
141 53
142 54 print('copying %s to %s' % (f, dest_path))
143 55 shutil.copyfile(f, dest_path)
144 56
145 57 print('creating installer')
146 58
147 59 args = [str(iscc_exe)]
148 60
149 61 if vc_x64:
150 62 args.append('/dARCH=x64')
151 63
152 64 if version:
153 65 args.append('/dVERSION=%s' % version)
154 66
155 67 args.append('/Odist')
156 68 args.append('contrib/packaging/inno/mercurial.iss')
157 69
158 70 subprocess.run(args, cwd=str(source_dir), check=True)
@@ -1,158 +1,125 b''
1 # inno.py - Inno Setup functionality.
1 # py2exe.py - Functionality for performing py2exe builds.
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 import shutil
13 12 import subprocess
14 13
15 14 from .downloads import (
16 15 download_entry,
17 16 )
18 17 from .util import (
19 18 extract_tar_to_directory,
20 19 extract_zip_to_directory,
21 find_vc_runtime_files,
22 20 python_exe_info,
23 21 )
24 22
25 23
26 def build(source_dir: pathlib.Path, build_dir: pathlib.Path,
27 python_exe: pathlib.Path, iscc_exe: pathlib.Path,
28 version=None):
29 """Build the Inno installer.
24 def build_py2exe(source_dir: pathlib.Path, build_dir: pathlib.Path,
25 python_exe: pathlib.Path, build_name: str,
26 venv_requirements_txt: pathlib.Path):
27 """Build Mercurial with py2exe.
30 28
31 29 Build files will be placed in ``build_dir``.
32 30
33 31 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
34 32 for finding the Python 2.7 toolchain. So, we require the environment
35 33 to already be configured with an active toolchain.
36 34 """
37 if not iscc_exe.exists():
38 raise Exception('%s does not exist' % iscc_exe)
39
40 35 if 'VCINSTALLDIR' not in os.environ:
41 36 raise Exception('not running from a Visual C++ build environment; '
42 37 'execute the "Visual C++ <version> Command Prompt" '
43 38 'application shortcut or a vcsvarsall.bat file')
44 39
45 40 # Identity x86/x64 and validate the environment matches the Python
46 41 # architecture.
47 42 vc_x64 = r'\x64' in os.environ['LIB']
48 43
49 44 py_info = python_exe_info(python_exe)
50 45
51 46 if vc_x64:
52 47 if py_info['arch'] != '64bit':
53 48 raise Exception('architecture mismatch: Visual C++ environment '
54 49 'is configured for 64-bit but Python is 32-bit')
55 50 else:
56 51 if py_info['arch'] != '32bit':
57 52 raise Exception('architecture mismatch: Visual C++ environment '
58 53 'is configured for 32-bit but Python is 64-bit')
59 54
60 55 if py_info['py3']:
61 56 raise Exception('Only Python 2 is currently supported')
62 57
63 58 build_dir.mkdir(exist_ok=True)
64 59
65 60 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
66 61 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
67 62 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
68 63 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
69 64
70 venv_path = build_dir / ('venv-inno-%s' % ('x64' if vc_x64 else 'x86'))
65 venv_path = build_dir / ('venv-%s-%s' % (build_name,
66 'x64' if vc_x64 else 'x86'))
71 67
72 68 gettext_root = build_dir / (
73 69 'gettext-win-%s' % gettext_entry['version'])
74 70
75 71 if not gettext_root.exists():
76 72 extract_zip_to_directory(gettext_pkg, gettext_root)
77 73 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
78 74
79 75 # This assumes Python 2. We don't need virtualenv on Python 3.
80 76 virtualenv_src_path = build_dir / (
81 77 'virtualenv-%s' % virtualenv_entry['version'])
82 78 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
83 79
84 80 if not virtualenv_src_path.exists():
85 81 extract_tar_to_directory(virtualenv_pkg, build_dir)
86 82
87 83 py2exe_source_path = build_dir / ('py2exe-%s' % py2exe_entry['version'])
88 84
89 85 if not py2exe_source_path.exists():
90 86 extract_zip_to_directory(py2exe_pkg, build_dir)
91 87
92 88 if not venv_path.exists():
93 89 print('creating virtualenv with dependencies')
94 90 subprocess.run(
95 91 [str(python_exe), str(virtualenv_py), str(venv_path)],
96 92 check=True)
97 93
98 94 venv_python = venv_path / 'Scripts' / 'python.exe'
99 95 venv_pip = venv_path / 'Scripts' / 'pip.exe'
100 96
101 requirements_txt = (source_dir / 'contrib' / 'packaging' /
102 'inno' / 'requirements.txt')
103 subprocess.run([str(venv_pip), 'install', '-r', str(requirements_txt)],
97 subprocess.run([str(venv_pip), 'install', '-r', str(venv_requirements_txt)],
104 98 check=True)
105 99
106 100 # Force distutils to use VC++ settings from environment, which was
107 101 # validated above.
108 102 env = dict(os.environ)
109 103 env['DISTUTILS_USE_SDK'] = '1'
110 104 env['MSSdk'] = '1'
111 105
112 106 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
113 107 if not py2exe_py_path.exists():
114 108 print('building py2exe')
115 109 subprocess.run([str(venv_python), 'setup.py', 'install'],
116 110 cwd=py2exe_source_path,
117 111 env=env,
118 112 check=True)
119 113
120 114 # Register location of msgfmt and other binaries.
121 115 env['PATH'] = '%s%s%s' % (
122 116 env['PATH'], os.pathsep, str(gettext_root / 'bin'))
123 117
124 118 print('building Mercurial')
125 119 subprocess.run(
126 120 [str(venv_python), 'setup.py',
127 121 'py2exe', '-b', '3' if vc_x64 else '2',
128 122 'build_doc', '--html'],
129 123 cwd=str(source_dir),
130 124 env=env,
131 125 check=True)
132
133 # hg.exe depends on VC9 runtime DLLs. Copy those into place.
134 for f in find_vc_runtime_files(vc_x64):
135 if f.name.endswith('.manifest'):
136 basename = 'Microsoft.VC90.CRT.manifest'
137 else:
138 basename = f.name
139
140 dest_path = source_dir / 'dist' / basename
141
142 print('copying %s to %s' % (f, dest_path))
143 shutil.copyfile(f, dest_path)
144
145 print('creating installer')
146
147 args = [str(iscc_exe)]
148
149 if vc_x64:
150 args.append('/dARCH=x64')
151
152 if version:
153 args.append('/dVERSION=%s' % version)
154
155 args.append('/Odist')
156 args.append('contrib/packaging/inno/mercurial.iss')
157
158 subprocess.run(args, cwd=str(source_dir), check=True)
@@ -1,73 +1,74 b''
1 1 #require test-repo
2 2
3 3 $ . "$TESTDIR/helpers-testrepo.sh"
4 4 $ check_code="$TESTDIR"/../contrib/check-code.py
5 5 $ cd "$TESTDIR"/..
6 6
7 7 New errors are not allowed. Warnings are strongly discouraged.
8 8 (The writing "no-che?k-code" is for not skipping this file when checking.)
9 9
10 10 $ testrepohg locate \
11 11 > -X contrib/python-zstandard \
12 12 > -X hgext/fsmonitor/pywatchman \
13 13 > -X mercurial/thirdparty \
14 14 > | sed 's-\\-/-g' | "$check_code" --warnings --per-file=0 - || false
15 15 Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob)
16 16 Skipping contrib/packaging/hgpackaging/inno.py it has no-che?k-code (glob)
17 Skipping contrib/packaging/hgpackaging/py2exe.py it has no-che?k-code (glob)
17 18 Skipping contrib/packaging/hgpackaging/util.py it has no-che?k-code (glob)
18 19 Skipping contrib/packaging/inno/build.py it has no-che?k-code (glob)
19 20 Skipping i18n/polib.py it has no-che?k-code (glob)
20 21 Skipping mercurial/statprof.py it has no-che?k-code (glob)
21 22 Skipping tests/badserverext.py it has no-che?k-code (glob)
22 23
23 24 @commands in debugcommands.py should be in alphabetical order.
24 25
25 26 >>> import re
26 27 >>> commands = []
27 28 >>> with open('mercurial/debugcommands.py', 'rb') as fh:
28 29 ... for line in fh:
29 30 ... m = re.match(br"^@command\('([a-z]+)", line)
30 31 ... if m:
31 32 ... commands.append(m.group(1))
32 33 >>> scommands = list(sorted(commands))
33 34 >>> for i, command in enumerate(scommands):
34 35 ... if command != commands[i]:
35 36 ... print('commands in debugcommands.py not sorted; first differing '
36 37 ... 'command is %s; expected %s' % (commands[i], command))
37 38 ... break
38 39
39 40 Prevent adding new files in the root directory accidentally.
40 41
41 42 $ testrepohg files 'glob:*'
42 43 .arcconfig
43 44 .clang-format
44 45 .editorconfig
45 46 .hgignore
46 47 .hgsigs
47 48 .hgtags
48 49 .jshintrc
49 50 CONTRIBUTING
50 51 CONTRIBUTORS
51 52 COPYING
52 53 Makefile
53 54 README.rst
54 55 hg
55 56 hgeditor
56 57 hgweb.cgi
57 58 setup.py
58 59
59 60 Prevent adding modules which could be shadowed by ancient .so/.dylib.
60 61
61 62 $ testrepohg files \
62 63 > mercurial/base85.py \
63 64 > mercurial/bdiff.py \
64 65 > mercurial/diffhelpers.py \
65 66 > mercurial/mpatch.py \
66 67 > mercurial/osutil.py \
67 68 > mercurial/parsers.py \
68 69 > mercurial/zstd.py
69 70 [1]
70 71
71 72 Keep python3 tests sorted:
72 73 $ sort < contrib/python3-whitelist > $TESTTMP/py3sorted
73 74 $ cmp contrib/python3-whitelist $TESTTMP/py3sorted || echo 'Please sort passing tests!'
General Comments 0
You need to be logged in to leave comments. Login now