##// END OF EJS Templates
wix: autogenerate wxs file for library files...
Gregory Szorc -
r42123:131d0b7c default
parent child Browse files
Show More
@@ -11,6 +11,8 b' import os'
11 11 import pathlib
12 12 import re
13 13 import subprocess
14 import tempfile
15 import xml.dom.minidom
14 16
15 17 from .downloads import (
16 18 download_entry,
@@ -128,6 +130,52 b' def make_post_build_signing_fn(name, sub'
128 130 return post_build_sign
129 131
130 132
133 LIBRARIES_XML = '''
134 <?xml version="1.0" encoding="utf-8"?>
135 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
136
137 <?include {wix_dir}/guids.wxi ?>
138 <?include {wix_dir}/defines.wxi ?>
139
140 <Fragment>
141 <DirectoryRef Id="INSTALLDIR" FileSource="$(var.SourceDir)">
142 <Directory Id="libdir" Name="lib" FileSource="$(var.SourceDir)/lib">
143 <Component Id="libOutput" Guid="$(var.lib.guid)" Win64='$(var.IsX64)'>
144 </Component>
145 </Directory>
146 </DirectoryRef>
147 </Fragment>
148 </Wix>
149 '''.lstrip()
150
151
152 def make_libraries_xml(wix_dir: pathlib.Path, dist_dir: pathlib.Path):
153 """Make XML data for library components WXS."""
154 # We can't use ElementTree because it doesn't handle the
155 # <?include ?> directives.
156 doc = xml.dom.minidom.parseString(
157 LIBRARIES_XML.format(wix_dir=str(wix_dir)))
158
159 component = doc.getElementsByTagName('Component')[0]
160
161 f = doc.createElement('File')
162 f.setAttribute('Name', 'library.zip')
163 f.setAttribute('KeyPath', 'yes')
164 component.appendChild(f)
165
166 lib_dir = dist_dir / 'lib'
167
168 for p in sorted(lib_dir.iterdir()):
169 if not p.name.endswith(('.dll', '.pyd')):
170 continue
171
172 f = doc.createElement('File')
173 f.setAttribute('Name', p.name)
174 component.appendChild(f)
175
176 return doc.toprettyxml()
177
178
131 179 def build_installer(source_dir: pathlib.Path, python_exe: pathlib.Path,
132 180 msi_name='mercurial', version=None, post_build_fn=None):
133 181 """Build a WiX MSI installer.
@@ -181,6 +229,17 b' def build_installer(source_dir: pathlib.'
181 229 wxs_source_dir = source_dir / rel_path
182 230 run_candle(wix_path, build_dir, wxs, wxs_source_dir, defines=defines)
183 231
232 # candle.exe doesn't like when we have an open handle on the file.
233 # So use TemporaryDirectory() instead of NamedTemporaryFile().
234 with tempfile.TemporaryDirectory() as td:
235 td = pathlib.Path(td)
236
237 tf = td / 'library.wxs'
238 with tf.open('w') as fh:
239 fh.write(make_libraries_xml(wix_dir, dist_dir))
240
241 run_candle(wix_path, build_dir, tf, dist_dir, defines=defines)
242
184 243 source = wix_dir / 'mercurial.wxs'
185 244 defines['Version'] = version
186 245 defines['Comments'] = 'Installs Mercurial version %s' % version
@@ -204,7 +263,10 b' def build_installer(source_dir: pathlib.'
204 263 assert source.endswith('.wxs')
205 264 args.append(str(build_dir / ('%s.wixobj' % source[:-4])))
206 265
207 args.append(str(build_dir / 'mercurial.wixobj'))
266 args.extend([
267 str(build_dir / 'library.wixobj'),
268 str(build_dir / 'mercurial.wixobj'),
269 ])
208 270
209 271 subprocess.run(args, cwd=str(source_dir), check=True)
210 272
@@ -9,35 +9,6 b''
9 9 <Component Id="distOutput" Guid="$(var.dist.guid)" Win64='$(var.IsX64)'>
10 10 <File Name="python27.dll" KeyPath="yes" />
11 11 </Component>
12 <Directory Id="libdir" Name="lib" FileSource="$(var.SourceDir)/lib">
13 <Component Id="libOutput" Guid="$(var.lib.guid)" Win64='$(var.IsX64)'>
14 <File Name="library.zip" KeyPath="yes" />
15 <File Name="mercurial.cext.base85.pyd" />
16 <File Name="mercurial.cext.bdiff.pyd" />
17 <File Name="mercurial.cext.mpatch.pyd" />
18 <File Name="mercurial.cext.osutil.pyd" />
19 <File Name="mercurial.cext.parsers.pyd" />
20 <File Name="mercurial.thirdparty.zope.interface._zope_interface_coptimizations.pyd" />
21 <File Name="mercurial.zstd.pyd" />
22 <File Name="hgext.fsmonitor.pywatchman.bser.pyd" />
23 <File Name="pyexpat.pyd" />
24 <File Name="bz2.pyd" />
25 <File Name="select.pyd" />
26 <File Name="sqlite3.dll" />
27 <File Name="tcl85.dll" />
28 <File Name="tk85.dll" />
29 <File Name="unicodedata.pyd" />
30 <File Name="_ctypes.pyd" />
31 <File Name="_elementtree.pyd" />
32 <File Name="_testcapi.pyd" />
33 <File Name="_hashlib.pyd" />
34 <File Name="_multiprocessing.pyd" />
35 <File Name="_socket.pyd" />
36 <File Name="_sqlite3.pyd" />
37 <File Name="_ssl.pyd" />
38 <File Name="_tkinter.pyd" />
39 </Component>
40 </Directory>
41 12 </DirectoryRef>
42 13 </Fragment>
43 14
General Comments 0
You need to be logged in to leave comments. Login now