mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-11-04 03:27:00 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			195 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/env  python
 | 
						|
__license__   = 'GPL v3'
 | 
						|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
 | 
						|
__docformat__ = 'restructuredtext en'
 | 
						|
 | 
						|
'''
 | 
						|
Freeze app into executable using py2exe.
 | 
						|
'''
 | 
						|
QT_DIR           = 'C:\\Qt\\4.5.2'
 | 
						|
LIBUSB_DIR       = 'C:\\libusb'
 | 
						|
LIBUNRAR         = 'C:\\Program Files\\UnrarDLL\\unrar.dll'
 | 
						|
PDFTOHTML        = 'C:\\cygwin\\home\\kovid\\poppler-0.10.6\\rel\\pdftohtml.exe'
 | 
						|
POPPLER          = 'C:\\cygwin\\home\\kovid\\poppler'
 | 
						|
IMAGEMAGICK_DIR  = 'C:\\ImageMagick'
 | 
						|
PDFTK            = 'C:\\pdftk.exe'
 | 
						|
PODOFO           = 'C:\\podofo'
 | 
						|
FONTCONFIG_DIR   = 'C:\\fontconfig'
 | 
						|
VC90             = r'C:\VC90.CRT'
 | 
						|
 | 
						|
# ModuleFinder can't handle runtime changes to __path__, but win32com uses them
 | 
						|
import sys
 | 
						|
import py2exe.mf as modulefinder
 | 
						|
import win32com
 | 
						|
for p in win32com.__path__[1:]:
 | 
						|
    modulefinder.AddPackagePath("win32com", p)
 | 
						|
for extra in ["win32com.shell"]: #,"win32com.mapi"
 | 
						|
    __import__(extra)
 | 
						|
    m = sys.modules[extra]
 | 
						|
    for p in m.__path__[1:]:
 | 
						|
        modulefinder.AddPackagePath(extra, p)
 | 
						|
 | 
						|
 | 
						|
import os, py2exe, shutil, zipfile, glob, re
 | 
						|
from distutils.core import setup
 | 
						|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
 | 
						|
sys.path.insert(0, BASE_DIR)
 | 
						|
from setup import VERSION, APPNAME, scripts, basenames
 | 
						|
sys.path.remove(BASE_DIR)
 | 
						|
 | 
						|
ICONS = [os.path.abspath(os.path.join(BASE_DIR, 'icons', i)) for i in ('library.ico', 'viewer.ico')]
 | 
						|
for icon in ICONS:
 | 
						|
    if not os.access(icon, os.R_OK):
 | 
						|
        raise Exception('No icon at '+icon)
 | 
						|
 | 
						|
VERSION = re.sub('[a-z]\d+', '', VERSION)
 | 
						|
WINVER = VERSION+'.0'
 | 
						|
 | 
						|
PY2EXE_DIR = os.path.join(BASE_DIR, 'build','py2exe')
 | 
						|
 | 
						|
