mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-10-31 10:37:00 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			157 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/env python2
 | |
| # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
 | |
| from __future__ import with_statement
 | |
| 
 | |
| __license__   = 'GPL v3'
 | |
| __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
 | |
| __docformat__ = 'restructuredtext en'
 | |
| 
 | |
| import os, shutil, subprocess, sys
 | |
| 
 | |
| from setup import __appname__, __version__, basenames
 | |
| from setup.build_environment import is64bit
 | |
| 
 | |
| WIXP = r'C:\Program Files (x86)\WiX Toolset v3.8'
 | |
| if is64bit:
 | |
|     UPGRADE_CODE = '5DD881FF-756B-4097-9D82-8C0F11D521EA'
 | |
| else:
 | |
|     UPGRADE_CODE = 'BEB2A80D-E902-4DAD-ADF9-8BD2DA42CFE1'
 | |
| MINVERHUMAN = 'Windows Vista'
 | |
| 
 | |
| CANDLE = WIXP+r'\bin\candle.exe'
 | |
| LIGHT = WIXP+r'\bin\light.exe'
 | |
| 
 | |
| class WixMixIn:
 | |
| 
 | |
|     def create_installer(self):
 | |
|         self.installer_dir = self.j(self.src_root, 'build', 'wix')
 | |
|         if os.path.exists(self.installer_dir):
 | |
|             shutil.rmtree(self.installer_dir)
 | |
|         os.makedirs(self.installer_dir)
 | |
| 
 | |
|         template = open(self.j(self.d(__file__), 'wix-template.xml'),
 | |
|                 'rb').read()
 | |
| 
 | |
|         components = self.get_components_from_files()
 | |
|         wxs = template.format(
 | |
|             app=__appname__,
 | |
|             appfolder='Calibre2' if is64bit else __appname__,
 | |
|             version=__version__,
 | |
|             upgrade_code=UPGRADE_CODE,
 | |
|             ProgramFilesFolder='ProgramFiles64Folder' if is64bit else 'ProgramFilesFolder',
 | |
|             x64=' 64bit' if is64bit else '',
 | |
|             minverhuman=MINVERHUMAN,
 | |
|             minver='600',
 | |
|             fix_wix='<Custom Action="OverwriteWixSetDefaultPerMachineFolder" After="WixSetDefaultPerMachineFolder" />' if is64bit else '',
 | |
|             compression=self.opts.msi_compression,
 | |
|             app_components=components,
 | |
|             exe_map=self.smap,
 | |
|             main_icon=self.j(self.src_root, 'icons', 'library.ico'),
 | |
|             viewer_icon=self.j(self.src_root, 'icons', 'viewer.ico'),
 | |
|             editor_icon=self.j(self.src_root, 'icons', 'ebook-edit.ico'),
 | |
|             web_icon=self.j(self.src_root, 'icons', 'web.ico'),
 | |
|         )
 | |
|         template = open(self.j(self.d(__file__), 'en-us.xml'),
 | |
|                 'rb').read()
 | |
|         enus = template.format(app=__appname__)
 | |
| 
 | |
|         enusf = self.j(self.installer_dir, 'en-us.wxl')
 | |
|         wxsf = self.j(self.installer_dir, __appname__+'.wxs')
 | |
|         with open(wxsf, 'wb') as f:
 | |
|             f.write(wxs)
 | |
|         with open(enusf, 'wb') as f:
 | |
|             f.write(enus)
 | |
|         wixobj = self.j(self.installer_dir, __appname__+'.wixobj')
 | |
|         arch = 'x64' if is64bit else 'x86'
 | |
|         cmd = [CANDLE, '-nologo', '-arch', arch, '-ext', 'WiXUtilExtension', '-o', wixobj, wxsf]
 | |
|         self.info(*cmd)
 | |
