##// END OF EJS Templates
pyoxidizer: wrap the pyoxidizer script on multiple line...
marmoute -
r48656:5f2b0d34 stable
parent child Browse files
Show More
@@ -1,290 +1,295 b''
1 1 # The following variables can be passed in as parameters:
2 2 #
3 3 # VERSION
4 4 # Version string of program being produced.
5 5 #
6 6 # MSI_NAME
7 7 # Root name of MSI installer.
8 8 #
9 9 # EXTRA_MSI_FEATURES
10 10 # ; delimited string of extra features to advertise in the built MSA.
11 11 #
12 12 # SIGNING_PFX_PATH
13 13 # Path to code signing certificate to use.
14 14 #
15 15 # SIGNING_PFX_PASSWORD
16 16 # Password to code signing PFX file defined by SIGNING_PFX_PATH.
17 17 #
18 18 # SIGNING_SUBJECT_NAME
19 19 # String fragment in code signing certificate subject name used to find
20 20 # code signing certificate in Windows certificate store.
21 21 #
22 22 # TIME_STAMP_SERVER_URL
23 23 # URL of time-stamp token authority (RFC 3161) servers to stamp code signatures.
24 24
25 25 ROOT = CWD + "/../.."
26 26
27 27 VERSION = VARS.get("VERSION", "5.8")
28 28 MSI_NAME = VARS.get("MSI_NAME", "mercurial")
29 29 EXTRA_MSI_FEATURES = VARS.get("EXTRA_MSI_FEATURES")
30 30 SIGNING_PFX_PATH = VARS.get("SIGNING_PFX_PATH")
31 31 SIGNING_PFX_PASSWORD = VARS.get("SIGNING_PFX_PASSWORD", "")
32 32 SIGNING_SUBJECT_NAME = VARS.get("SIGNING_SUBJECT_NAME")
33 33 TIME_STAMP_SERVER_URL = VARS.get("TIME_STAMP_SERVER_URL", "http://timestamp.digicert.com")
34 34
35 35 IS_WINDOWS = "windows" in BUILD_TARGET_TRIPLE
36 36
37 37 # Code to run in Python interpreter.
38 RUN_CODE = "import hgdemandimport; hgdemandimport.enable(); from mercurial import dispatch; dispatch.run()"
38 RUN_CODE = """
39 import hgdemandimport;
40 hgdemandimport.enable();
41 from mercurial import dispatch;
42 dispatch.run();
43 """
39 44
40 45 set_build_path(ROOT + "/build/pyoxidizer")
41 46
42 47 def make_distribution():
43 48 return default_python_distribution(python_version = "3.9")
44 49
45 50 def resource_callback(policy, resource):
46 51 if not IS_WINDOWS:
47 52 resource.add_location = "in-memory"
48 53 return
49 54
50 55 # We use a custom resource routing policy to influence where things are loaded
51 56 # from.
52 57 #
53 58 # For Python modules and resources, we load from memory if they are in
54 59 # the standard library and from the filesystem if not. This is because
55 60 # parts of Mercurial and some 3rd party packages aren't yet compatible
56 61 # with memory loading.
57 62 #
58 63 # For Python extension modules, we load from the filesystem because
59 64 # this yields greatest compatibility.
60 65 if type(resource) in ("PythonModuleSource", "PythonPackageResource", "PythonPackageDistributionResource"):
61 66 if resource.is_stdlib:
62 67 resource.add_location = "in-memory"
63 68 else:
64 69 resource.add_location = "filesystem-relative:lib"
65 70
66 71 elif type(resource) == "PythonExtensionModule":
67 72 resource.add_location = "filesystem-relative:lib"
68 73
69 74 def make_exe(dist):
70 75 """Builds a Rust-wrapped Mercurial binary."""
71 76 packaging_policy = dist.make_python_packaging_policy()
72 77
73 78 # Extension may depend on any Python functionality. Include all
74 79 # extensions.
75 80 packaging_policy.extension_module_filter = "all"
76 81 packaging_policy.resources_location = "in-memory"
77 82 if IS_WINDOWS:
78 83 packaging_policy.resources_location_fallback = "filesystem-relative:lib"
79 84 packaging_policy.register_resource_callback(resource_callback)
80 85
81 86 config = dist.make_python_interpreter_config()
82 87 config.allocator_backend = "default"
83 88 config.run_command = RUN_CODE
84 89
85 90 # We want to let the user load extensions from the file system
86 91 config.filesystem_importer = True
87 92
88 93 # We need this to make resourceutil happy, since it looks for sys.frozen.
89 94 config.sys_frozen = True
90 95 config.legacy_windows_stdio = True
91 96
92 97 exe = dist.to_python_executable(
93 98 name = "hg",
94 99 packaging_policy = packaging_policy,
95 100 config = config,
96 101 )
97 102
98 103 # Add Mercurial to resources.
99 104 exe.add_python_resources(exe.pip_install(["--verbose", ROOT]))
100 105
101 106 # On Windows, we install extra packages for convenience.
102 107 if IS_WINDOWS:
103 108 exe.add_python_resources(
104 109 exe.pip_install(["-r", ROOT + "/contrib/packaging/requirements-windows-py3.txt"]),
105 110 )
106 111 extra_packages = VARS.get("extra_py_packages", "")
107 112 if extra_packages:
108 113 for extra in extra_packages.split(","):
109 114 extra_src, pkgs = extra.split("=")
110 115 pkgs = pkgs.split(":")
111 116 exe.add_python_resources(exe.read_package_root(extra_src, pkgs))
112 117
113 118 return exe
114 119
115 120 def make_manifest(dist, exe):
116 121 m = FileManifest()
117 122 m.add_python_resource(".", exe)
118 123
119 124 return m
120 125
121 126
122 127 # This adjusts the InstallManifest produced from exe generation to provide
123 128 # additional files found in a Windows install layout.
124 129 def make_windows_install_layout(manifest):
125 130 # Copy various files to new install locations. This can go away once
126 131 # we're using the importlib resource reader.
127 132 RECURSIVE_COPIES = {
128 133 "lib/mercurial/locale/": "locale/",
129 134 "lib/mercurial/templates/": "templates/",
130 135 }
131 136 for (search, replace) in RECURSIVE_COPIES.items():
132 137 for path in manifest.paths():
133 138 if path.startswith(search):
134 139 new_path = path.replace(search, replace)
135 140 print("copy %s to %s" % (path, new_path))
136 141 file = manifest.get_file(path)
137 142 manifest.add_file(file, path = new_path)
138 143
139 144 # Similar to above, but with filename pattern matching.
140 145 # lib/mercurial/helptext/**/*.txt -> helptext/
141 146 # lib/mercurial/defaultrc/*.rc -> defaultrc/
142 147 for path in manifest.paths():
143 148 if path.startswith("lib/mercurial/helptext/") and path.endswith(".txt"):
144 149 new_path = path[len("lib/mercurial/"):]
145 150 elif path.startswith("lib/mercurial/defaultrc/") and path.endswith(".rc"):
146 151 new_path = path[len("lib/mercurial/"):]
147 152 else:
148 153 continue
149 154
150 155 print("copying %s to %s" % (path, new_path))
151 156 manifest.add_file(manifest.get_file(path), path = new_path)
152 157
153 158 extra_install_files = VARS.get("extra_install_files", "")
154 159 if extra_install_files:
155 160 for extra in extra_install_files.split(","):
156 161 print("adding extra files from %s" % extra)
157 162 # TODO: I expected a ** glob to work, but it didn't.
158 163 #
159 164 # TODO: I know this has forward-slash paths. As far as I can tell,
160 165 # backslashes don't ever match glob() expansions in
161 166 # tugger-starlark, even on Windows.
162 167 manifest.add_manifest(glob(include=[extra + "/*/*"], strip_prefix=extra+"/"))
163 168
164 169 # We also install a handful of additional files.
165 170 EXTRA_CONTRIB_FILES = [
166 171 "bash_completion",
167 172 "hgweb.fcgi",
168 173 "hgweb.wsgi",
169 174 "logo-droplets.svg",
170 175 "mercurial.el",
171 176 "mq.el",
172 177 "tcsh_completion",
173 178 "tcsh_completion_build.sh",
174 179 "xml.rnc",
175 180 "zsh_completion",
176 181 ]
177 182
178 183 for f in EXTRA_CONTRIB_FILES:
179 184 manifest.add_file(FileContent(path = ROOT + "/contrib/" + f), directory = "contrib")
180 185
181 186 # Individual files with full source to destination path mapping.
182 187 EXTRA_FILES = {
183 188 "contrib/hgk": "contrib/hgk.tcl",
184 189 "contrib/win32/postinstall.txt": "ReleaseNotes.txt",
185 190 "contrib/win32/ReadMe.html": "ReadMe.html",
186 191 "doc/style.css": "doc/style.css",
187 192 "COPYING": "Copying.txt",
188 193 }
189 194
190 195 for source, dest in EXTRA_FILES.items():
191 196 print("adding extra file %s" % dest)
192 197 manifest.add_file(FileContent(path = ROOT + "/" + source), path = dest)
193 198
194 199 # And finally some wildcard matches.
195 200 manifest.add_manifest(glob(
196 201 include = [ROOT + "/contrib/vim/*"],
197 202 strip_prefix = ROOT + "/"
198 203 ))
199 204 manifest.add_manifest(glob(
200 205 include = [ROOT + "/doc/*.html"],
201 206 strip_prefix = ROOT + "/"
202 207 ))
203 208
204 209 # But we don't ship hg-ssh on Windows, so exclude its documentation.
205 210 manifest.remove("doc/hg-ssh.8.html")
206 211
207 212 return manifest
208 213
209 214
210 215 def make_msi(manifest):
211 216 manifest = make_windows_install_layout(manifest)
212 217
213 218 if "x86_64" in BUILD_TARGET_TRIPLE:
214 219 platform = "x64"
215 220 else:
216 221 platform = "x86"
217 222
218 223 manifest.add_file(
219 224 FileContent(path = ROOT + "/contrib/packaging/wix/COPYING.rtf"),
220 225 path = "COPYING.rtf",
221 226 )
222 227 manifest.remove("Copying.txt")
223 228 manifest.add_file(
224 229 FileContent(path = ROOT + "/contrib/win32/mercurial.ini"),
225 230 path = "defaultrc/mercurial.rc",
226 231 )
227 232 manifest.add_file(
228 233 FileContent(filename = "editor.rc", content = "[ui]\neditor = notepad\n"),
229 234 path = "defaultrc/editor.rc",
230 235 )
231 236
232 237 wix = WiXInstaller("hg", "%s-%s.msi" % (MSI_NAME, VERSION))
233 238
234 239 # Materialize files in the manifest to the install layout.
235 240 wix.add_install_files(manifest)
236 241
237 242 # From mercurial.wxs.
238 243 wix.install_files_root_directory_id = "INSTALLDIR"
239 244
240 245 # Pull in our custom .wxs files.
241 246 defines = {
242 247 "PyOxidizer": "1",
243 248 "Platform": platform,
244 249 "Version": VERSION,
245 250 "Comments": "Installs Mercurial version %s" % VERSION,
246 251 "PythonVersion": "3",
247 252 "MercurialHasLib": "1",
248 253 }
249 254
250 255 if EXTRA_MSI_FEATURES:
251 256 defines["MercurialExtraFeatures"] = EXTRA_MSI_FEATURES
252 257
253 258 wix.add_wxs_file(
254 259 ROOT + "/contrib/packaging/wix/mercurial.wxs",
255 260 preprocessor_parameters=defines,
256 261 )
257 262
258 263 # Our .wxs references to other files. Pull those into the build environment.
259 264 for f in ("defines.wxi", "guids.wxi", "COPYING.rtf"):
260 265 wix.add_build_file(f, ROOT + "/contrib/packaging/wix/" + f)
261 266
262 267 wix.add_build_file("mercurial.ico", ROOT + "/contrib/win32/mercurial.ico")
263 268
264 269 return wix
265 270
266 271
267 272 def register_code_signers():
268 273 if not IS_WINDOWS:
269 274 return
270 275
271 276 if SIGNING_PFX_PATH:
272 277 signer = code_signer_from_pfx_file(SIGNING_PFX_PATH, SIGNING_PFX_PASSWORD)
273 278 elif SIGNING_SUBJECT_NAME:
274 279 signer = code_signer_from_windows_store_subject(SIGNING_SUBJECT_NAME)
275 280 else:
276 281 signer = None
277 282
278 283 if signer:
279 284 signer.set_time_stamp_server(TIME_STAMP_SERVER_URL)
280 285 signer.activate()
281 286
282 287
283 288 register_code_signers()
284 289
285 290 register_target("distribution", make_distribution)
286 291 register_target("exe", make_exe, depends = ["distribution"])
287 292 register_target("app", make_manifest, depends = ["distribution", "exe"], default = True)
288 293 register_target("msi", make_msi, depends = ["app"])
289 294
290 295 resolve_targets()
General Comments 0
You need to be logged in to leave comments. Login now