class BuildEXE(py2exe.build_exe.py2exe):
 | 
						|
 | 
						|
    def run(self):
 | 
						|
        py2exe.build_exe.py2exe.run(self)
 | 
						|
        print 'Adding plugins...'
 | 
						|
        tgt = os.path.join(self.dist_dir, 'plugins')
 | 
						|
        if not os.path.exists(tgt):
 | 
						|
            os.mkdir(tgt)
 | 
						|
        for f in glob.glob(os.path.join(BASE_DIR, 'src', 'calibre', 'plugins', '*.dll')):
 | 
						|
            shutil.copyfile(f, os.path.join(self.dist_dir, os.path.basename(f)))
 | 
						|
        for f in glob.glob(os.path.join(BASE_DIR, 'src', 'calibre', 'plugins', '*.pyd')):
 | 
						|
            shutil.copyfile(f, os.path.join(tgt, os.path.basename(f)))
 | 
						|
        for f in glob.glob(os.path.join(BASE_DIR, 'src', 'calibre', 'plugins', '*.manifest')):
 | 
						|
            shutil.copyfile(f, os.path.join(tgt, os.path.basename(f)))
 | 
						|
        shutil.copyfile('LICENSE', os.path.join(self.dist_dir, 'LICENSE'))
 | 
						|
        print
 | 
						|
        print 'Adding QtXml4.dll'
 | 
						|
        shutil.copyfile(os.path.join(QT_DIR, 'bin', 'QtXml4.dll'),
 | 
						|
                            os.path.join(self.dist_dir, 'QtXml4.dll'))
 | 
						|
        print 'Adding Qt plugins...',
 | 
						|
        qt_prefix = QT_DIR
 | 
						|
        plugdir = os.path.join(qt_prefix, 'plugins')
 | 
						|
        for d in ('imageformats', 'codecs', 'iconengines'):
 | 
						|
            print d,
 | 
						|
            imfd = os.path.join(plugdir, d)
 | 
						|
            tg = os.path.join(self.dist_dir, d)
 | 
						|
            if os.path.exists(tg):
 | 
						|
                shutil.rmtree(tg)
 | 
						|
            shutil.copytree(imfd, tg)
 | 
						|
 | 
						|
        print
 | 
						|
        print 'Adding main scripts'
 | 
						|
        f = zipfile.ZipFile(os.path.join(PY2EXE_DIR, 'library.zip'), 'a', zipfile.ZIP_DEFLATED)
 | 
						|
        for i in scripts['console'] + scripts['gui']:
 | 
						|
            f.write(i, i.partition('\\')[-1])
 | 
						|
        f.close()
 | 
						|
 | 
						|
        print
 | 
						|
        print 'Copying icons'
 | 
						|
        for icon in ICONS:
 | 
						|
            shutil.copyfile(icon, os.path.join(PY2EXE_DIR, os.path.basename(icon)))
 | 
						|
 | 
						|
        print
 | 
						|
        print 'Adding third party dependencies'
 | 
						|
        tdir = os.path.join(PY2EXE_DIR, 'driver')
 | 
						|
        os.makedirs(tdir)
 | 
						|
        for pat in ('*.dll', '*.sys', '*.cat', '*.inf'):
 | 
						|
            for f in glob.glob(os.path.join(LIBUSB_DIR, pat)):
 | 
						|
                shutil.copyfile(f, os.path.join(tdir, os.path.basename(f)))
 | 
						|
        print '\tAdding unrar'
 | 
						|
        shutil.copyfile(LIBUNRAR, os.path.join(PY2EXE_DIR, os.path.basename(LIBUNRAR)))
 | 
						|
        print '\tAdding poppler'
 | 
						|
        for x in ('bin\\pdftohtml.exe', 'bin\\poppler-qt4.dll',
 | 
						|
            'bin\\freetype.dll', 'bin\\jpeg62.dll'):
 | 
						|
            shutil.copyfile(os.path.join(POPPLER, x),
 | 
						|
                    os.path.join(PY2EXE_DIR, os.path.basename(x)))
 | 
						|
        print '\tAdding podofo'
 | 
						|
        for f in glob.glob(os.path.join(PODOFO, '*.dll')):
 | 
						|
            shutil.copyfile(f, os.path.join(PY2EXE_DIR, os.path.basename(f)))
 | 
						|
 | 
						|
        print '\tAdding ImageMagick'
 | 
						|
        for f in os.listdir(IMAGEMAGICK_DIR):
 | 
						|
            shutil.copyfile(os.path.join(IMAGEMAGICK_DIR, f), os.path.join(PY2EXE_DIR, f))
 | 
						|
        print '\tCopying fontconfig'
 | 
						|
        for f in glob.glob(os.path.join(FONTCONFIG_DIR, '*')):
 | 
						|
            tgt = os.path.join(PY2EXE_DIR, os.path.basename(f))
 | 
						|
            if os.path.isdir(f):
 | 
						|
                shutil.copytree(f, tgt)
 | 
						|
            else:
 | 
						|
                shutil.copyfile(f, tgt)
 | 
						|
 | 
						|
        print
 | 
						|
        print 'Doing DLL redirection' # See http://msdn.microsoft.com/en-us/library/ms682600(VS.85).aspx
 | 
						|
        for f in glob.glob(os.path.join(PY2EXE_DIR, '*.exe')):
 | 
						|
            open(f + '.local', 'w').write('\n')
 | 
						|
 | 
						|
        print
 | 
						|
        print 'Adding Windows runtime dependencies...'
 | 
						|
        for f in glob.glob(os.path.join(VC90, '*')):
 | 
						|
            shutil.copyfile(f, os.path.join(PY2EXE_DIR, os.path.basename(f)))
 | 
						|
 | 
						|
 | 
						|
