##// END OF EJS Templates
packaging: reference proper output directory...
Gregory Szorc -
r48696:1e6cb23c stable
parent child Browse files
Show More
@@ -1,180 +1,175 b''
1 # pyoxidizer.py - Packaging support for PyOxidizer
1 # pyoxidizer.py - Packaging support for PyOxidizer
2 #
2 #
3 # Copyright 2020 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2020 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 sys
14 import sys
15 import typing
15 import typing
16
16
17 from .downloads import download_entry
17 from .downloads import download_entry
18 from .util import (
18 from .util import (
19 extract_zip_to_directory,
19 extract_zip_to_directory,
20 process_install_rules,
20 process_install_rules,
21 find_vc_runtime_dll,
21 find_vc_runtime_dll,
22 )
22 )
23
23
24
24
25 STAGING_RULES_WINDOWS = [
25 STAGING_RULES_WINDOWS = [
26 ('contrib/bash_completion', 'contrib/'),
26 ('contrib/bash_completion', 'contrib/'),
27 ('contrib/hgk', 'contrib/hgk.tcl'),
27 ('contrib/hgk', 'contrib/hgk.tcl'),
28 ('contrib/hgweb.fcgi', 'contrib/'),
28 ('contrib/hgweb.fcgi', 'contrib/'),
29 ('contrib/hgweb.wsgi', 'contrib/'),
29 ('contrib/hgweb.wsgi', 'contrib/'),
30 ('contrib/logo-droplets.svg', 'contrib/'),
30 ('contrib/logo-droplets.svg', 'contrib/'),
31 ('contrib/mercurial.el', 'contrib/'),
31 ('contrib/mercurial.el', 'contrib/'),
32 ('contrib/mq.el', 'contrib/'),
32 ('contrib/mq.el', 'contrib/'),
33 ('contrib/tcsh_completion', 'contrib/'),
33 ('contrib/tcsh_completion', 'contrib/'),
34 ('contrib/tcsh_completion_build.sh', 'contrib/'),
34 ('contrib/tcsh_completion_build.sh', 'contrib/'),
35 ('contrib/vim/*', 'contrib/vim/'),
35 ('contrib/vim/*', 'contrib/vim/'),
36 ('contrib/win32/postinstall.txt', 'ReleaseNotes.txt'),
36 ('contrib/win32/postinstall.txt', 'ReleaseNotes.txt'),
37 ('contrib/win32/ReadMe.html', 'ReadMe.html'),
37 ('contrib/win32/ReadMe.html', 'ReadMe.html'),
38 ('contrib/xml.rnc', 'contrib/'),
38 ('contrib/xml.rnc', 'contrib/'),
39 ('contrib/zsh_completion', 'contrib/'),
39 ('contrib/zsh_completion', 'contrib/'),
40 ('doc/*.html', 'doc/'),
40 ('doc/*.html', 'doc/'),
41 ('doc/style.css', 'doc/'),
41 ('doc/style.css', 'doc/'),
42 ('COPYING', 'Copying.txt'),
42 ('COPYING', 'Copying.txt'),
43 ]
43 ]
44
44
45 STAGING_RULES_APP = [
45 STAGING_RULES_APP = [
46 ('lib/mercurial/helptext/**/*.txt', 'helptext/'),
46 ('lib/mercurial/helptext/**/*.txt', 'helptext/'),
47 ('lib/mercurial/defaultrc/*.rc', 'defaultrc/'),
47 ('lib/mercurial/defaultrc/*.rc', 'defaultrc/'),
48 ('lib/mercurial/locale/**/*', 'locale/'),
48 ('lib/mercurial/locale/**/*', 'locale/'),
49 ('lib/mercurial/templates/**/*', 'templates/'),
49 ('lib/mercurial/templates/**/*', 'templates/'),
50 ]
50 ]
51
51
52 STAGING_EXCLUDES_WINDOWS = [
52 STAGING_EXCLUDES_WINDOWS = [
53 "doc/hg-ssh.8.html",
53 "doc/hg-ssh.8.html",
54 ]
54 ]
55
55
56
56
57 def build_docs_html(source_dir: pathlib.Path):
57 def build_docs_html(source_dir: pathlib.Path):
58 """Ensures HTML documentation is built.
58 """Ensures HTML documentation is built.
59
59
60 This will fail if docutils isn't available.
60 This will fail if docutils isn't available.
61
61
62 (The HTML docs aren't built as part of `pip install` so we need to build them
62 (The HTML docs aren't built as part of `pip install` so we need to build them
63 out of band.)
63 out of band.)
64 """
64 """
65 subprocess.run(
65 subprocess.run(
66 [sys.executable, str(source_dir / "setup.py"), "build_doc", "--html"],
66 [sys.executable, str(source_dir / "setup.py"), "build_doc", "--html"],
67 cwd=str(source_dir),
67 cwd=str(source_dir),
68 check=True,
68 check=True,
69 )
69 )
70
70
71
71
72 def run_pyoxidizer(
72 def run_pyoxidizer(
73 source_dir: pathlib.Path,
73 source_dir: pathlib.Path,
74 build_dir: pathlib.Path,
74 build_dir: pathlib.Path,
75 target_triple: str,
75 target_triple: str,
76 build_vars: typing.Optional[typing.Dict[str, str]] = None,
76 build_vars: typing.Optional[typing.Dict[str, str]] = None,
77 target: typing.Optional[str] = None,
77 target: typing.Optional[str] = None,
78 ) -> pathlib.Path:
78 ) -> pathlib.Path:
79 """Run `pyoxidizer` in an environment with access to build dependencies.
79 """Run `pyoxidizer` in an environment with access to build dependencies.
80
80
81 Returns the output directory that pyoxidizer would have used for build
81 Returns the output directory that pyoxidizer would have used for build
82 artifacts. Actual build artifacts are likely in a sub-directory with the
82 artifacts. Actual build artifacts are likely in a sub-directory with the
83 name of the pyoxidizer build target that was built.
83 name of the pyoxidizer build target that was built.
84 """
84 """
85 build_vars = build_vars or {}
85 build_vars = build_vars or {}
86
86
87 # We need to make gettext binaries available for compiling i18n files.
87 # We need to make gettext binaries available for compiling i18n files.
88 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
88 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
89 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
89 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
90
90
91 gettext_root = build_dir / ('gettext-win-%s' % gettext_entry['version'])
91 gettext_root = build_dir / ('gettext-win-%s' % gettext_entry['version'])
92
92
93 if not gettext_root.exists():
93 if not gettext_root.exists():
94 extract_zip_to_directory(gettext_pkg, gettext_root)
94 extract_zip_to_directory(gettext_pkg, gettext_root)
95 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
95 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
96
96
97 env = dict(os.environ)
97 env = dict(os.environ)
98 env["PATH"] = "%s%s%s" % (
98 env["PATH"] = "%s%s%s" % (
99 env["PATH"],
99 env["PATH"],
100 os.pathsep,
100 os.pathsep,
101 str(gettext_root / "bin"),
101 str(gettext_root / "bin"),
102 )
102 )
103
103
104 args = [
104 args = [
105 "pyoxidizer",
105 "pyoxidizer",
106 "build",
106 "build",
107 "--path",
107 "--path",
108 str(source_dir / "rust" / "hgcli"),
108 str(source_dir / "rust" / "hgcli"),
109 "--release",
109 "--release",
110 "--target-triple",
110 "--target-triple",
111 target_triple,
111 target_triple,
112 ]
112 ]
113
113
114 for k, v in sorted(build_vars.items()):
114 for k, v in sorted(build_vars.items()):
115 args.extend(["--var", k, v])
115 args.extend(["--var", k, v])
116
116
117 if target:
117 if target:
118 args.append(target)
118 args.append(target)
119
119
120 subprocess.run(args, env=env, check=True)
120 subprocess.run(args, env=env, check=True)
121
121
122 return source_dir / "build" / "pyoxidizer" / target_triple / "release"
122 return source_dir / "build" / "pyoxidizer" / target_triple / "release"
123
123
124
124
125 def create_pyoxidizer_install_layout(
125 def create_pyoxidizer_install_layout(
126 source_dir: pathlib.Path,
126 source_dir: pathlib.Path,
127 build_dir: pathlib.Path,
127 build_dir: pathlib.Path,
128 out_dir: pathlib.Path,
128 out_dir: pathlib.Path,
129 target_triple: str,
129 target_triple: str,
130 ):
130 ):
131 """Build Mercurial with PyOxidizer and copy additional files into place.
131 """Build Mercurial with PyOxidizer and copy additional files into place.
132
132
133 After successful completion, ``out_dir`` contains files constituting a
133 After successful completion, ``out_dir`` contains files constituting a
134 Mercurial install.
134 Mercurial install.
135 """
135 """
136
136
137 run_pyoxidizer(source_dir, build_dir, target_triple)
137 run_pyoxidizer(source_dir, build_dir, target_triple)
138
138
139 if "windows" in target_triple:
140 target = "app_windows"
141 else:
142 target = "app_posix"
143
144 build_dir = (
139 build_dir = (
145 source_dir / "build" / "pyoxidizer" / target_triple / "release" / target
140 source_dir / "build" / "pyoxidizer" / target_triple / "release" / "app"
146 )
141 )
147
142
148 if out_dir.exists():
143 if out_dir.exists():
149 print("purging %s" % out_dir)
144 print("purging %s" % out_dir)
150 shutil.rmtree(out_dir)
145 shutil.rmtree(out_dir)
151
146
152 # Now assemble all the files from PyOxidizer into the staging directory.
147 # Now assemble all the files from PyOxidizer into the staging directory.
153 shutil.copytree(build_dir, out_dir)
148 shutil.copytree(build_dir, out_dir)
154
149
155 # Move some of those files around. We can get rid of this once Mercurial
150 # Move some of those files around. We can get rid of this once Mercurial
156 # is taught to use the importlib APIs for reading resources.
151 # is taught to use the importlib APIs for reading resources.
157 process_install_rules(STAGING_RULES_APP, build_dir, out_dir)
152 process_install_rules(STAGING_RULES_APP, build_dir, out_dir)
158
153
159 build_docs_html(source_dir)
154 build_docs_html(source_dir)
160
155
161 if "windows" in target_triple:
156 if "windows" in target_triple:
162 process_install_rules(STAGING_RULES_WINDOWS, source_dir, out_dir)
157 process_install_rules(STAGING_RULES_WINDOWS, source_dir, out_dir)
163
158
164 # Write out a default editor.rc file to configure notepad as the
159 # Write out a default editor.rc file to configure notepad as the
165 # default editor.
160 # default editor.
166 os.makedirs(out_dir / "defaultrc", exist_ok=True)
161 os.makedirs(out_dir / "defaultrc", exist_ok=True)
167 with (out_dir / "defaultrc" / "editor.rc").open(
162 with (out_dir / "defaultrc" / "editor.rc").open(
168 "w", encoding="utf-8"
163 "w", encoding="utf-8"
169 ) as fh:
164 ) as fh:
170 fh.write("[ui]\neditor = notepad\n")
165 fh.write("[ui]\neditor = notepad\n")
171
166
172 for f in STAGING_EXCLUDES_WINDOWS:
167 for f in STAGING_EXCLUDES_WINDOWS:
173 p = out_dir / f
168 p = out_dir / f
174 if p.exists():
169 if p.exists():
175 print("removing %s" % p)
170 print("removing %s" % p)
176 p.unlink()
171 p.unlink()
177
172
178 # Add vcruntimeXXX.dll next to executable.
173 # Add vcruntimeXXX.dll next to executable.
179 vc_runtime_dll = find_vc_runtime_dll(x64="x86_64" in target_triple)
174 vc_runtime_dll = find_vc_runtime_dll(x64="x86_64" in target_triple)
180 shutil.copy(vc_runtime_dll, out_dir / vc_runtime_dll.name)
175 shutil.copy(vc_runtime_dll, out_dir / vc_runtime_dll.name)
General Comments 0
You need to be logged in to leave comments. Login now