|         self.run_wix(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-%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')
 | |
|         cmd = [LIGHT, '-nologo', '-ext', 'WixUIExtension',
 | |
|                 '-cultures:en-us', '-loc', enusf, wixobj,
 | |
|                 '-ext', 'WixUtilExtension',
 | |
|                 '-o', self.installer,
 | |
|                 '-dWixUILicenseRtf='+license,
 | |
|                 '-dWixUIBannerBmp='+banner,
 | |
|                 '-dWixUIDialogBmp='+dialog]
 | |
|         cmd.extend([
 | |
|             '-sice:ICE60',  # No language in dlls warning
 | |
|             '-sice:ICE61',  # Allow upgrading with same version number
 | |
|             '-sice:ICE40',  # Re-install mode overriden
 | |
|             '-sice:ICE69',  # Shortcut components are part of a different feature than the files they point to
 | |
|         ])
 | |
|         if self.opts.no_ice:
 | |
|             cmd.append('-sval')
 | |
|         if self.opts.verbose:
 | |
|             cmd.append('-v')
 | |
|         self.info(*cmd)
 | |
|         self.run_wix(cmd)
 | |
| 
 | |
|     def run_wix(self, cmd):
 | |
|         p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
 | |
|                               stderr=subprocess.PIPE)
 | |
|         ret = p.wait()
 | |
|         self.info(p.stdout.read())
 | |
|         self.info(p.stderr.read())
 | |
|         if ret != 0:
 | |
|             sys.exit(1)
 | |
| 
 | |
|     def get_components_from_files(self):
 | |
| 
 | |
|         self._file_idc = 0
 | |
|         self.file_id_map = {}
 | |
| 
 | |
|         def process_dir(path):
 | |
|             components = []
 | |
|             for x in os.listdir(path):
 | |
|                 self._file_idc += 1
 | |
|                 f = os.path.join(path, x)
 | |
|                 self.file_id_map[f] = fid = self._file_idc
 | |
| 
 | |
|                 if os.path.isdir(f):
 | |
|                     components.append(
 | |
|                         '<Directory Id="file_%s" FileSource="%s" Name="%s">' %
 | |
|                         (self.file_id_map[f], f, x))
 | |
|                     c = process_dir(f)
 | |
|                     components.extend(c)
 | |
|                     components.append('</Directory>')
 | |
|                 else:
 | |
|                     checksum = 'Checksum="yes"' if x.endswith('.exe') else ''
 | |
|                     c = [
 | |
|                     ('<Component Id="component_%s" Feature="MainApplication" '
 | |
|                      'Guid="*">') % (fid,),
 | |
|                     ('<File Id="file_%s" Source="%s" Name="%s" ReadOnly="yes" '
 | |
|                      'KeyPath="yes" %s/>') %
 | |
|                         (fid, f, x, checksum),
 | |
|                     '</Component>'
 | |
|                     ]
 | |
|                     if x.endswith('.exe') and not x.startswith('pdf'):
 | |
|                         # Add the executable to app paths so that users can
 | |
|                         # launch it from the run dialog even if it is not on
 | |
|                         # the path. See http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx
 | |
|                         c[-1:-1] = [
 | |
|                         ('<RegistryValue Root="HKLM" '
 | |
|                          r'Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App '
 | |
|                          r'Paths\%s" Value="[#file_%d]" Type="string" />'%(x, fid)),
 | |
|                         ('<RegistryValue Root="HKLM" '
 | |
|                          r'Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App '
 | |
|                          r'Paths\{0}" Name="Path" Value="[APPLICATIONFOLDER]" '
 | |
|                          'Type="string" />'.format(x)),
 | |
|                         ]
 | |
|                     components.append('\n'.join(c))
 | |
|             return components
 | |
| 
 | |
|         components = process_dir(os.path.abspath(self.base))
 | |
|         self.smap = {}
 | |
|         for x in basenames['gui']:
 | |
|             self.smap[x] = 'file_%d'%self.file_id_map[self.a(self.j(self.base, x+'.exe'))]
 | |
| 
 | |
|         return '\t\t\t\t'+'\n\t\t\t\t'.join(components)
 |