]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Lib/distutils/command/bdist_wininst.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / distutils / command / bdist_wininst.py
CommitLineData
4710c53d 1"""distutils.command.bdist_wininst\r
2\r
3Implements the Distutils 'bdist_wininst' command: create a windows installer\r
4exe-program."""\r
5\r
6__revision__ = "$Id$"\r
7\r
8import sys\r
9import os\r
10import string\r
11\r
12from sysconfig import get_python_version\r
13\r
14from distutils.core import Command\r
15from distutils.dir_util import remove_tree\r
16from distutils.errors import DistutilsOptionError, DistutilsPlatformError\r
17from distutils import log\r
18from distutils.util import get_platform\r
19\r
20class bdist_wininst (Command):\r
21\r
22 description = "create an executable installer for MS Windows"\r
23\r
24 user_options = [('bdist-dir=', None,\r
25 "temporary directory for creating the distribution"),\r
26 ('plat-name=', 'p',\r
27 "platform name to embed in generated filenames "\r
28 "(default: %s)" % get_platform()),\r
29 ('keep-temp', 'k',\r
30 "keep the pseudo-installation tree around after " +\r
31 "creating the distribution archive"),\r
32 ('target-version=', None,\r
33 "require a specific python version" +\r
34 " on the target system"),\r
35 ('no-target-compile', 'c',\r
36 "do not compile .py to .pyc on the target system"),\r
37 ('no-target-optimize', 'o',\r
38 "do not compile .py to .pyo (optimized)"\r
39 "on the target system"),\r
40 ('dist-dir=', 'd',\r
41 "directory to put final built distributions in"),\r
42 ('bitmap=', 'b',\r
43 "bitmap to use for the installer instead of python-powered logo"),\r
44 ('title=', 't',\r
45 "title to display on the installer background instead of default"),\r
46 ('skip-build', None,\r
47 "skip rebuilding everything (for testing/debugging)"),\r
48 ('install-script=', None,\r
49 "basename of installation script to be run after"\r
50 "installation or before deinstallation"),\r
51 ('pre-install-script=', None,\r
52 "Fully qualified filename of a script to be run before "\r
53 "any files are installed. This script need not be in the "\r
54 "distribution"),\r
55 ('user-access-control=', None,\r
56 "specify Vista's UAC handling - 'none'/default=no "\r
57 "handling, 'auto'=use UAC if target Python installed for "\r
58 "all users, 'force'=always use UAC"),\r
59 ]\r
60\r
61 boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',\r
62 'skip-build']\r
63\r
64 def initialize_options (self):\r
65 self.bdist_dir = None\r
66 self.plat_name = None\r
67 self.keep_temp = 0\r
68 self.no_target_compile = 0\r
69 self.no_target_optimize = 0\r
70 self.target_version = None\r
71 self.dist_dir = None\r
72 self.bitmap = None\r
73 self.title = None\r
74 self.skip_build = 0\r
75 self.install_script = None\r
76 self.pre_install_script = None\r
77 self.user_access_control = None\r
78\r
79 # initialize_options()\r
80\r
81\r
82 def finalize_options (self):\r
83 if self.bdist_dir is None:\r
84 if self.skip_build and self.plat_name:\r
85 # If build is skipped and plat_name is overridden, bdist will\r
86 # not see the correct 'plat_name' - so set that up manually.\r
87 bdist = self.distribution.get_command_obj('bdist')\r
88 bdist.plat_name = self.plat_name\r
89 # next the command will be initialized using that name\r
90 bdist_base = self.get_finalized_command('bdist').bdist_base\r
91 self.bdist_dir = os.path.join(bdist_base, 'wininst')\r
92 if not self.target_version:\r
93 self.target_version = ""\r
94 if not self.skip_build and self.distribution.has_ext_modules():\r
95 short_version = get_python_version()\r
96 if self.target_version and self.target_version != short_version:\r
97 raise DistutilsOptionError, \\r
98 "target version can only be %s, or the '--skip-build'" \\r
99 " option must be specified" % (short_version,)\r
100 self.target_version = short_version\r
101\r
102 self.set_undefined_options('bdist',\r
103 ('dist_dir', 'dist_dir'),\r
104 ('plat_name', 'plat_name'),\r
105 )\r
106\r
107 if self.install_script:\r
108 for script in self.distribution.scripts:\r
109 if self.install_script == os.path.basename(script):\r
110 break\r
111 else:\r
112 raise DistutilsOptionError, \\r
113 "install_script '%s' not found in scripts" % \\r
114 self.install_script\r
115 # finalize_options()\r
116\r
117\r
118 def run (self):\r
119 if (sys.platform != "win32" and\r
120 (self.distribution.has_ext_modules() or\r
121 self.distribution.has_c_libraries())):\r
122 raise DistutilsPlatformError \\r
123 ("distribution contains extensions and/or C libraries; "\r
124 "must be compiled on a Windows 32 platform")\r
125\r
126 if not self.skip_build:\r
127 self.run_command('build')\r
128\r
129 install = self.reinitialize_command('install', reinit_subcommands=1)\r
130 install.root = self.bdist_dir\r
131 install.skip_build = self.skip_build\r
132 install.warn_dir = 0\r
133 install.plat_name = self.plat_name\r
134\r
135 install_lib = self.reinitialize_command('install_lib')\r
136 # we do not want to include pyc or pyo files\r
137 install_lib.compile = 0\r
138 install_lib.optimize = 0\r
139\r
140 if self.distribution.has_ext_modules():\r
141 # If we are building an installer for a Python version other\r
142 # than the one we are currently running, then we need to ensure\r
143 # our build_lib reflects the other Python version rather than ours.\r
144 # Note that for target_version!=sys.version, we must have skipped the\r
145 # build step, so there is no issue with enforcing the build of this\r
146 # version.\r
147 target_version = self.target_version\r
148 if not target_version:\r
149 assert self.skip_build, "Should have already checked this"\r
150 target_version = sys.version[0:3]\r
151 plat_specifier = ".%s-%s" % (self.plat_name, target_version)\r
152 build = self.get_finalized_command('build')\r
153 build.build_lib = os.path.join(build.build_base,\r
154 'lib' + plat_specifier)\r
155\r
156 # Use a custom scheme for the zip-file, because we have to decide\r
157 # at installation time which scheme to use.\r
158 for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):\r
159 value = string.upper(key)\r
160 if key == 'headers':\r
161 value = value + '/Include/$dist_name'\r
162 setattr(install,\r
163 'install_' + key,\r
164 value)\r
165\r
166 log.info("installing to %s", self.bdist_dir)\r
167 install.ensure_finalized()\r
168\r
169 # avoid warning of 'install_lib' about installing\r
170 # into a directory not in sys.path\r
171 sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))\r
172\r
173 install.run()\r
174\r
175 del sys.path[0]\r
176\r
177 # And make an archive relative to the root of the\r
178 # pseudo-installation tree.\r
179 from tempfile import mktemp\r
180 archive_basename = mktemp()\r
181 fullname = self.distribution.get_fullname()\r
182 arcname = self.make_archive(archive_basename, "zip",\r
183 root_dir=self.bdist_dir)\r
184 # create an exe containing the zip-file\r
185 self.create_exe(arcname, fullname, self.bitmap)\r
186 if self.distribution.has_ext_modules():\r
187 pyversion = get_python_version()\r
188 else:\r
189 pyversion = 'any'\r
190 self.distribution.dist_files.append(('bdist_wininst', pyversion,\r
191 self.get_installer_filename(fullname)))\r
192 # remove the zip-file again\r
193 log.debug("removing temporary file '%s'", arcname)\r
194 os.remove(arcname)\r
195\r
196 if not self.keep_temp:\r
197 remove_tree(self.bdist_dir, dry_run=self.dry_run)\r
198\r
199 # run()\r
200\r
201 def get_inidata (self):\r
202 # Return data describing the installation.\r
203\r
204 lines = []\r
205 metadata = self.distribution.metadata\r
206\r
207 # Write the [metadata] section.\r
208 lines.append("[metadata]")\r
209\r
210 # 'info' will be displayed in the installer's dialog box,\r
211 # describing the items to be installed.\r
212 info = (metadata.long_description or '') + '\n'\r
213\r
214 # Escape newline characters\r
215 def escape(s):\r
216 return string.replace(s, "\n", "\\n")\r
217\r
218 for name in ["author", "author_email", "description", "maintainer",\r
219 "maintainer_email", "name", "url", "version"]:\r
220 data = getattr(metadata, name, "")\r
221 if data:\r
222 info = info + ("\n %s: %s" % \\r
223 (string.capitalize(name), escape(data)))\r
224 lines.append("%s=%s" % (name, escape(data)))\r
225\r
226 # The [setup] section contains entries controlling\r
227 # the installer runtime.\r
228 lines.append("\n[Setup]")\r
229 if self.install_script:\r
230 lines.append("install_script=%s" % self.install_script)\r
231 lines.append("info=%s" % escape(info))\r
232 lines.append("target_compile=%d" % (not self.no_target_compile))\r
233 lines.append("target_optimize=%d" % (not self.no_target_optimize))\r
234 if self.target_version:\r
235 lines.append("target_version=%s" % self.target_version)\r
236 if self.user_access_control:\r
237 lines.append("user_access_control=%s" % self.user_access_control)\r
238\r
239 title = self.title or self.distribution.get_fullname()\r
240 lines.append("title=%s" % escape(title))\r
241 import time\r
242 import distutils\r
243 build_info = "Built %s with distutils-%s" % \\r
244 (time.ctime(time.time()), distutils.__version__)\r
245 lines.append("build_info=%s" % build_info)\r
246 return string.join(lines, "\n")\r
247\r
248 # get_inidata()\r
249\r
250 def create_exe (self, arcname, fullname, bitmap=None):\r
251 import struct\r
252\r
253 self.mkpath(self.dist_dir)\r
254\r
255 cfgdata = self.get_inidata()\r
256\r
257 installer_name = self.get_installer_filename(fullname)\r
258 self.announce("creating %s" % installer_name)\r
259\r
260 if bitmap:\r
261 bitmapdata = open(bitmap, "rb").read()\r
262 bitmaplen = len(bitmapdata)\r
263 else:\r
264 bitmaplen = 0\r
265\r
266 file = open(installer_name, "wb")\r
267 file.write(self.get_exe_bytes())\r
268 if bitmap:\r
269 file.write(bitmapdata)\r
270\r
271 # Convert cfgdata from unicode to ascii, mbcs encoded\r
272 try:\r
273 unicode\r
274 except NameError:\r
275 pass\r
276 else:\r
277 if isinstance(cfgdata, unicode):\r
278 cfgdata = cfgdata.encode("mbcs")\r
279\r
280 # Append the pre-install script\r
281 cfgdata = cfgdata + "\0"\r
282 if self.pre_install_script:\r
283 script_data = open(self.pre_install_script, "r").read()\r
284 cfgdata = cfgdata + script_data + "\n\0"\r
285 else:\r
286 # empty pre-install script\r
287 cfgdata = cfgdata + "\0"\r
288 file.write(cfgdata)\r
289\r
290 # The 'magic number' 0x1234567B is used to make sure that the\r
291 # binary layout of 'cfgdata' is what the wininst.exe binary\r
292 # expects. If the layout changes, increment that number, make\r
293 # the corresponding changes to the wininst.exe sources, and\r
294 # recompile them.\r
295 header = struct.pack("<iii",\r
296 0x1234567B, # tag\r
297 len(cfgdata), # length\r
298 bitmaplen, # number of bytes in bitmap\r
299 )\r
300 file.write(header)\r
301 file.write(open(arcname, "rb").read())\r
302\r
303 # create_exe()\r
304\r
305 def get_installer_filename(self, fullname):\r
306 # Factored out to allow overriding in subclasses\r
307 if self.target_version:\r
308 # if we create an installer for a specific python version,\r
309 # it's better to include this in the name\r
310 installer_name = os.path.join(self.dist_dir,\r
311 "%s.%s-py%s.exe" %\r
312 (fullname, self.plat_name, self.target_version))\r
313 else:\r
314 installer_name = os.path.join(self.dist_dir,\r
315 "%s.%s.exe" % (fullname, self.plat_name))\r
316 return installer_name\r
317 # get_installer_filename()\r
318\r
319 def get_exe_bytes (self):\r
320 from distutils.msvccompiler import get_build_version\r
321 # If a target-version other than the current version has been\r
322 # specified, then using the MSVC version from *this* build is no good.\r
323 # Without actually finding and executing the target version and parsing\r
324 # its sys.version, we just hard-code our knowledge of old versions.\r
325 # NOTE: Possible alternative is to allow "--target-version" to\r
326 # specify a Python executable rather than a simple version string.\r
327 # We can then execute this program to obtain any info we need, such\r
328 # as the real sys.version string for the build.\r
329 cur_version = get_python_version()\r
330 if self.target_version and self.target_version != cur_version:\r
331 # If the target version is *later* than us, then we assume they\r
332 # use what we use\r
333 # string compares seem wrong, but are what sysconfig.py itself uses\r
334 if self.target_version > cur_version:\r
335 bv = get_build_version()\r
336 else:\r
337 if self.target_version < "2.4":\r
338 bv = 6.0\r
339 else:\r
340 bv = 7.1\r
341 else:\r
342 # for current version - use authoritative check.\r
343 bv = get_build_version()\r
344\r
345 # wininst-x.y.exe is in the same directory as this file\r
346 directory = os.path.dirname(__file__)\r
347 # we must use a wininst-x.y.exe built with the same C compiler\r
348 # used for python. XXX What about mingw, borland, and so on?\r
349\r
350 # if plat_name starts with "win" but is not "win32"\r
351 # we want to strip "win" and leave the rest (e.g. -amd64)\r
352 # for all other cases, we don't want any suffix\r
353 if self.plat_name != 'win32' and self.plat_name[:3] == 'win':\r
354 sfix = self.plat_name[3:]\r
355 else:\r
356 sfix = ''\r
357\r
358 filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix))\r
359 f = open(filename, "rb")\r
360 try:\r
361 return f.read()\r
362 finally:\r
363 f.close()\r
364# class bdist_wininst\r