mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
OS X builds, needs testing
This commit is contained in:
parent
e69fc6b8b3
commit
d7fec99345
@ -160,6 +160,7 @@ if iswindows:
|
|||||||
podofo_inc = os.path.join(sw_inc_dir, 'podofo')
|
podofo_inc = os.path.join(sw_inc_dir, 'podofo')
|
||||||
podofo_lib = sw_lib_dir
|
podofo_lib = sw_lib_dir
|
||||||
elif isosx:
|
elif isosx:
|
||||||
|
QT_FRAMEWORKS = [x.replace('5', '') for x in QT_DLLS]
|
||||||
sw = os.environ.get('SW', os.path.expanduser('~/sw'))
|
sw = os.environ.get('SW', os.path.expanduser('~/sw'))
|
||||||
podofo_inc = os.path.join(sw, 'include', 'podofo')
|
podofo_inc = os.path.join(sw, 'include', 'podofo')
|
||||||
podofo_lib = os.path.join(sw, 'lib')
|
podofo_lib = os.path.join(sw, 'lib')
|
||||||
|
@ -10,21 +10,23 @@ import sys, os, shutil, plistlib, subprocess, glob, zipfile, tempfile, \
|
|||||||
py_compile, stat, operator
|
py_compile, stat, operator
|
||||||
abspath, join, basename = os.path.abspath, os.path.join, os.path.basename
|
abspath, join, basename = os.path.abspath, os.path.join, os.path.basename
|
||||||
|
|
||||||
from setup import __version__ as VERSION, __appname__ as APPNAME, basenames, \
|
from setup import (
|
||||||
modules as main_modules, Command, SRC, functions as main_functions
|
__version__ as VERSION, __appname__ as APPNAME, basenames, modules as
|
||||||
|
main_modules, Command, SRC, functions as main_functions)
|
||||||
|
from setup.build_environment import sw as SW, QT_FRAMEWORKS, QT_PLUGINS, PYQT_MODULES
|
||||||
|
|
||||||
LICENSE = open('LICENSE', 'rb').read()
|
LICENSE = open('LICENSE', 'rb').read()
|
||||||
MAGICK_HOME='@executable_path/../Frameworks/ImageMagick'
|
MAGICK_HOME='@executable_path/../Frameworks/ImageMagick'
|
||||||
ENV = dict(
|
ENV = dict(
|
||||||
FONTCONFIG_PATH='@executable_path/../Resources/fonts',
|
FONTCONFIG_PATH='@executable_path/../Resources/fonts',
|
||||||
FONTCONFIG_FILE='@executable_path/../Resources/fonts/fonts.conf',
|
FONTCONFIG_FILE='@executable_path/../Resources/fonts/fonts.conf',
|
||||||
MAGICK_CONFIGURE_PATH=MAGICK_HOME+'/config',
|
MAGICK_CONFIGURE_PATH=MAGICK_HOME+'/config-Q16',
|
||||||
MAGICK_CODER_MODULE_PATH=MAGICK_HOME+'/modules-Q16/coders',
|
MAGICK_CODER_MODULE_PATH=MAGICK_HOME+'/modules-Q16/coders',
|
||||||
MAGICK_CODER_FILTER_PATH=MAGICK_HOME+'/modules-Q16/filter',
|
MAGICK_CODER_FILTER_PATH=MAGICK_HOME+'/modules-Q16/filters',
|
||||||
QT_PLUGIN_PATH='@executable_path/../MacOS',
|
QT_PLUGIN_PATH='@executable_path/../MacOS/qt-plugins',
|
||||||
PYTHONIOENCODING='UTF-8',
|
PYTHONIOENCODING='UTF-8',
|
||||||
)
|
)
|
||||||
|
|
||||||
SW = os.environ.get('SW', '/sw')
|
|
||||||
|
|
||||||
info = warn = None
|
info = warn = None
|
||||||
|
|
||||||
@ -47,15 +49,15 @@ def compile_launcher_lib(contents_dir, gcc, base):
|
|||||||
fd = join(contents_dir, 'Frameworks')
|
fd = join(contents_dir, 'Frameworks')
|
||||||
dest = join(fd, 'calibre-launcher.dylib')
|
dest = join(fd, 'calibre-launcher.dylib')
|
||||||
src = join(base, 'util.c')
|
src = join(base, 'util.c')
|
||||||
cmd = [gcc] + '-Wall -arch i386 -arch x86_64 -dynamiclib -std=gnu99'.split() + [src] + \
|
cmd = [gcc] + '-Wall -dynamiclib -std=gnu99'.split() + [src] + \
|
||||||
['-I'+base] + \
|
['-I'+base] + \
|
||||||
['-I/sw/python/Python.framework/Versions/Current/Headers'] + \
|
['-I%s/python/Python.framework/Versions/Current/Headers' % SW] + \
|
||||||
'-current_version 1.0 -compatibility_version 1.0'.split() + \
|
'-current_version 1.0 -compatibility_version 1.0'.split() + \
|
||||||
'-fvisibility=hidden -o'.split() + [dest] + \
|
'-fvisibility=hidden -o'.split() + [dest] + \
|
||||||
['-install_name',
|
['-install_name',
|
||||||
'@executable_path/../Frameworks/'+os.path.basename(dest)] + \
|
'@executable_path/../Frameworks/'+os.path.basename(dest)] + \
|
||||||
['-F/sw/python', '-framework', 'Python', '-framework', 'CoreFoundation', '-headerpad_max_install_names']
|
[('-F%s/python' % SW), '-framework', 'Python', '-framework', 'CoreFoundation', '-headerpad_max_install_names']
|
||||||
info('\t'+' '.join(cmd))
|
# info('\t'+' '.join(cmd))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
subprocess.check_call(cmd)
|
subprocess.check_call(cmd)
|
||||||
return dest
|
return dest
|
||||||
@ -87,10 +89,9 @@ def compile_launchers(contents_dir, xprograms, pyver):
|
|||||||
fsrc = '/tmp/%s.c'%program
|
fsrc = '/tmp/%s.c'%program
|
||||||
with open(fsrc, 'wb') as f:
|
with open(fsrc, 'wb') as f:
|
||||||
f.write(psrc)
|
f.write(psrc)
|
||||||
cmd = [gcc, '-Wall', '-arch', 'x86_64', '-arch', 'i386',
|
cmd = [gcc, '-Wall', '-I'+base, fsrc, lib, '-o', out,
|
||||||
'-I'+base, fsrc, lib, '-o', out,
|
|
||||||
'-headerpad_max_install_names']
|
'-headerpad_max_install_names']
|
||||||
info('\t'+' '.join(cmd))
|
# info('\t'+' '.join(cmd))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
subprocess.check_call(cmd)
|
subprocess.check_call(cmd)
|
||||||
return programs
|
return programs
|
||||||
@ -230,50 +231,49 @@ class Py2App(object):
|
|||||||
|
|
||||||
@flush
|
@flush
|
||||||
def get_dependencies(self, path_to_lib):
|
def get_dependencies(self, path_to_lib):
|
||||||
raw = subprocess.Popen(['otool', '-L', path_to_lib],
|
install_name = subprocess.check_output(['otool', '-D', path_to_lib]).splitlines()[-1].strip()
|
||||||
stdout=subprocess.PIPE).stdout.read()
|
raw = subprocess.check_output(['otool', '-L', path_to_lib])
|
||||||
for line in raw.splitlines():
|
for line in raw.splitlines():
|
||||||
if 'compatibility' not in line or line.strip().endswith(':'):
|
if 'compatibility' not in line or line.strip().endswith(':'):
|
||||||
continue
|
continue
|
||||||
idx = line.find('(')
|
idx = line.find('(')
|
||||||
path = line[:idx].strip()
|
path = line[:idx].strip()
|
||||||
yield path
|
yield path, path == install_name
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def get_local_dependencies(self, path_to_lib):
|
def get_local_dependencies(self, path_to_lib):
|
||||||
for x in self.get_dependencies(path_to_lib):
|
for x, is_id in self.get_dependencies(path_to_lib):
|
||||||
for y in (SW+'/lib/', '/usr/local/lib/', SW+'/qt/lib/',
|
for y in (SW+'/lib/', SW+'/qt/lib/', SW+'/python/Python.framework/',):
|
||||||
'/opt/local/lib/',
|
|
||||||
SW+'/python/Python.framework/', SW+'/freetype/lib/'):
|
|
||||||
if x.startswith(y):
|
if x.startswith(y):
|
||||||
if y == SW+'/python/Python.framework/':
|
if y == SW+'/python/Python.framework/':
|
||||||
y = SW+'/python/'
|
y = SW+'/python/'
|
||||||
yield x, x[len(y):]
|
yield x, x[len(y):], is_id
|
||||||
break
|
break
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def change_dep(self, old_dep, new_dep, path_to_lib):
|
def change_dep(self, old_dep, new_dep, is_id, path_to_lib):
|
||||||
info('\tResolving dependency %s to'%old_dep, new_dep)
|
cmd = ['-id', new_dep] if is_id else ['-change', old_dep, new_dep]
|
||||||
subprocess.check_call(['install_name_tool', '-change', old_dep, new_dep,
|
subprocess.check_call(['install_name_tool'] + cmd + [path_to_lib])
|
||||||
path_to_lib])
|
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def fix_dependencies_in_lib(self, path_to_lib):
|
def fix_dependencies_in_lib(self, path_to_lib):
|
||||||
info('\nFixing dependencies in', path_to_lib)
|
|
||||||
self.to_strip.append(path_to_lib)
|
self.to_strip.append(path_to_lib)
|
||||||
old_mode = flipwritable(path_to_lib)
|
old_mode = flipwritable(path_to_lib)
|
||||||
for dep, bname in self.get_local_dependencies(path_to_lib):
|
for dep, bname, is_id in self.get_local_dependencies(path_to_lib):
|
||||||
ndep = self.FID+'/'+bname
|
ndep = self.FID+'/'+bname
|
||||||
self.change_dep(dep, ndep, path_to_lib)
|
self.change_dep(dep, ndep, is_id, path_to_lib)
|
||||||
if list(self.get_local_dependencies(path_to_lib)):
|
ldeps = list(self.get_local_dependencies(path_to_lib))
|
||||||
raise Exception('Failed to resolve deps in: '+path_to_lib)
|
if ldeps:
|
||||||
|
info('\nFailed to fix dependencies in', path_to_lib)
|
||||||
|
info('Remaining local dependencies:', ldeps)
|
||||||
|
raise SystemExit(1)
|
||||||
if old_mode is not None:
|
if old_mode is not None:
|
||||||
flipwritable(path_to_lib, old_mode)
|
flipwritable(path_to_lib, old_mode)
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def add_python_framework(self):
|
def add_python_framework(self):
|
||||||
info('\nAdding Python framework')
|
info('\nAdding Python framework')
|
||||||
src = join('/sw/python', 'Python.framework')
|
src = join(SW + '/python', 'Python.framework')
|
||||||
x = join(self.frameworks_dir, 'Python.framework')
|
x = join(self.frameworks_dir, 'Python.framework')
|
||||||
curr = os.path.realpath(join(src, 'Versions', 'Current'))
|
curr = os.path.realpath(join(src, 'Versions', 'Current'))
|
||||||
currd = join(x, 'Versions', basename(curr))
|
currd = join(x, 'Versions', basename(curr))
|
||||||
@ -286,18 +286,19 @@ class Py2App(object):
|
|||||||
|
|
||||||
@flush
|
@flush
|
||||||
def add_qt_frameworks(self):
|
def add_qt_frameworks(self):
|
||||||
info('\nAdding Qt Framework')
|
info('\nAdding Qt Frameworks')
|
||||||
for f in ('QtCore', 'QtGui', 'QtXml', 'QtNetwork', 'QtSvg', 'QtWebKit',
|
for f in QT_FRAMEWORKS:
|
||||||
'QtXmlPatterns'):
|
|
||||||
self.add_qt_framework(f)
|
self.add_qt_framework(f)
|
||||||
for d in glob.glob(join(SW, 'qt', 'plugins', '*')):
|
pdir = join(SW, 'qt', 'plugins')
|
||||||
shutil.copytree(d, join(self.contents_dir, 'MacOS', basename(d)))
|
ddir = join(self.contents_dir, 'MacOS', 'qt-plugins')
|
||||||
for l in glob.glob(join(self.contents_dir, 'MacOS', '*/*.dylib')):
|
os.mkdir(ddir)
|
||||||
|
for x in QT_PLUGINS:
|
||||||
|
shutil.copytree(join(pdir, x), join(ddir, x))
|
||||||
|
for l in glob.glob(join(ddir, '*/*.dylib')):
|
||||||
self.fix_dependencies_in_lib(l)
|
self.fix_dependencies_in_lib(l)
|
||||||
x = os.path.relpath(l, join(self.contents_dir, 'MacOS'))
|
x = os.path.relpath(l, ddir)
|
||||||
self.set_id(l, '@executable_path/'+x)
|
self.set_id(l, '@executable_path/'+x)
|
||||||
|
|
||||||
@flush
|
|
||||||
def add_qt_framework(self, f):
|
def add_qt_framework(self, f):
|
||||||
libname = f
|
libname = f
|
||||||
f = f+'.framework'
|
f = f+'.framework'
|
||||||
@ -351,7 +352,7 @@ class Py2App(object):
|
|||||||
LSMinimumSystemVersion='10.7.2',
|
LSMinimumSystemVersion='10.7.2',
|
||||||
LSRequiresNativeExecution=True,
|
LSRequiresNativeExecution=True,
|
||||||
NSAppleScriptEnabled=False,
|
NSAppleScriptEnabled=False,
|
||||||
NSHumanReadableCopyright='Copyright 2010, Kovid Goyal',
|
NSHumanReadableCopyright='Copyright 2014, Kovid Goyal',
|
||||||
CFBundleGetInfoString=('calibre, an E-book management '
|
CFBundleGetInfoString=('calibre, an E-book management '
|
||||||
'application. Visit http://calibre-ebook.com for details.'),
|
'application. Visit http://calibre-ebook.com for details.'),
|
||||||
CFBundleIconFile='library.icns',
|
CFBundleIconFile='library.icns',
|
||||||
@ -378,7 +379,7 @@ class Py2App(object):
|
|||||||
@flush
|
@flush
|
||||||
def add_poppler(self):
|
def add_poppler(self):
|
||||||
info('\nAdding poppler')
|
info('\nAdding poppler')
|
||||||
for x in ('libpoppler.37.dylib',):
|
for x in ('libpoppler.46.dylib',):
|
||||||
self.install_dylib(os.path.join(SW, 'lib', x))
|
self.install_dylib(os.path.join(SW, 'lib', x))
|
||||||
for x in ('pdftohtml', 'pdftoppm', 'pdfinfo'):
|
for x in ('pdftohtml', 'pdftoppm', 'pdfinfo'):
|
||||||
self.install_dylib(os.path.join(SW, 'bin', x), False)
|
self.install_dylib(os.path.join(SW, 'bin', x), False)
|
||||||
@ -391,14 +392,13 @@ class Py2App(object):
|
|||||||
@flush
|
@flush
|
||||||
def add_libpng(self):
|
def add_libpng(self):
|
||||||
info('\nAdding libpng')
|
info('\nAdding libpng')
|
||||||
self.install_dylib(os.path.join(SW, 'lib', 'libpng12.0.dylib'))
|
self.install_dylib(os.path.join(SW, 'lib', 'libpng16.16.dylib'))
|
||||||
self.install_dylib(os.path.join(SW, 'lib', 'libpng.3.dylib'))
|
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def add_fontconfig(self):
|
def add_fontconfig(self):
|
||||||
info('\nAdding fontconfig')
|
info('\nAdding fontconfig')
|
||||||
for x in ('fontconfig.1', 'freetype.6', 'expat.1',
|
for x in ('fontconfig.1', 'freetype.6', 'expat.1',
|
||||||
'plist.1', 'usbmuxd.2', 'imobiledevice.4'):
|
'plist.2', 'usbmuxd.2', 'imobiledevice.4'):
|
||||||
src = os.path.join(SW, 'lib', 'lib'+x+'.dylib')
|
src = os.path.join(SW, 'lib', 'lib'+x+'.dylib')
|
||||||
self.install_dylib(src)
|
self.install_dylib(src)
|
||||||
dst = os.path.join(self.resources_dir, 'fonts')
|
dst = os.path.join(self.resources_dir, 'fonts')
|
||||||
@ -421,8 +421,8 @@ class Py2App(object):
|
|||||||
@flush
|
@flush
|
||||||
def add_imagemagick(self):
|
def add_imagemagick(self):
|
||||||
info('\nAdding ImageMagick')
|
info('\nAdding ImageMagick')
|
||||||
for x in ('Wand', 'Core'):
|
for x in ('Wand-6', 'Core-6'):
|
||||||
self.install_dylib(os.path.join(SW, 'lib', 'libMagick%s.5.dylib'%x))
|
self.install_dylib(os.path.join(SW, 'lib', 'libMagick%s.Q16.2.dylib'%x))
|
||||||
idir = glob.glob(os.path.join(SW, 'lib', 'ImageMagick-*'))[-1]
|
idir = glob.glob(os.path.join(SW, 'lib', 'ImageMagick-*'))[-1]
|
||||||
dest = os.path.join(self.frameworks_dir, 'ImageMagick')
|
dest = os.path.join(self.frameworks_dir, 'ImageMagick')
|
||||||
if os.path.exists(dest):
|
if os.path.exists(dest):
|
||||||
@ -433,6 +433,10 @@ class Py2App(object):
|
|||||||
if f.endswith('.so'):
|
if f.endswith('.so'):
|
||||||
f = join(x[0], f)
|
f = join(x[0], f)
|
||||||
self.fix_dependencies_in_lib(f)
|
self.fix_dependencies_in_lib(f)
|
||||||
|
for d in ('etc', 'share'):
|
||||||
|
base = os.path.join(SW, d, 'ImageMagick-6')
|
||||||
|
for x in os.listdir(base):
|
||||||
|
shutil.copy2(os.path.join(base, x), os.path.join(dest, 'config-Q16'))
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def add_misc_libraries(self):
|
def add_misc_libraries(self):
|
||||||
@ -476,7 +480,12 @@ class Py2App(object):
|
|||||||
if tdir is not None:
|
if tdir is not None:
|
||||||
shutil.rmtree(tdir)
|
shutil.rmtree(tdir)
|
||||||
shutil.rmtree(os.path.join(self.site_packages, 'calibre', 'plugins'))
|
shutil.rmtree(os.path.join(self.site_packages, 'calibre', 'plugins'))
|
||||||
self.remove_bytecode(join(self.resources_dir, 'Python', 'site-packages'))
|
sp = join(self.resources_dir, 'Python', 'site-packages')
|
||||||
|
for x in os.listdir(join(sp, 'PyQt5')):
|
||||||
|
if x.endswith('.so') and x.rpartition('.')[0] not in PYQT_MODULES:
|
||||||
|
os.remove(join(sp, 'PyQt5', x))
|
||||||
|
os.remove(join(sp, 'PyQt5', 'uic/port_v3/proxy_base.py'))
|
||||||
|
self.remove_bytecode(sp)
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def add_modules_from_dir(self, src):
|
def add_modules_from_dir(self, src):
|
||||||
@ -528,7 +537,7 @@ class Py2App(object):
|
|||||||
@flush
|
@flush
|
||||||
def add_stdlib(self):
|
def add_stdlib(self):
|
||||||
info('\nAdding python stdlib')
|
info('\nAdding python stdlib')
|
||||||
src = '/sw/python/Python.framework/Versions/Current/lib/python'
|
src = SW + '/python/Python.framework/Versions/Current/lib/python'
|
||||||
src += self.version_info
|
src += self.version_info
|
||||||
dest = join(self.resources_dir, 'Python', 'lib', 'python')
|
dest = join(self.resources_dir, 'Python', 'lib', 'python')
|
||||||
dest += self.version_info
|
dest += self.version_info
|
||||||
@ -596,6 +605,8 @@ class Py2App(object):
|
|||||||
else:
|
else:
|
||||||
os.symlink(join('../..', x),
|
os.symlink(join('../..', x),
|
||||||
join(cc_dir, x))
|
join(cc_dir, x))
|
||||||
|
# Comes from the terminal-notifier project:
|
||||||
|
# https://github.com/alloy/terminal-notifier
|
||||||
shutil.copytree(join(SW, 'build/notifier.app'), join(
|
shutil.copytree(join(SW, 'build/notifier.app'), join(
|
||||||
self.contents_dir, 'calibre-notifier.app'))
|
self.contents_dir, 'calibre-notifier.app'))
|
||||||
|
|
||||||
|
@ -11,8 +11,7 @@ static const char *ERR_OOM = "Out of memory";
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
report_error(const char *msg) {
|
report_error(const char *msg) {
|
||||||
fprintf(stderr, msg);
|
fprintf(stderr, "%s\n", msg);
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user