mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
64 bit windows msi builds, though it's still picking up the 32 bit paths for some reason. Sigh.
This commit is contained in:
parent
ba83fb26f3
commit
c1dd30004e
@ -215,6 +215,8 @@ class Command(object):
|
||||
sys.stdout.flush()
|
||||
|
||||
def installer_name(ext, is64bit=False):
|
||||
if is64bit and ext == 'msi':
|
||||
return 'dist/%s-64bit-%s.msi'%(__appname__, __version__)
|
||||
if ext in ('exe', 'msi'):
|
||||
return 'dist/%s-%s.%s'%(__appname__, __version__, ext)
|
||||
if ext == 'dmg':
|
||||
|
@ -20,7 +20,7 @@ __all__ = [
|
||||
'upload_user_manual', 'upload_demo', 'reupload',
|
||||
'linux32', 'linux64', 'linux', 'linux_freeze',
|
||||
'osx32_freeze', 'osx', 'rsync', 'push',
|
||||
'win32_freeze', 'win32', 'win',
|
||||
'win32_freeze', 'win32', 'win64', 'win',
|
||||
'stage1', 'stage2', 'stage3', 'stage4', 'stage5', 'publish'
|
||||
]
|
||||
|
||||
@ -91,9 +91,10 @@ osx = OSX()
|
||||
from setup.installer.osx.app.main import OSX32_Freeze
|
||||
osx32_freeze = OSX32_Freeze()
|
||||
|
||||
from setup.installer.windows import Win, Win32
|
||||
from setup.installer.windows import Win, Win32, Win64
|
||||
win = Win()
|
||||
win32 = Win32()
|
||||
win64 = Win64()
|
||||
from setup.installer.windows.freeze import Win32Freeze
|
||||
win32_freeze = Win32Freeze()
|
||||
|
||||
|
@ -20,20 +20,21 @@ class Win(Command):
|
||||
def run(self, opts):
|
||||
pass
|
||||
|
||||
|
||||
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'
|
||||
class WinBase(VMInstaller):
|
||||
FREEZE_COMMAND = 'win32_freeze'
|
||||
FREEZE_TEMPLATE = 'python -OO setup.py {freeze_command} --no-ice'
|
||||
INSTALLER_EXT = 'msi'
|
||||
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):
|
||||
print ('Signing installers ...')
|
||||
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')
|
||||
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',
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@ LZMA = r'Q:\easylzma\build\easylzma-0.0.8'
|
||||
|
||||
VERSION = re.sub('[a-z]\d+', '', __version__)
|
||||
WINVER = VERSION+'.0'
|
||||
machine = 'X64' if is64bit else 'X86'
|
||||
|
||||
DESCRIPTIONS = {
|
||||
'calibre' : 'The main calibre program',
|
||||
@ -132,6 +133,22 @@ class Win32Freeze(Command, WixMixIn):
|
||||
# used instead
|
||||
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):
|
||||
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.rmtree(comext)
|
||||
|
||||
# Fix PyCrypto, removing the bootstrap .py modules that load 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 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 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)
|
||||
# Fix PyCrypto and Pillow, removing the bootstrap .py modules that load
|
||||
# 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')
|
||||
) + glob.glob(self.j(sp_dir, 'Pillow-*')):
|
||||
self.fix_pyd_bootstraps_in(crypto_dir)
|
||||
|
||||
for pat in (r'PyQt4\uic\port_v3', ):
|
||||
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)
|
||||
if self.newer(exe, [obj, xobj]):
|
||||
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:'+(LZMA+r'\lib\Release'),
|
||||
'/RELEASE', '/MANIFEST', '/MANIFESTUAC:level="asInvoker" uiAccess="false"',
|
||||
@ -458,7 +463,7 @@ class Win32Freeze(Command, WixMixIn):
|
||||
exe = self.j(base, 'calibre-portable.exe')
|
||||
if self.newer(exe, [obj]):
|
||||
self.info('Linking', exe)
|
||||
cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:X86',
|
||||
cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:'+machine,
|
||||
'/LIBPATH:'+self.obj_dir, '/SUBSYSTEM:WINDOWS',
|
||||
'/RELEASE',
|
||||
'/ENTRY:wWinMainCRTStartup',
|
||||
@ -517,7 +522,7 @@ class Win32Freeze(Command, WixMixIn):
|
||||
ver = '.'.join(__version__.split('.')[:2])
|
||||
if self.newer(dll, objects):
|
||||
cmd = [msvc.linker, '/DLL', '/INCREMENTAL:NO', '/VERSION:'+ver,
|
||||
'/OUT:'+dll, '/nologo', '/MACHINE:X86'] + objects + \
|
||||
'/OUT:'+dll, '/nologo', '/MACHINE:'+machine] + objects + \
|
||||
[self.embed_resources(dll),
|
||||
'/LIBPATH:C:/Python%s/libs'%self.py_ver,
|
||||
'python%s.lib'%self.py_ver,
|
||||
@ -547,7 +552,7 @@ class Win32Freeze(Command, WixMixIn):
|
||||
lib = dll.replace('.dll', '.lib')
|
||||
if self.newer(exe, [dest, lib, self.rc_template, __file__]):
|
||||
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:C:/Python%s/libs'%self.py_ver, '/RELEASE',
|
||||
'/OUT:'+exe, self.embed_resources(exe),
|
||||
@ -581,6 +586,7 @@ class Win32Freeze(Command, WixMixIn):
|
||||
sp = self.j(self.lib_dir, 'site-packages')
|
||||
# Special handling for PIL and pywin32
|
||||
handled = set(['PIL.pth', 'pywin32.pth', 'PIL', 'win32'])
|
||||
if not is64bit:
|
||||
self.add_to_zipfile(zf, 'PIL', sp)
|
||||
base = self.j(sp, 'win32', 'lib')
|
||||
for x in os.listdir(base):
|
||||
@ -593,16 +599,17 @@ class Win32Freeze(Command, WixMixIn):
|
||||
self.add_to_zipfile(zf, x, base)
|
||||
|
||||
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')):
|
||||
handled.add(self.b(d))
|
||||
for x in os.listdir(d):
|
||||
if x == 'EGG-INFO':
|
||||
if x in {'EGG-INFO', 'site.py', 'site.pyc', 'site.pyo'}:
|
||||
continue
|
||||
self.add_to_zipfile(zf, x, d)
|
||||
|
||||
# The rest of site-packages
|
||||
# We dont want the site.py from site-packages
|
||||
handled.add('site.pyo')
|
||||
for x in os.listdir(sp):
|
||||
if x in handled or x.endswith('.egg-info'):
|
||||
continue
|
||||
@ -622,8 +629,10 @@ class Win32Freeze(Command, WixMixIn):
|
||||
line = line.strip()
|
||||
if not line or line.startswith('#') or line.startswith('import'):
|
||||
continue
|
||||
candidate = self.j(base, line)
|
||||
candidate = os.path.abspath(self.j(base, line))
|
||||
if os.path.exists(candidate):
|
||||
if not os.path.isdir(candidate):
|
||||
raise ValueError('%s is not a directory'%candidate)
|
||||
yield candidate
|
||||
|
||||
def add_to_zipfile(self, zf, name, base, exclude=frozenset()):
|
||||
|
@ -109,10 +109,8 @@ of mimetypes from the windows registry
|
||||
Python packages
|
||||
------------------
|
||||
|
||||
Install setuptools from http://pypi.python.org/pypi/setuptools If there are no
|
||||
windows binaries already compiled for the version of python you are using then
|
||||
download the source and run the following command in the folder where the
|
||||
source has been unpacked::
|
||||
Install setuptools from http://pypi.python.org/pypi/setuptools. Use the source
|
||||
tarball. Edit setup.py and set zip_safe=False. Then run::
|
||||
|
||||
python setup.py install
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<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'>
|
||||
|
||||
<Package Id='*' Keywords='Installer' Description="{app} Installer"
|
||||
@ -33,15 +33,15 @@
|
||||
|
||||
<Property Id="APPLICATIONFOLDER">
|
||||
<RegistrySearch Id='calibreInstDir' Type='raw'
|
||||
Root='HKLM' Key="Software\{app}\Installer" Name="InstallPath" />
|
||||
Root='HKLM' Key="Software\{app}{x64}\Installer" Name="InstallPath" />
|
||||
</Property>
|
||||
|
||||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||||
<Directory Id='ProgramFilesFolder' Name='PFiles'>
|
||||
<Directory Id='{ProgramFilesFolder}' Name='PFiles'>
|
||||
<Directory Id='APPLICATIONFOLDER' Name='{app}' />
|
||||
</Directory>
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="{app} - E-book Management"/>
|
||||
<Directory Id="ApplicationProgramsFolder" Name="{app}{x64} - E-book Management"/>
|
||||
</Directory>
|
||||
<Directory Id="DesktopFolder" Name="Desktop"/>
|
||||
</Directory>
|
||||
@ -50,24 +50,24 @@
|
||||
{app_components}
|
||||
<Component Id="AddToPath" Guid="*">
|
||||
<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 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>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||
<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"
|
||||
Target="[#{exe_map[calibre]}]"
|
||||
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"
|
||||
Target="[#{exe_map[ebook-viewer]}]"
|
||||
WorkingDirectory="APPLICATIONROOTDIRECTORY" />
|
||||
<Shortcut Id="s3" Name="LRF viewer"
|
||||
<Shortcut Id="s3" Name="LRF viewer{x64}"
|
||||
Description="Viewer for LRF format e-books"
|
||||
Target="[#{exe_map[lrfviewer]}]"
|
||||
WorkingDirectory="APPLICATIONROOTDIRECTORY" />
|
||||
@ -79,17 +79,17 @@
|
||||
Target="http://calibre-ebook.com/get-involved"/>
|
||||
|
||||
<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>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="DesktopFolder">
|
||||
<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"
|
||||
Target="[#{exe_map[calibre]}]"
|
||||
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>
|
||||
</DirectoryRef>
|
||||
|
||||
@ -124,8 +124,8 @@
|
||||
<Property Id="ARPPRODUCTICON" Value="main_icon" />
|
||||
|
||||
<Condition
|
||||
Message="This application is only supported on Windows XP SP3, or higher.">
|
||||
<![CDATA[Installed OR (VersionNT >= 501)]]>
|
||||
Message="This application is only supported on {minverhuman}, or higher.">
|
||||
<![CDATA[Installed OR (VersionNT >= {minver})]]>
|
||||
</Condition>
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
|
||||
|
@ -6,11 +6,20 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os, shutil, subprocess
|
||||
import os, shutil, subprocess, sys
|
||||
|
||||
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'
|
||||
LIGHT = WIXP+r'\bin\light.exe'
|
||||
|
||||
@ -29,7 +38,11 @@ class WixMixIn:
|
||||
wxs = template.format(
|
||||
app = __appname__,
|
||||
version = __version__,
|
||||
upgrade_code = 'BEB2A80D-E902-4DAD-ADF9-8BD2DA42CFE1',
|
||||
upgrade_code = UPGRADE_CODE,
|
||||
ProgramFilesFolder = 'ProgramFiles64Folder' if is64bit else 'ProgramFilesFolder',
|
||||
x64 = ' 64bit' if is64bit else '',
|
||||
minverhuman = MINVERHUMAN,
|
||||
minver = '600' if is64bit else '501',
|
||||
compression = self.opts.msi_compression,
|
||||
app_components = components,
|
||||
exe_map = self.smap,
|
||||
@ -48,14 +61,15 @@ class WixMixIn:
|
||||
with open(enusf, 'wb') as f:
|
||||
f.write(enus)
|
||||
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)
|
||||
subprocess.check_call(cmd)
|
||||
self.installer = self.j(self.src_root, 'dist')
|
||||
if not os.path.exists(self.installer):
|
||||
os.makedirs(self.installer)
|
||||
self.installer = self.j(self.installer, '%s-%s.msi' % (__appname__,
|
||||
__version__))
|
||||
self.installer = self.j(self.installer, '%s%s-%s.msi' % (__appname__,
|
||||
('-64bit' if is64bit else ''), __version__))
|
||||
license = self.j(self.src_root, 'LICENSE.rtf')
|
||||
banner = self.j(self.src_root, 'icons', 'wix-banner.bmp')
|
||||
dialog = self.j(self.src_root, 'icons', 'wix-dialog.bmp')
|
||||
|
Loading…
x
Reference in New Issue
Block a user