Move the utilities into their own bundle

This commit is contained in:
Kovid Goyal 2019-08-30 12:19:16 +05:30
parent 16ea6403a0
commit 22e3558a05
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 41 additions and 25 deletions

View File

@ -33,7 +33,7 @@ QT_DLLS, QT_PLUGINS, PYQT_MODULES = iv['QT_DLLS'], iv['QT_PLUGINS'], iv['PYQT_MO
py_ver = '.'.join(map(str, python_major_minor_version())) py_ver = '.'.join(map(str, python_major_minor_version()))
sign_app = runpy.run_path(join(dirname(abspath(__file__)), 'sign.py'))['sign_app'] sign_app = runpy.run_path(join(dirname(abspath(__file__)), 'sign.py'))['sign_app']
QT_PREFIX = os.path.join(PREFIX, 'qt') QT_PREFIX = join(PREFIX, 'qt')
QT_FRAMEWORKS = [x.replace('5', '') for x in QT_DLLS] QT_FRAMEWORKS = [x.replace('5', '') for x in QT_DLLS]
ENV = dict( ENV = dict(
@ -159,14 +159,17 @@ class Freeze(object):
FID = '@executable_path/../Frameworks' FID = '@executable_path/../Frameworks'
def __init__(self, build_dir, ext_dir, test_runner, test_launchers=False, dont_strip=False, sign_installers=False): def __init__(self, build_dir, ext_dir, test_runner, test_launchers=False, dont_strip=False, sign_installers=False):
self.build_dir = build_dir self.build_dir = os.path.realpath(build_dir)
self.sign_installers = sign_installers self.sign_installers = sign_installers
self.ext_dir = ext_dir self.ext_dir = os.path.realpath(ext_dir)
self.test_runner = test_runner self.test_runner = test_runner
self.dont_strip = dont_strip self.dont_strip = dont_strip
self.contents_dir = join(self.build_dir, 'Contents') self.contents_dir = join(self.build_dir, 'Contents')
self.resources_dir = join(self.contents_dir, 'Resources') self.resources_dir = join(self.contents_dir, 'Resources')
self.frameworks_dir = join(self.contents_dir, 'Frameworks') self.frameworks_dir = join(self.contents_dir, 'Frameworks')
self.exe_dir = join(self.contents_dir, 'MacOS')
self.helpers_dir = join(self.build_dir, 'Helpers', 'utils.app', 'Contents', 'MacOS')
self.webengine_dir = join(self.build_dir, 'Helpers', 'QtWebEngineProcess.app', 'Contents', 'MacOS')
self.site_packages = join(self.resources_dir, 'Python', 'site-packages') self.site_packages = join(self.resources_dir, 'Python', 'site-packages')
self.to_strip = [] self.to_strip = []
self.warnings = [] self.warnings = []
@ -211,12 +214,12 @@ class Freeze(object):
@flush @flush
def run_tests(self): def run_tests(self):
cc_dir = os.path.join(self.contents_dir, 'calibre-debug.app', 'Contents') cc_dir = join(self.contents_dir, 'calibre-debug.app', 'Contents')
self.test_runner(join(cc_dir, 'MacOS', 'calibre-debug'), self.contents_dir) self.test_runner(join(cc_dir, 'MacOS', 'calibre-debug'), self.contents_dir)
@flush @flush
def add_resources(self): def add_resources(self):
shutil.copytree('resources', os.path.join(self.resources_dir, shutil.copytree('resources', join(self.resources_dir,
'resources')) 'resources'))
@flush @flush
@ -262,6 +265,8 @@ class Freeze(object):
yield x, x[len('@rpath/'):], is_id yield x, x[len('@rpath/'):], is_id
elif x.startswith('@rpath/libjpeg'): elif x.startswith('@rpath/libjpeg'):
yield x, x[len('@rpath/'):], is_id yield x, x[len('@rpath/'):], is_id
elif x.startswith('@rpath/libpoppler'):
yield x, x[len('@rpath/'):], is_id
else: else:
for y in (PREFIX + '/lib/', PREFIX + '/python/Python.framework/'): for y in (PREFIX + '/lib/', PREFIX + '/python/Python.framework/'):
if x.startswith(y): if x.startswith(y):
@ -356,6 +361,12 @@ class Freeze(object):
subprocess.check_call([ subprocess.check_call([
'iconutil', '-c', 'icns', x, '-o', join( 'iconutil', '-c', 'icns', x, '-o', join(
self.resources_dir, basename(x).partition('.')[0] + '.icns')]) self.resources_dir, basename(x).partition('.')[0] + '.icns')])
for helpers in (self.helpers_dir, self.webengine_dir):
os.makedirs(helpers)
cdir = dirname(helpers)
dest = join(cdir, 'Frameworks')
src = self.frameworks_dir
os.symlink(os.path.relpath(src, cdir), dest)
@flush @flush
def add_calibre_plugins(self): def add_calibre_plugins(self):
@ -408,12 +419,14 @@ class Freeze(object):
plistlib.dump(pl, p) plistlib.dump(pl, p)
@flush @flush
def install_dylib(self, path, set_id=True): def install_dylib(self, path, set_id=True, dest=None):
shutil.copy2(path, self.frameworks_dir) dest = dest or self.frameworks_dir
os.makedirs(dest, exist_ok=True)
shutil.copy2(path, dest)
if set_id: if set_id:
self.set_id(join(self.frameworks_dir, basename(path)), self.set_id(join(dest, basename(path)),
self.FID + '/' + basename(path)) self.FID + '/' + basename(path))
self.fix_dependencies_in_lib(join(self.frameworks_dir, basename(path))) self.fix_dependencies_in_lib(join(dest, basename(path)))
@flush @flush
def add_podofo(self): def add_podofo(self):
@ -425,32 +438,34 @@ class Freeze(object):
def add_poppler(self): def add_poppler(self):
print('\nAdding poppler') print('\nAdding poppler')
for x in ('libpoppler.87.dylib',): for x in ('libpoppler.87.dylib',):
self.install_dylib(os.path.join(PREFIX, 'lib', x)) self.install_dylib(join(PREFIX, 'lib', x))
for x in ('pdftohtml', 'pdftoppm', 'pdfinfo'): for x in ('pdftohtml', 'pdftoppm', 'pdfinfo'):
self.install_dylib(os.path.join(PREFIX, 'bin', x), False) self.install_dylib(
join(PREFIX, 'bin', x), set_id=False, dest=self.helpers_dir)
@flush @flush
def add_imaging_libs(self): def add_imaging_libs(self):
print('\nAdding libjpeg, libpng, libwebp, optipng and mozjpeg') print('\nAdding libjpeg, libpng, libwebp, optipng and mozjpeg')
for x in ('jpeg.8', 'png16.16', 'webp.7', 'webpmux.3', 'webpdemux.2'): for x in ('jpeg.8', 'png16.16', 'webp.7', 'webpmux.3', 'webpdemux.2'):
self.install_dylib(os.path.join(PREFIX, 'lib', 'lib%s.dylib' % x)) self.install_dylib(join(PREFIX, 'lib', 'lib%s.dylib' % x))
for x in 'optipng', 'JxrDecApp': for x in 'optipng', 'JxrDecApp':
self.install_dylib(os.path.join(PREFIX, 'bin', x), False) self.install_dylib(join(PREFIX, 'bin', x), set_id=False, dest=self.helpers_dir)
for x in ('jpegtran', 'cjpeg'): for x in ('jpegtran', 'cjpeg'):
self.install_dylib(os.path.join(PREFIX, 'private', 'mozjpeg', 'bin', x), False) self.install_dylib(
join(PREFIX, 'private', 'mozjpeg', 'bin', x), set_id=False, dest=self.helpers_dir)
@flush @flush
def add_fontconfig(self): def add_fontconfig(self):
print('\nAdding fontconfig') print('\nAdding fontconfig')
for x in ('fontconfig.1', 'freetype.6', 'expat.1'): for x in ('fontconfig.1', 'freetype.6', 'expat.1'):
src = os.path.join(PREFIX, 'lib', 'lib' + x + '.dylib') src = join(PREFIX, 'lib', 'lib' + x + '.dylib')
self.install_dylib(src) self.install_dylib(src)
dst = os.path.join(self.resources_dir, 'fonts') dst = join(self.resources_dir, 'fonts')
if os.path.exists(dst): if os.path.exists(dst):
shutil.rmtree(dst) shutil.rmtree(dst)
src = os.path.join(PREFIX, 'etc', 'fonts') src = join(PREFIX, 'etc', 'fonts')
shutil.copytree(src, dst, symlinks=False) shutil.copytree(src, dst, symlinks=False)
fc = os.path.join(dst, 'fonts.conf') fc = join(dst, 'fonts.conf')
with open(fc, 'rb') as f: with open(fc, 'rb') as f:
raw = f.read().decode('utf-8') raw = f.read().decode('utf-8')
raw = raw.replace('<dir>/usr/share/fonts</dir>', '''\ raw = raw.replace('<dir>/usr/share/fonts</dir>', '''\
@ -506,7 +521,7 @@ class Freeze(object):
if tdir is not None: if tdir is not None:
shutil.rmtree(tdir) shutil.rmtree(tdir)
try: try:
shutil.rmtree(os.path.join(self.site_packages, 'calibre', 'plugins')) shutil.rmtree(join(self.site_packages, 'calibre', 'plugins'))
except OSError as err: except OSError as err:
if err.errno != errno.ENOENT: if err.errno != errno.ENOENT:
raise raise
@ -520,7 +535,7 @@ class Freeze(object):
@flush @flush
def add_modules_from_dir(self, src): def add_modules_from_dir(self, src):
for x in glob.glob(join(src, '*.py')) + glob.glob(join(src, '*.so')): for x in glob.glob(join(src, '*.py')) + glob.glob(join(src, '*.so')):
dest = os.path.join(self.site_packages, os.path.basename(x)) dest = join(self.site_packages, os.path.basename(x))
shutil.copy2(x, dest) shutil.copy2(x, dest)
if x.endswith('.so'): if x.endswith('.so'):
self.fix_dependencies_in_lib(dest) self.fix_dependencies_in_lib(dest)
@ -608,7 +623,7 @@ class Freeze(object):
def create_app_clone(self, name, specialise_plist, remove_doc_types=True): def create_app_clone(self, name, specialise_plist, remove_doc_types=True):
print('\nCreating ' + name) print('\nCreating ' + name)
cc_dir = os.path.join(self.contents_dir, name, 'Contents') cc_dir = join(self.contents_dir, name, 'Contents')
exe_dir = join(cc_dir, 'MacOS') exe_dir = join(cc_dir, 'MacOS')
os.makedirs(exe_dir) os.makedirs(exe_dir)
for x in os.listdir(self.contents_dir): for x in os.listdir(self.contents_dir):
@ -687,17 +702,17 @@ class Freeze(object):
if err.errno != errno.ENOENT: if err.errno != errno.ENOENT:
raise raise
os.mkdir(destdir) os.mkdir(destdir)
dmg = os.path.join(destdir, volname + '.dmg') dmg = join(destdir, volname + '.dmg')
if os.path.exists(dmg): if os.path.exists(dmg):
os.unlink(dmg) os.unlink(dmg)
tdir = tempfile.mkdtemp() tdir = tempfile.mkdtemp()
appdir = os.path.join(tdir, os.path.basename(d)) appdir = join(tdir, os.path.basename(d))
shutil.copytree(d, appdir, symlinks=True) shutil.copytree(d, appdir, symlinks=True)
if self.sign_installers: if self.sign_installers:
with timeit() as times: with timeit() as times:
sign_app(appdir) sign_app(appdir)
print('Signing completed in %d minutes %d seconds' % tuple(times)) print('Signing completed in %d minutes %d seconds' % tuple(times))
os.symlink('/Applications', os.path.join(tdir, 'Applications')) os.symlink('/Applications', join(tdir, 'Applications'))
size_in_mb = int(subprocess.check_output(['du', '-s', '-k', tdir]).decode('utf-8').split()[0]) / 1024. size_in_mb = int(subprocess.check_output(['du', '-s', '-k', tdir]).decode('utf-8').split()[0]) / 1024.
cmd = ['/usr/bin/hdiutil', 'create', '-srcfolder', tdir, '-volname', volname, '-format', format] cmd = ['/usr/bin/hdiutil', 'create', '-srcfolder', tdir, '-volname', volname, '-format', format]
if 190 < size_in_mb < 250: if 190 < size_in_mb < 250:

View File

@ -34,7 +34,8 @@ def popen(cmd, **kw):
if isosx and hasattr(sys, 'frameworks_dir'): if isosx and hasattr(sys, 'frameworks_dir'):
PDFTOHTML = os.path.join(getattr(sys, 'frameworks_dir'), PDFTOHTML) base = os.path.join(os.path.dirname(os.path.dirname(sys.frameworks_dir)), 'Helpers', 'utils.app', 'Contents', 'MacOS')
PDFTOHTML = os.path.join(base, PDFTOHTML)
if iswindows and hasattr(sys, 'frozen'): if iswindows and hasattr(sys, 'frozen'):
base = sys.extensions_location if hasattr(sys, 'new_app_layout') else os.path.dirname(sys.executable) base = sys.extensions_location if hasattr(sys, 'new_app_layout') else os.path.dirname(sys.executable)
PDFTOHTML = os.path.join(base, 'pdftohtml.exe') PDFTOHTML = os.path.join(base, 'pdftohtml.exe')