10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""distutils.command.bdist_wininst 20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 30a8c90248264a8b26970b4473770bcc3df8515fJosh GaoImplements the Distutils 'bdist_wininst' command: create a windows installer 40a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoexe-program.""" 50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao__revision__ = "$Id$" 70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 80a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys 90a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os 100a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport string 110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 120a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom sysconfig import get_python_version 130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 140a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom distutils.core import Command 150a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom distutils.dir_util import remove_tree 160a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom distutils.errors import DistutilsOptionError, DistutilsPlatformError 170a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom distutils import log 180a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom distutils.util import get_platform 190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 200a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass bdist_wininst (Command): 210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao description = "create an executable installer for MS Windows" 230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao user_options = [('bdist-dir=', None, 250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "temporary directory for creating the distribution"), 260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('plat-name=', 'p', 270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "platform name to embed in generated filenames " 280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "(default: %s)" % get_platform()), 290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('keep-temp', 'k', 300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "keep the pseudo-installation tree around after " + 310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "creating the distribution archive"), 320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('target-version=', None, 330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "require a specific python version" + 340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao " on the target system"), 350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('no-target-compile', 'c', 360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "do not compile .py to .pyc on the target system"), 370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('no-target-optimize', 'o', 380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "do not compile .py to .pyo (optimized)" 390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "on the target system"), 400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('dist-dir=', 'd', 410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "directory to put final built distributions in"), 420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('bitmap=', 'b', 430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "bitmap to use for the installer instead of python-powered logo"), 440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('title=', 't', 450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "title to display on the installer background instead of default"), 460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('skip-build', None, 470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "skip rebuilding everything (for testing/debugging)"), 480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('install-script=', None, 490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "basename of installation script to be run after" 500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "installation or before deinstallation"), 510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('pre-install-script=', None, 520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "Fully qualified filename of a script to be run before " 530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "any files are installed. This script need not be in the " 540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "distribution"), 550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('user-access-control=', None, 560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "specify Vista's UAC handling - 'none'/default=no " 570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "handling, 'auto'=use UAC if target Python installed for " 580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "all users, 'force'=always use UAC"), 590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ] 600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize', 620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 'skip-build'] 630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def initialize_options (self): 650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.bdist_dir = None 660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.plat_name = None 670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.keep_temp = 0 680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.no_target_compile = 0 690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.no_target_optimize = 0 700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.target_version = None 710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.dist_dir = None 720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.bitmap = None 730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.title = None 740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.skip_build = None 750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.install_script = None 760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.pre_install_script = None 770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.user_access_control = None 780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # initialize_options() 800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def finalize_options (self): 830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.set_undefined_options('bdist', ('skip_build', 'skip_build')) 840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.bdist_dir is None: 860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.skip_build and self.plat_name: 870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # If build is skipped and plat_name is overridden, bdist will 880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # not see the correct 'plat_name' - so set that up manually. 890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bdist = self.distribution.get_command_obj('bdist') 900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bdist.plat_name = self.plat_name 910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # next the command will be initialized using that name 920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bdist_base = self.get_finalized_command('bdist').bdist_base 930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.bdist_dir = os.path.join(bdist_base, 'wininst') 940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not self.target_version: 960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.target_version = "" 970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not self.skip_build and self.distribution.has_ext_modules(): 990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao short_version = get_python_version() 1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.target_version and self.target_version != short_version: 1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise DistutilsOptionError, \ 1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "target version can only be %s, or the '--skip-build'" \ 1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao " option must be specified" % (short_version,) 1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.target_version = short_version 1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.set_undefined_options('bdist', 1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('dist_dir', 'dist_dir'), 1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ('plat_name', 'plat_name'), 1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.install_script: 1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for script in self.distribution.scripts: 1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.install_script == os.path.basename(script): 1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao break 1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise DistutilsOptionError, \ 1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "install_script '%s' not found in scripts" % \ 1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.install_script 1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # finalize_options() 1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def run (self): 1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if (sys.platform != "win32" and 1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao (self.distribution.has_ext_modules() or 1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.distribution.has_c_libraries())): 1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise DistutilsPlatformError \ 1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ("distribution contains extensions and/or C libraries; " 1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "must be compiled on a Windows 32 platform") 1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not self.skip_build: 1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.run_command('build') 1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install = self.reinitialize_command('install', reinit_subcommands=1) 1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install.root = self.bdist_dir 1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install.skip_build = self.skip_build 1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install.warn_dir = 0 1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install.plat_name = self.plat_name 1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install_lib = self.reinitialize_command('install_lib') 1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # we do not want to include pyc or pyo files 1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install_lib.compile = 0 1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install_lib.optimize = 0 1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.distribution.has_ext_modules(): 1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # If we are building an installer for a Python version other 1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # than the one we are currently running, then we need to ensure 1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # our build_lib reflects the other Python version rather than ours. 1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Note that for target_version!=sys.version, we must have skipped the 1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # build step, so there is no issue with enforcing the build of this 1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # version. 1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao target_version = self.target_version 1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not target_version: 1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao assert self.skip_build, "Should have already checked this" 1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao target_version = sys.version[0:3] 1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao plat_specifier = ".%s-%s" % (self.plat_name, target_version) 1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao build = self.get_finalized_command('build') 1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao build.build_lib = os.path.join(build.build_base, 1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 'lib' + plat_specifier) 1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Use a custom scheme for the zip-file, because we have to decide 1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # at installation time which scheme to use. 1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'): 1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao value = string.upper(key) 1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if key == 'headers': 1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao value = value + '/Include/$dist_name' 1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao setattr(install, 1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 'install_' + key, 1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao value) 1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao log.info("installing to %s", self.bdist_dir) 1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install.ensure_finalized() 1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # avoid warning of 'install_lib' about installing 1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # into a directory not in sys.path 1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB')) 1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao install.run() 1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao del sys.path[0] 1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # And make an archive relative to the root of the 1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # pseudo-installation tree. 1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from tempfile import mktemp 1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao archive_basename = mktemp() 1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao fullname = self.distribution.get_fullname() 1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao arcname = self.make_archive(archive_basename, "zip", 1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao root_dir=self.bdist_dir) 1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # create an exe containing the zip-file 1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.create_exe(arcname, fullname, self.bitmap) 1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.distribution.has_ext_modules(): 1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pyversion = get_python_version() 1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pyversion = 'any' 1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.distribution.dist_files.append(('bdist_wininst', pyversion, 1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.get_installer_filename(fullname))) 1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # remove the zip-file again 1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao log.debug("removing temporary file '%s'", arcname) 1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao os.remove(arcname) 1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not self.keep_temp: 2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao remove_tree(self.bdist_dir, dry_run=self.dry_run) 2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # run() 2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def get_inidata (self): 2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Return data describing the installation. 2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines = [] 2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao metadata = self.distribution.metadata 2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Write the [metadata] section. 2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("[metadata]") 2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 'info' will be displayed in the installer's dialog box, 2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # describing the items to be installed. 2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao info = (metadata.long_description or '') + '\n' 2170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Escape newline characters 2190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def escape(s): 2200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return string.replace(s, "\n", "\\n") 2210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for name in ["author", "author_email", "description", "maintainer", 2230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "maintainer_email", "name", "url", "version"]: 2240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao data = getattr(metadata, name, "") 2250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if data: 2260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao info = info + ("\n %s: %s" % \ 2270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao (string.capitalize(name), escape(data))) 2280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("%s=%s" % (name, escape(data))) 2290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # The [setup] section contains entries controlling 2310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # the installer runtime. 2320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("\n[Setup]") 2330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.install_script: 2340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("install_script=%s" % self.install_script) 2350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("info=%s" % escape(info)) 2360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("target_compile=%d" % (not self.no_target_compile)) 2370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("target_optimize=%d" % (not self.no_target_optimize)) 2380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.target_version: 2390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("target_version=%s" % self.target_version) 2400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.user_access_control: 2410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("user_access_control=%s" % self.user_access_control) 2420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao title = self.title or self.distribution.get_fullname() 2440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("title=%s" % escape(title)) 2450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import time 2460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import distutils 2470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao build_info = "Built %s with distutils-%s" % \ 2480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao (time.ctime(time.time()), distutils.__version__) 2490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao lines.append("build_info=%s" % build_info) 2500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return string.join(lines, "\n") 2510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # get_inidata() 2530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def create_exe (self, arcname, fullname, bitmap=None): 2550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import struct 2560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.mkpath(self.dist_dir) 2580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao cfgdata = self.get_inidata() 2600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao installer_name = self.get_installer_filename(fullname) 2620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.announce("creating %s" % installer_name) 2630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if bitmap: 2650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bitmapdata = open(bitmap, "rb").read() 2660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bitmaplen = len(bitmapdata) 2670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 2680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bitmaplen = 0 2690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao file = open(installer_name, "wb") 2710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao file.write(self.get_exe_bytes()) 2720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if bitmap: 2730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao file.write(bitmapdata) 2740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Convert cfgdata from unicode to ascii, mbcs encoded 2760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 2770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao unicode 2780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except NameError: 2790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pass 2800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 2810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if isinstance(cfgdata, unicode): 2820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao cfgdata = cfgdata.encode("mbcs") 2830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Append the pre-install script 2850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao cfgdata = cfgdata + "\0" 2860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.pre_install_script: 2870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao script_data = open(self.pre_install_script, "r").read() 2880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao cfgdata = cfgdata + script_data + "\n\0" 2890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 2900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # empty pre-install script 2910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao cfgdata = cfgdata + "\0" 2920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao file.write(cfgdata) 2930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # The 'magic number' 0x1234567B is used to make sure that the 2950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # binary layout of 'cfgdata' is what the wininst.exe binary 2960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # expects. If the layout changes, increment that number, make 2970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # the corresponding changes to the wininst.exe sources, and 2980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # recompile them. 2990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao header = struct.pack("<iii", 3000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 0x1234567B, # tag 3010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao len(cfgdata), # length 3020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bitmaplen, # number of bytes in bitmap 3030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 3040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao file.write(header) 3050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao file.write(open(arcname, "rb").read()) 3060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # create_exe() 3080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def get_installer_filename(self, fullname): 3100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Factored out to allow overriding in subclasses 3110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.target_version: 3120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # if we create an installer for a specific python version, 3130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # it's better to include this in the name 3140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao installer_name = os.path.join(self.dist_dir, 3150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "%s.%s-py%s.exe" % 3160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao (fullname, self.plat_name, self.target_version)) 3170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 3180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao installer_name = os.path.join(self.dist_dir, 3190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "%s.%s.exe" % (fullname, self.plat_name)) 3200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return installer_name 3210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # get_installer_filename() 3220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def get_exe_bytes (self): 3240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from distutils.msvccompiler import get_build_version 3250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # If a target-version other than the current version has been 3260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # specified, then using the MSVC version from *this* build is no good. 3270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Without actually finding and executing the target version and parsing 3280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # its sys.version, we just hard-code our knowledge of old versions. 3290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # NOTE: Possible alternative is to allow "--target-version" to 3300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # specify a Python executable rather than a simple version string. 3310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # We can then execute this program to obtain any info we need, such 3320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # as the real sys.version string for the build. 3330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao cur_version = get_python_version() 3340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.target_version and self.target_version != cur_version: 3350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # If the target version is *later* than us, then we assume they 3360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # use what we use 3370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # string compares seem wrong, but are what sysconfig.py itself uses 3380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.target_version > cur_version: 3390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bv = get_build_version() 3400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 3410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.target_version < "2.4": 3420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bv = 6.0 3430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 3440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bv = 7.1 3450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 3460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # for current version - use authoritative check. 3470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bv = get_build_version() 3480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # wininst-x.y.exe is in the same directory as this file 3500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao directory = os.path.dirname(__file__) 3510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # we must use a wininst-x.y.exe built with the same C compiler 3520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # used for python. XXX What about mingw, borland, and so on? 3530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # if plat_name starts with "win" but is not "win32" 3550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # we want to strip "win" and leave the rest (e.g. -amd64) 3560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # for all other cases, we don't want any suffix 3570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.plat_name != 'win32' and self.plat_name[:3] == 'win': 3580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sfix = self.plat_name[3:] 3590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 3600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sfix = '' 3610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix)) 3630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao f = open(filename, "rb") 3640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 3650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return f.read() 3660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao finally: 3670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao f.close() 3680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# class bdist_wininst 369