def exe_factory(dest_base, script, icon_resources=None):
 | 
						|
    exe = {
 | 
						|
           'dest_base'       : dest_base,
 | 
						|
           'script'          : script,
 | 
						|
           'name'            : dest_base,
 | 
						|
           'version'         : WINVER,
 | 
						|
           'description'     : 'calibre - E-book library management',
 | 
						|
           'author'          : 'Kovid Goyal',
 | 
						|
           'copyright'       : '(c) Kovid Goyal, 2008',
 | 
						|
           'company'         : 'kovidgoyal.net',
 | 
						|
           }
 | 
						|
    if icon_resources is not None:
 | 
						|
        exe['icon_resources'] = icon_resources
 | 
						|
    return exe
 | 
						|
 | 
						|
def main(args=sys.argv):
 | 
						|
    sys.argv[1:2] = ['py2exe']
 | 
						|
    if os.path.exists(PY2EXE_DIR):
 | 
						|
        shutil.rmtree(PY2EXE_DIR)
 | 
						|
 | 
						|
    console = [exe_factory(basenames['console'][i], scripts['console'][i])
 | 
						|
               for i in range(len(scripts['console']))]
 | 
						|
    setup(
 | 
						|
          cmdclass = {'py2exe': BuildEXE},
 | 
						|
          windows = [
 | 
						|
                     exe_factory(APPNAME, scripts['gui'][0], [(1, ICONS[0])]),
 | 
						|
                     exe_factory('lrfviewer', scripts['gui'][1], [(1, ICONS[1])]),
 | 
						|
                     exe_factory('ebook-viewer', scripts['gui'][2], [(1, ICONS[1])]),
 | 
						|
                    ],
 | 
						|
          console = console,
 | 
						|
          options = { 'py2exe' : {'compressed': 1,
 | 
						|
                                  'optimize'  : 2,
 | 
						|
                                  'dist_dir'  : PY2EXE_DIR,
 | 
						|
                                  'includes'  : [
 | 
						|
                                             'sip', 'pkg_resources', 'PyQt4.QtSvg',
 | 
						|
                                             'mechanize', 'ClientForm', 'wmi',
 | 
						|
                                             'win32file', 'pythoncom',
 | 
						|
                                             'email.iterators',
 | 
						|
                                             'email.generator',
 | 
						|
                                             'win32process', 'win32api', 'msvcrt',
 | 
						|
                                             'win32event', 'calibre.ebooks.lrf.any.*',
 | 
						|
                                             'sqlite3.dump',
 | 
						|
                                             'BeautifulSoup', 'pyreadline',
 | 
						|
                                             'pydoc', 'IPython.Extensions.*',
 | 
						|
                                             'calibre.web.feeds.recipes.*',
 | 
						|
                                             'calibre.gui2.convert.*',
 | 
						|
                                             'calibre.ebooks.lrf.fonts.prs500.*',
 | 
						|
                                             'PyQt4.QtWebKit', 'PyQt4.QtNetwork',
 | 
						|
                                             ],
 | 
						|
                                  'packages'  : ['PIL', 'lxml', 'cherrypy',
 | 
						|
                                                 'dateutil', 'dns'],
 | 
						|
                                  'excludes'  : ["Tkconstants", "Tkinter", "tcl",
 | 
						|
                                                 "_imagingtk", "ImageTk", "FixTk"
 | 
						|
                                                ],
 | 
						|
                                  'dll_excludes' : ['mswsock.dll'],
 | 
						|
                                 },
 | 
						|
                    },
 | 
						|
 | 
						|
          )
 | 
						|
    return 0
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    sys.exit(main())
 |