64 bit windows msi builds, though it's still picking up the 32 bit paths for some reason. Sigh.

This commit is contained in:
Kovid Goyal 2012-11-30 18:19:12 +05:30
parent ba83fb26f3
commit c1dd30004e
7 changed files with 110 additions and 70 deletions

View File

@ -215,6 +215,8 @@ class Command(object):
sys.stdout.flush() sys.stdout.flush()
def installer_name(ext, is64bit=False): def installer_name(ext, is64bit=False):
if is64bit and ext == 'msi':
return 'dist/%s-64bit-%s.msi'%(__appname__, __version__)
if ext in ('exe', 'msi'): if ext in ('exe', 'msi'):
return 'dist/%s-%s.%s'%(__appname__, __version__, ext) return 'dist/%s-%s.%s'%(__appname__, __version__, ext)
if ext == 'dmg': if ext == 'dmg':

View File

@ -20,7 +20,7 @@ __all__ = [
'upload_user_manual', 'upload_demo', 'reupload', 'upload_user_manual', 'upload_demo', 'reupload',
'linux32', 'linux64', 'linux', 'linux_freeze', 'linux32', 'linux64', 'linux', 'linux_freeze',
'osx32_freeze', 'osx', 'rsync', 'push', 'osx32_freeze', 'osx', 'rsync', 'push',
'win32_freeze', 'win32', 'win', 'win32_freeze', 'win32', 'win64', 'win',
'stage1', 'stage2', 'stage3', 'stage4', 'stage5', 'publish' 'stage1', 'stage2', 'stage3', 'stage4', 'stage5', 'publish'
] ]
@ -91,9 +91,10 @@ osx = OSX()
from setup.installer.osx.app.main import OSX32_Freeze from setup.installer.osx.app.main import OSX32_Freeze
osx32_freeze = OSX32_Freeze() osx32_freeze = OSX32_Freeze()
from setup.installer.windows import Win, Win32 from setup.installer.windows import Win, Win32, Win64
win = Win() win = Win()
win32 = Win32() win32 = Win32()
win64 = Win64()
from setup.installer.windows.freeze import Win32Freeze from setup.installer.windows.freeze import Win32Freeze
win32_freeze = Win32Freeze() win32_freeze = Win32Freeze()

View File

@ -20,20 +20,21 @@ class Win(Command):
def run(self, opts): def run(self, opts):
pass pass
class WinBase(VMInstaller):
class Win32(VMInstaller):
description = 'Build 32bit windows binary installer'
INSTALLER_EXT = 'exe'
VM_NAME = 'xp_build'
VM = '/vmware/bin/%s'%VM_NAME
VM_CHECK = 'calibre_windows_xp_home'
FREEZE_COMMAND = 'win32_freeze' FREEZE_COMMAND = 'win32_freeze'
FREEZE_TEMPLATE = 'python -OO setup.py {freeze_command} --no-ice' FREEZE_TEMPLATE = 'python -OO setup.py {freeze_command} --no-ice'
INSTALLER_EXT = 'msi' INSTALLER_EXT = 'msi'
SHUTDOWN_CMD = ['shutdown.exe', '-s', '-f', '-t', '0'] SHUTDOWN_CMD = ['shutdown.exe', '-s', '-f', '-t', '0']
class Win32(WinBase):
description = 'Build 32bit windows binary installer'
VM_NAME = 'xp_build'
VM = '/vmware/bin/%s'%VM_NAME
VM_CHECK = 'calibre_windows_xp_home'
def sign_msi(self): def sign_msi(self):
print ('Signing installers ...') print ('Signing installers ...')
subprocess.check_call(['ssh', self.VM_NAME, '~/sign.sh'], shell=False) subprocess.check_call(['ssh', self.VM_NAME, '~/sign.sh'], shell=False)
@ -57,4 +58,19 @@ class Win32(VMInstaller):
self.warn('Failed to get portable installer') self.warn('Failed to get portable installer')
raise SystemExit(1) raise SystemExit(1)
class Win64(WinBase):
description = 'Build 64bit windows binary installer'
VM_NAME = 'win64'
VM = '/vmware/bin/%s'%VM_NAME
VM_CHECK = 'win64'
IS_64_BIT = True
BUILD_PREFIX = WinBase.BUILD_PREFIX + [
'if [ -f "$HOME/.bash_profile" ] ; then',
' source "$HOME/.bash_profile"',
'fi',
]

