diff --git a/installer/windows/freeze.py b/installer/windows/freeze.py index 007217803e..73bb9cae56 100644 --- a/installer/windows/freeze.py +++ b/installer/windows/freeze.py @@ -6,13 +6,13 @@ __docformat__ = 'restructuredtext en' ''' Freeze app into executable using py2exe. ''' -QT_DIR = 'C:\\Qt\\4.4.1' +QT_DIR = 'C:\\Qt\\4.4.3' LIBUSB_DIR = 'C:\\libusb' LIBUNRAR = 'C:\\Program Files\\UnrarDLL\\unrar.dll' PDFTOHTML = 'C:\\pdftohtml\\pdftohtml.exe' IMAGEMAGICK_DIR = 'C:\\ImageMagick' FONTCONFIG_DIR = 'C:\\fontconfig' - +VC90 = r'C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT' import sys, os, py2exe, shutil, zipfile, glob, subprocess, re from distutils.core import setup @@ -65,6 +65,8 @@ class BuildEXE(py2exe.build_exe.py2exe): 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' @@ -115,12 +117,17 @@ class BuildEXE(py2exe.build_exe.py2exe): 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))) + @classmethod def manifest(cls, prog): @@ -142,17 +149,17 @@ def main(args=sys.argv): {'script' : scripts['gui'][0], 'dest_base' : APPNAME, 'icon_resources' : [(1, ICONS[0])], - 'other_resources' : [BuildEXE.manifest(APPNAME)], + #'other_resources' : [BuildEXE.manifest(APPNAME)], }, {'script' : scripts['gui'][1], 'dest_base' : 'lrfviewer', 'icon_resources' : [(1, ICONS[1])], - 'other_resources' : [BuildEXE.manifest('lrfviewer')], + #'other_resources' : [BuildEXE.manifest('lrfviewer')], }, {'script' : scripts['gui'][2], 'dest_base' : 'ebook-viewer', 'icon_resources' : [(1, ICONS[1])], - 'other_resources' : [BuildEXE.manifest('ebook-viewer')], + #'other_resources' : [BuildEXE.manifest('ebook-viewer')], }, ], console = console, @@ -162,12 +169,12 @@ def main(args=sys.argv): 'includes' : [ 'sip', 'pkg_resources', 'PyQt4.QtSvg', 'mechanize', 'ClientForm', 'wmi', - 'win32file', 'pythoncom', 'rtf2xml', + 'win32file', 'pythoncom', 'win32process', 'win32api', 'msvcrt', 'win32event', 'calibre.ebooks.lrf.any.*', 'calibre.ebooks.lrf.feeds.*', - 'genshi', 'BeautifulSoup', - 'path', 'pydoc', 'IPython.Extensions.*', + 'BeautifulSoup', 'pyreadline', + 'pydoc', 'IPython.Extensions.*', 'calibre.web.feeds.recipes.*', 'PyQt4.QtWebKit', 'PyQt4.QtNetwork', ], diff --git a/pyqtdistutils.py b/pyqtdistutils.py index 252968fb60..0e53aaabfe 100644 --- a/pyqtdistutils.py +++ b/pyqtdistutils.py @@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en' ''' Build PyQt extensions. Integrates with distutils (but uses the PyQt build system). ''' -from distutils.core import Extension +from distutils.core import Extension as _Extension from distutils.command.build_ext import build_ext as _build_ext from distutils.dep_util import newer_group from distutils import log @@ -15,12 +15,23 @@ import sipconfig, os, sys, string, glob, shutil from PyQt4 import pyqtconfig iswindows = 'win32' in sys.platform QMAKE = os.path.expanduser('~/qt/bin/qmake') if 'darwin' in sys.platform else'qmake' -WINDOWS_PYTHON = ['C:/Python25/libs'] +WINDOWS_PYTHON = ['C:/Python26/libs'] OSX_SDK = '/Developer/SDKs/MacOSX10.4u.sdk' def replace_suffix(path, new_suffix): return os.path.splitext(path)[0] + new_suffix +class Extension(_Extension): + pass + +if iswindows: + from distutils import msvc9compiler + msvc = msvc9compiler.MSVCCompiler() + msvc.initialize() + nmake = msvc.find_exe('nmake.exe') + rc = msvc.find_exe('rc.exe') + + class PyQtExtension(Extension): def __init__(self, name, sources, sip_sources, **kw): @@ -37,9 +48,7 @@ class PyQtExtension(Extension): class build_ext(_build_ext): def make(self, makefile): - make = 'make' - if iswindows: - make = 'mingw32-make' + make = nmake if iswindows else 'make' self.spawn([make, '-f', makefile]) def build_qt_objects(self, ext, bdir): @@ -65,12 +74,13 @@ CONFIG += x86 ppc open(name+'.pro', 'wb').write(pro) self.spawn([QMAKE, '-o', 'Makefile.qt', name+'.pro']) self.make('Makefile.qt') - pat = 'release\\*.o' if iswindows else '*.o' + pat = 'release\\*.obj' if iswindows else '*.o' return map(os.path.abspath, glob.glob(pat)) finally: os.chdir(cwd) def build_sbf(self, sip, sbf, bdir): + print '\tBuilding spf...' sip_bin = self.sipcfg.sip_bin self.spawn([sip_bin, "-c", bdir, @@ -100,9 +110,7 @@ CONFIG += x86 ppc def build_extension(self, ext): self.inplace = True # Causes extensions to be built in the source tree - if not isinstance(ext, PyQtExtension): - return _build_ext.build_extension(self, ext) - + fullname = self.get_ext_fullname(ext.name) if self.inplace: # ignore build-lib -- put the compiled extension into @@ -119,7 +127,38 @@ CONFIG += x86 ppc else: ext_filename = os.path.join(self.build_lib, self.get_ext_filename(fullname)) - bdir = os.path.abspath(os.path.join(self.build_temp, fullname)) + bdir = os.path.abspath(os.path.join(self.build_temp, fullname)) + if not os.path.exists(bdir): + os.makedirs(bdir) + + if not isinstance(ext, PyQtExtension): + if not iswindows: + return _build_ext.build_extension(self, ext) + + c_sources = [f for f in ext.sources if os.path.splitext(f)[1].lower() in ('.c', '.cpp', '.cxx')] + compile_args = '/c /nologo /Ox /MD /W3 /GX /DNDEBUG'.split() + compile_args += ext.extra_compile_args + self.swig_opts = '' + inc_dirs = self.include_dirs + [x.replace('/', '\\') for x in ext.include_dirs] + cc = [msvc.cc] + compile_args + ['-I%s'%x for x in list(set(inc_dirs))] + objects = [] + for f in c_sources: + o = os.path.join(bdir, os.path.basename(f)+'.obj') + objects.append(o) + compiler = cc + ['/Tc'+f, '/Fo'+o] + self.spawn(compiler) + out = os.path.join(bdir, base+'.pyd') + linker = [msvc.linker] + '/DLL /nologo /INCREMENTAL:NO'.split() + linker += ['/LIBPATH:'+x for x in self.library_dirs] + linker += [x+'.lib' for x in ext.libraries] + linker += ['/EXPORT:init'+base] + objects + ['/OUT:'+out] + self.spawn(linker) + for src in (out, out+'.manifest'): + shutil.copyfile(src, os.path.join('src', 'calibre', 'plugins', os.path.basename(src))) + return + + + if not os.path.exists(bdir): os.makedirs(bdir) ext.sources2 = map(os.path.abspath, ext.sources) diff --git a/setup.py b/setup.py index 37d54c4317..ca704d0916 100644 --- a/setup.py +++ b/setup.py @@ -46,10 +46,10 @@ main_functions = { } if __name__ == '__main__': - from setuptools import setup, find_packages, Extension + from setuptools import setup, find_packages from distutils.command.build import build as _build from distutils.core import Command as _Command - from pyqtdistutils import PyQtExtension, build_ext + from pyqtdistutils import PyQtExtension, build_ext, Extension import subprocess, glob def newer(targets, sources): @@ -391,8 +391,10 @@ if __name__ == '__main__': ext_modules.append(Extension('calibre.plugins.winutil', sources=['src/calibre/utils/windows/winutil.c'], libraries=['shell32', 'setupapi'], - include_dirs=['C:/WinDDK/6001.18001/inc/api/']) - ) + include_dirs=['C:/WinDDK/6001.18001/inc/api/', + 'C:/WinDDK/6001.18001/inc/crt/'], + extra_compile_args=['/X'] + )) if isosx: ext_modules.append(Extension('calibre.plugins.usbobserver', sources=['src/calibre/devices/usbobserver/usbobserver.c']) diff --git a/src/calibre/devices/libusb.py b/src/calibre/devices/libusb.py index 0bedce32bb..226a99f239 100644 --- a/src/calibre/devices/libusb.py +++ b/src/calibre/devices/libusb.py @@ -4,17 +4,20 @@ __copyright__ = '2008, Kovid Goyal ' This module provides a thin ctypes based wrapper around libusb. """ -from ctypes import cdll, POINTER, byref, pointer, Structure, \ +from ctypes import cdll, POINTER, byref, pointer, Structure as _Structure, \ c_ubyte, c_ushort, c_int, c_char, c_void_p, c_byte, c_uint from errno import EBUSY, ENOMEM -from calibre import iswindows, isosx, load_library, isfrozen +from calibre import iswindows, isosx, load_library _libusb_name = 'libusb' PATH_MAX = 511 if iswindows else 1024 if isosx else 4096 if iswindows: - Structure._pack_ = 1 + class Structure(_Structure): + _pack_ = 1 _libusb_name = 'libusb0' +else: + Structure = _Structure try: try: diff --git a/src/calibre/gui2/pictureflow/pictureflow.cpp b/src/calibre/gui2/pictureflow/pictureflow.cpp index a6b28146e9..3d2b0286c0 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.cpp +++ b/src/calibre/gui2/pictureflow/pictureflow.cpp @@ -715,7 +715,7 @@ void PictureFlowPrivate::render() painter.setPen(Qt::white); //painter.setPen(QColor(255,255,255,127)); - if (centerIndex < slideCount() and centerIndex > -1) + if (centerIndex < slideCount() && centerIndex > -1) painter.drawText( QRect(0,0, buffer.width(), (buffer.height() - slideSize().height())/2), Qt::AlignCenter, slideImages->caption(centerIndex)); @@ -767,12 +767,12 @@ void PictureFlowPrivate::render() int sc = slideCount(); painter.setPen(QColor(255,255,255, (255-fade) )); - if (leftTextIndex < sc and leftTextIndex > -1) + if (leftTextIndex < sc && leftTextIndex > -1) painter.drawText( QRect(0,0, buffer.width(), (buffer.height() - slideSize().height())/2), Qt::AlignCenter, slideImages->caption(leftTextIndex)); painter.setPen(QColor(255,255,255, fade)); - if (leftTextIndex+1 < sc and leftTextIndex > -2) + if (leftTextIndex+1 < sc && leftTextIndex > -2) painter.drawText( QRect(0,0, buffer.width(), (buffer.height() - slideSize().height())/2), Qt::AlignCenter, slideImages->caption(leftTextIndex+1)); diff --git a/src/calibre/libunrar.py b/src/calibre/libunrar.py index bb324282c3..7c608b72f1 100644 --- a/src/calibre/libunrar.py +++ b/src/calibre/libunrar.py @@ -7,7 +7,7 @@ This module provides a thin ctypes based wrapper around libunrar. See ftp://ftp.rarlabs.com/rar/unrarsrc-3.7.5.tar.gz """ import os, ctypes, sys, re -from ctypes import Structure, c_char_p, c_uint, c_void_p, POINTER, \ +from ctypes import Structure as _Structure, c_char_p, c_uint, c_void_p, POINTER, \ byref, c_wchar_p, c_int, c_char, c_wchar from tempfile import NamedTemporaryFile from StringIO import StringIO @@ -18,9 +18,12 @@ from calibre.ptempfile import TemporaryDirectory _librar_name = 'libunrar' cdll = ctypes.cdll if iswindows: - Structure._pack_ = 1 + class Structure(_Structure): + _pack_ = 1 _librar_name = 'unrar' cdll = ctypes.windll +else: + Structure = _Structure if hasattr(sys, 'frozen') and iswindows: _libunrar = cdll.LoadLibrary(os.path.join(os.path.dirname(sys.executable), 'unrar.dll')) _libunrar = load_library(_librar_name, cdll) diff --git a/todo-2.6 b/todo-2.6 index 00ed1d0e26..33b5a5e428 100644 --- a/todo-2.6 +++ b/todo-2.6 @@ -5,5 +5,3 @@ * Use multiprocessing for cpu_count instead of QThread -* Windows build: - * Compile all dependencies with MSVC 2008 since this is what python now uses