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