View File

@ -25,6 +25,7 @@ LZMA = r'Q:\easylzma\build\easylzma-0.0.8'
VERSION = re.sub('[a-z]\d+', '', __version__) VERSION = re.sub('[a-z]\d+', '', __version__)
WINVER = VERSION+'.0' WINVER = VERSION+'.0'
machine = 'X64' if is64bit else 'X86'
DESCRIPTIONS = { DESCRIPTIONS = {
'calibre' : 'The main calibre program', 'calibre' : 'The main calibre program',
@ -132,6 +133,22 @@ class Win32Freeze(Command, WixMixIn):
# used instead # used instead
shutil.copy2(f, tgt) shutil.copy2(f, tgt)
def fix_pyd_bootstraps_in(self, crypto_dir):
for dirpath, dirnames, filenames in os.walk(crypto_dir):
for f in filenames:
name, ext = os.path.splitext(f)
if ext == '.pyd':
with open(self.j(dirpath, name+'.py')) as f:
raw = f.read().strip()
if (not raw.startswith('def __bootstrap__') or not
raw.endswith('__bootstrap__()')):
raise Exception('The file %r has non'
' bootstrap code'%self.j(dirpath, f))
for ext in ('.py', '.pyc', '.pyo'):
x = self.j(dirpath, name+ext)
if os.path.exists(x):
os.remove(x)
def freeze(self): def freeze(self):
shutil.copy2(self.j(self.src_root, 'LICENSE'), self.base) shutil.copy2(self.j(self.src_root, 'LICENSE'), self.base)
@ -184,23 +201,11 @@ class Win32Freeze(Command, WixMixIn):
shutil.copytree(self.j(comext, 'shell'), self.j(sp_dir, 'win32com', 'shell')) shutil.copytree(self.j(comext, 'shell'), self.j(sp_dir, 'win32com', 'shell'))
shutil.rmtree(comext) shutil.rmtree(comext)
# Fix PyCrypto, removing the bootstrap .py modules that load the .pyd # Fix PyCrypto and Pillow, removing the bootstrap .py modules that load
# modules, since they do not work when in a zip file # the .pyd modules, since they do not work when in a zip file
for crypto_dir in glob.glob(self.j(sp_dir, 'pycrypto-*', 'Crypto')): for crypto_dir in glob.glob(self.j(sp_dir, 'pycrypto-*', 'Crypto')
for dirpath, dirnames, filenames in os.walk(crypto_dir): ) + glob.glob(self.j(sp_dir, 'Pillow-*')):
for f in filenames: self.fix_pyd_bootstraps_in(crypto_dir)
name, ext = os.path.splitext(f)
if ext == '.pyd':
with open(self.j(dirpath, name+'.py')) as f:
raw = f.read().strip()
if (not raw.startswith('def __bootstrap__') or not
raw.endswith('__bootstrap__()')):
raise Exception('The PyCrypto file %r has non'
' bootstrap code'%self.j(dirpath, f))
for ext in ('.py', '.pyc', '.pyo'):
x = self.j(dirpath, name+ext)
if os.path.exists(x):
os.remove(x)
for pat in (r'PyQt4\uic\port_v3', ): for pat in (r'PyQt4\uic\port_v3', ):
x = glob.glob(self.j(self.lib_dir, 'site-packages', pat))[0] x = glob.glob(self.j(self.lib_dir, 'site-packages', pat))[0]
@ -401,7 +406,7 @@ class Win32Freeze(Command, WixMixIn):
exe = self.j('dist', 'calibre-portable-installer-%s.exe'%VERSION) exe = self.j('dist', 'calibre-portable-installer-%s.exe'%VERSION)
if self.newer(exe, [obj, xobj]): if self.newer(exe, [obj, xobj]):
self.info('Linking', exe) self.info('Linking', exe)
cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:X86', cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:'+machine,
'/LIBPATH:'+self.obj_dir, '/SUBSYSTEM:WINDOWS', '/LIBPATH:'+self.obj_dir, '/SUBSYSTEM:WINDOWS',
'/LIBPATH:'+(LZMA+r'\lib\Release'), '/LIBPATH:'+(LZMA+r'\lib\Release'),
'/RELEASE', '/MANIFEST', '/MANIFESTUAC:level="asInvoker" uiAccess="false"', '/RELEASE', '/MANIFEST', '/MANIFESTUAC:level="asInvoker" uiAccess="false"',
@ -458,7 +463,7 @@ class Win32Freeze(Command, WixMixIn):
exe = self.j(base, 'calibre-portable.exe') exe = self.j(base, 'calibre-portable.exe')
if self.newer(exe, [obj]): if self.newer(exe, [obj]):
self.info('Linking', exe) self.info('Linking', exe)
cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:X86', cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:'+machine,
'/LIBPATH:'+self.obj_dir, '/SUBSYSTEM:WINDOWS', '/LIBPATH:'+self.obj_dir, '/SUBSYSTEM:WINDOWS',
'/RELEASE', '/RELEASE',
'/ENTRY:wWinMainCRTStartup', '/ENTRY:wWinMainCRTStartup',
@ -517,7 +522,7 @@ class Win32Freeze(Command, WixMixIn):
ver = '.'.join(__version__.split('.')[:2]) ver = '.'.join(__version__.split('.')[:2])
if self.newer(dll, objects): if self.newer(dll, objects):
cmd = [msvc.linker, '/DLL', '/INCREMENTAL:NO', '/VERSION:'+ver, cmd = [msvc.linker, '/DLL', '/INCREMENTAL:NO', '/VERSION:'+ver,
'/OUT:'+dll, '/nologo', '/MACHINE:X86'] + objects + \ '/OUT:'+dll, '/nologo', '/MACHINE:'+machine] + objects + \
[self.embed_resources(dll), [self.embed_resources(dll),
'/LIBPATH:C:/Python%s/libs'%self.py_ver, '/LIBPATH:C:/Python%s/libs'%self.py_ver,
'python%s.lib'%self.py_ver, 'python%s.lib'%self.py_ver,
@ -547,7 +552,7 @@ class Win32Freeze(Command, WixMixIn):
lib = dll.replace('.dll', '.lib') lib = dll.replace('.dll', '.lib')
if self.newer(exe, [dest, lib, self.rc_template, __file__]): if self.newer(exe, [dest, lib, self.rc_template, __file__]):
self.info('Linking', bname) self.info('Linking', bname)
cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:X86', cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:'+machine,
'/LIBPATH:'+self.obj_dir, '/SUBSYSTEM:'+subsys, '/LIBPATH:'+self.obj_dir, '/SUBSYSTEM:'+subsys,
'/LIBPATH:C:/Python%s/libs'%self.py_ver, '/RELEASE', '/LIBPATH:C:/Python%s/libs'%self.py_ver, '/RELEASE',
'/OUT:'+exe, self.embed_resources(exe), '/OUT:'+exe, self.embed_resources(exe),
@ -581,7 +586,8 @@ class Win32Freeze(Command, WixMixIn):
sp = self.j(self.lib_dir, 'site-packages') sp = self.j(self.lib_dir, 'site-packages')
# Special handling for PIL and pywin32 # Special handling for PIL and pywin32
handled = set(['PIL.pth', 'pywin32.pth', 'PIL', 'win32']) handled = set(['PIL.pth', 'pywin32.pth', 'PIL', 'win32'])
self.add_to_zipfile(zf, 'PIL', sp) if not is64bit:
self.add_to_zipfile(zf, 'PIL', sp)
base = self.j(sp, 'win32', 'lib') base = self.j(sp, 'win32', 'lib')
for x in os.listdir(base): for x in os.listdir(base):
if os.path.splitext(x)[1] not in ('.exe',): if os.path.splitext(x)[1] not in ('.exe',):
@ -593,16 +599,17 @@ class Win32Freeze(Command, WixMixIn):
self.add_to_zipfile(zf, x, base) self.add_to_zipfile(zf, x, base)
handled.add('easy-install.pth') handled.add('easy-install.pth')
# We dont want the site.py from site-packages
handled.add('site.pyo')
for d in self.get_pth_dirs(self.j(sp, 'easy-install.pth')): for d in self.get_pth_dirs(self.j(sp, 'easy-install.pth')):
handled.add(self.b(d)) handled.add(self.b(d))
for x in os.listdir(d): for x in os.listdir(d):
if x == 'EGG-INFO': if x in {'EGG-INFO', 'site.py', 'site.pyc', 'site.pyo'}:
continue continue
self.add_to_zipfile(zf, x, d) self.add_to_zipfile(zf, x, d)
# The rest of site-packages # The rest of site-packages
# We dont want the site.py from site-packages
handled.add('site.pyo')
for x in os.listdir(sp): for x in os.listdir(sp):
if x in handled or x.endswith('.egg-info'): if x in handled or x.endswith('.egg-info'):
continue continue
@ -622,8 +629,10 @@ class Win32Freeze(Command, WixMixIn):
line = line.strip() line = line.strip()
if not line or line.startswith('#') or line.startswith('import'): if not line or line.startswith('#') or line.startswith('import'):
continue continue
candidate = self.j(base, line) candidate = os.path.abspath(self.j(base, line))
if os.path.exists(candidate): if os.path.exists(candidate):
if not os.path.isdir(candidate):
raise ValueError('%s is not a directory'%candidate)
yield candidate yield candidate
def add_to_zipfile(self, zf, name, base, exclude=frozenset()): def add_to_zipfile(self, zf, name, base, exclude=frozenset()):

View File

@ -109,10 +109,8 @@ of mimetypes from the windows registry
Python packages Python packages
------------------ ------------------
Install setuptools from http://pypi.python.org/pypi/setuptools If there are no Install setuptools from http://pypi.python.org/pypi/setuptools. Use the source
windows binaries already compiled for the version of python you are using then tarball. Edit setup.py and set zip_safe=False. Then run::
download the source and run the following command in the folder where the
source has been unpacked::
python setup.py install python setup.py install

View File

@ -2,13 +2,13 @@
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi' xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi' xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
> >
<Product Name='{app}' Id='*' UpgradeCode='{upgrade_code}' <Product Name='{app}{x64}' Id='*' UpgradeCode='{upgrade_code}'
Language='1033' Codepage='1252' Version='{version}' Manufacturer='Kovid Goyal'> Language='1033' Codepage='1252' Version='{version}' Manufacturer='Kovid Goyal'>
<Package Id='*' Keywords='Installer' Description="{app} Installer" <Package Id='*' Keywords='Installer' Description="{app} Installer"
Comments='{app} is a registered trademark of Kovid Goyal' Manufacturer='Kovid Goyal' Comments='{app} is a registered trademark of Kovid Goyal' Manufacturer='Kovid Goyal'
InstallerVersion='300' Languages='1033' Compressed='yes' InstallerVersion='300' Languages='1033' Compressed='yes'
SummaryCodepage='1252' /> SummaryCodepage='1252' />
<Media Id="1" Cabinet="{app}.cab" CompressionLevel="{compression}" EmbedCab="yes" /> <Media Id="1" Cabinet="{app}.cab" CompressionLevel="{compression}" EmbedCab="yes" />
<!-- The following line ensures that DLLs are replaced even if their version is the same as before. This <!-- The following line ensures that DLLs are replaced even if their version is the same as before. This
@ -33,15 +33,15 @@
<Property Id="APPLICATIONFOLDER"> <Property Id="APPLICATIONFOLDER">
<RegistrySearch Id='calibreInstDir' Type='raw' <RegistrySearch Id='calibreInstDir' Type='raw'
Root='HKLM' Key="Software\{app}\Installer" Name="InstallPath" /> Root='HKLM' Key="Software\{app}{x64}\Installer" Name="InstallPath" />
</Property> </Property>
<Directory Id='TARGETDIR' Name='SourceDir'> <Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'> <Directory Id='{ProgramFilesFolder}' Name='PFiles'>
<Directory Id='APPLICATIONFOLDER' Name='{app}' /> <Directory Id='APPLICATIONFOLDER' Name='{app}' />
</Directory> </Directory>
<Directory Id="ProgramMenuFolder"> <Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="{app} - E-book Management"/> <Directory Id="ApplicationProgramsFolder" Name="{app}{x64} - E-book Management"/>
</Directory> </Directory>
<Directory Id="DesktopFolder" Name="Desktop"/> <Directory Id="DesktopFolder" Name="Desktop"/>
</Directory> </Directory>
@ -50,24 +50,24 @@
{app_components} {app_components}
<Component Id="AddToPath" Guid="*"> <Component Id="AddToPath" Guid="*">
<Environment Id='UpdatePath' Name='PATH' Action='set' System='yes' Part='last' Value='[APPLICATIONFOLDER]' /> <Environment Id='UpdatePath' Name='PATH' Action='set' System='yes' Part='last' Value='[APPLICATIONFOLDER]' />
<RegistryValue Root="HKCU" Key="Software\Microsoft\{app}" Name="system_path_updated" Type="integer" Value="1" KeyPath="yes"/> <RegistryValue Root="HKCU" Key="Software\Microsoft\{app}{x64}" Name="system_path_updated" Type="integer" Value="1" KeyPath="yes"/>
</Component> </Component>
<Component Id="RememberInstallDir" Guid="*"> <Component Id="RememberInstallDir" Guid="*">
<RegistryValue Root="HKLM" Key="Software\{app}\Installer" Name="InstallPath" Type="string" Value="[APPLICATIONFOLDER]" KeyPath="yes"/> <RegistryValue Root="HKLM" Key="Software\{app}{x64}\Installer" Name="InstallPath" Type="string" Value="[APPLICATIONFOLDER]" KeyPath="yes"/>
</Component> </Component>
</DirectoryRef> </DirectoryRef>
<DirectoryRef Id="ApplicationProgramsFolder"> <DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="StartMenuShortcuts" Guid="*"> <Component Id="StartMenuShortcuts" Guid="*">
<Shortcut Id="s1" Name="{app} - E-book management" <Shortcut Id="s1" Name="{app}{x64} - E-book management"
Description="Manage your e-book collection and download news" Description="Manage your e-book collection and download news"
Target="[#{exe_map[calibre]}]" Target="[#{exe_map[calibre]}]"
WorkingDirectory="APPLICATIONROOTDIRECTORY" /> WorkingDirectory="APPLICATIONROOTDIRECTORY" />
<Shortcut Id="s2" Name="E-book viewer" <Shortcut Id="s2" Name="E-book viewer{x64}"
Description="Viewer for all the major e-book formats" Description="Viewer for all the major e-book formats"
Target="[#{exe_map[ebook-viewer]}]" Target="[#{exe_map[ebook-viewer]}]"
WorkingDirectory="APPLICATIONROOTDIRECTORY" /> WorkingDirectory="APPLICATIONROOTDIRECTORY" />
<Shortcut Id="s3" Name="LRF viewer" <Shortcut Id="s3" Name="LRF viewer{x64}"
Description="Viewer for LRF format e-books" Description="Viewer for LRF format e-books"
Target="[#{exe_map[lrfviewer]}]" Target="[#{exe_map[lrfviewer]}]"
WorkingDirectory="APPLICATIONROOTDIRECTORY" /> WorkingDirectory="APPLICATIONROOTDIRECTORY" />
@ -79,17 +79,17 @@
Target="http://calibre-ebook.com/get-involved"/> Target="http://calibre-ebook.com/get-involved"/>
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/> <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\{app}" Name="start_menu_shortcuts_installed" Type="integer" Value="1" KeyPath="yes"/> <RegistryValue Root="HKCU" Key="Software\Microsoft\{app}{x64}" Name="start_menu_shortcuts_installed" Type="integer" Value="1" KeyPath="yes"/>
</Component> </Component>
</DirectoryRef> </DirectoryRef>
<DirectoryRef Id="DesktopFolder"> <DirectoryRef Id="DesktopFolder">
<Component Id="DesktopShortcut" Guid="*"> <Component Id="DesktopShortcut" Guid="*">
<Shortcut Id="ds1" Name="{app} - E-book management" <Shortcut Id="ds1" Name="{app}{x64} - E-book management"
Description="Manage your e-book collection and download news" Description="Manage your e-book collection and download news"
Target="[#{exe_map[calibre]}]" Target="[#{exe_map[calibre]}]"
WorkingDirectory="APPLICATIONROOTDIRECTORY" /> WorkingDirectory="APPLICATIONROOTDIRECTORY" />
<RegistryValue Root="HKCU" Key="Software\Microsoft\{app}" Name="desktop_shortcut_installed" Type="integer" Value="1" KeyPath="yes"/> <RegistryValue Root="HKCU" Key="Software\Microsoft\{app}{x64}" Name="desktop_shortcut_installed" Type="integer" Value="1" KeyPath="yes"/>
</Component> </Component>
</DirectoryRef> </DirectoryRef>
@ -124,8 +124,8 @@
<Property Id="ARPPRODUCTICON" Value="main_icon" /> <Property Id="ARPPRODUCTICON" Value="main_icon" />
<Condition <Condition
Message="This application is only supported on Windows XP SP3, or higher."> Message="This application is only supported on {minverhuman}, or higher.">
<![CDATA[Installed OR (VersionNT >= 501)]]> <![CDATA[Installed OR (VersionNT >= {minver})]]>
</Condition> </Condition>
<InstallExecuteSequence> <InstallExecuteSequence>
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom> <Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>

View File

@ -6,11 +6,20 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os, shutil, subprocess import os, shutil, subprocess, sys
from setup import __appname__, __version__, basenames from setup import __appname__, __version__, basenames
from setup.build_environment import is64bit
if is64bit:
WIXP = r'C:\Program Files (x86)\WiX Toolset v3.6'
UPGRADE_CODE = '5DD881FF-756B-4097-9D82-8C0F11D521EA'
MINVERHUMAN = 'Windows Vista'
else:
WIXP = r'C:\Program Files\Windows Installer XML v3.5'
UPGRADE_CODE = 'BEB2A80D-E902-4DAD-ADF9-8BD2DA42CFE1'
MINVERHUMAN = 'Windows XP SP3'
WIXP = r'C:\Program Files\Windows Installer XML v3.5'
CANDLE = WIXP+r'\bin\candle.exe' CANDLE = WIXP+r'\bin\candle.exe'
LIGHT = WIXP+r'\bin\light.exe' LIGHT = WIXP+r'\bin\light.exe'
@ -27,15 +36,19 @@ class WixMixIn:
components = self.get_components_from_files() components = self.get_components_from_files()
wxs = template.format( wxs = template.format(
app = __appname__, app = __appname__,
version = __version__, version = __version__,
upgrade_code = 'BEB2A80D-E902-4DAD-ADF9-8BD2DA42CFE1', upgrade_code = UPGRADE_CODE,
compression = self.opts.msi_compression, ProgramFilesFolder = 'ProgramFiles64Folder' if is64bit else 'ProgramFilesFolder',
app_components = components, x64 = ' 64bit' if is64bit else '',
exe_map = self.smap, minverhuman = MINVERHUMAN,
main_icon = self.j(self.src_root, 'icons', 'library.ico'), minver = '600' if is64bit else '501',
web_icon = self.j(self.src_root, 'icons', 'web.ico'), compression = self.opts.msi_compression,
) app_components = components,
exe_map = self.smap,
main_icon = self.j(self.src_root, 'icons', 'library.ico'),
web_icon = self.j(self.src_root, 'icons', 'web.ico'),
)
template = open(self.j(self.d(__file__), 'en-us.xml'), template = open(self.j(self.d(__file__), 'en-us.xml'),
'rb').read() 'rb').read()
enus = template.format(app=__appname__) enus = template.format(app=__appname__)
@ -48,14 +61,15 @@ class WixMixIn:
with open(enusf, 'wb') as f: with open(enusf, 'wb') as f:
f.write(enus) f.write(enus)
wixobj = self.j(self.installer_dir, __appname__+'.wixobj') wixobj = self.j(self.installer_dir, __appname__+'.wixobj')
cmd = [CANDLE, '-nologo', '-ext', 'WiXUtilExtension', '-o', wixobj, wxsf] arch = 'x64' if is64bit else 'x86'
cmd = [CANDLE, '-nologo', '-arch', arch, '-ext', 'WiXUtilExtension', '-o', wixobj, wxsf]
self.info(*cmd) self.info(*cmd)
subprocess.check_call(cmd) subprocess.check_call(cmd)
self.installer = self.j(self.src_root, 'dist') self.installer = self.j(self.src_root, 'dist')
if not os.path.exists(self.installer): if not os.path.exists(self.installer):
os.makedirs(self.installer) os.makedirs(self.installer)
self.installer = self.j(self.installer, '%s-%s.msi' % (__appname__, self.installer = self.j(self.installer, '%s%s-%s.msi' % (__appname__,
__version__)) ('-64bit' if is64bit else ''), __version__))
license = self.j(self.src_root, 'LICENSE.rtf') license = self.j(self.src_root, 'LICENSE.rtf')
banner = self.j(self.src_root, 'icons', 'wix-banner.bmp') banner = self.j(self.src_root, 'icons', 'wix-banner.bmp')
dialog = self.j(self.src_root, 'icons', 'wix-dialog.bmp') dialog = self.j(self.src_root, 'icons', 'wix-dialog.bmp')