Use the new auto-build infrastructure for creating calibre installers

This commit is contained in:
Kovid Goyal 2016-07-17 20:06:22 +05:30
parent 7bce30a9db
commit 37cd0c56e5
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
117 changed files with 94 additions and 11871 deletions

View File

@ -18,12 +18,14 @@ __all__ = [
'pypi_register', 'pypi_upload', 'upload_to_server', 'pypi_register', 'pypi_upload', 'upload_to_server',
'upload_installers', 'upload_installers',
'upload_user_manual', 'upload_demo', 'reupload', 'upload_user_manual', 'upload_demo', 'reupload',
'linux32', 'linux64', 'linux', 'linux_freeze',
'osx32_freeze', 'osx', 'rsync', 'push',
'win32_freeze', 'win32', 'win64', 'win',
'stage1', 'stage2', 'stage3', 'stage4', 'stage5', 'publish', 'publish_betas', 'stage1', 'stage2', 'stage3', 'stage4', 'stage5', 'publish', 'publish_betas',
'linux', 'linux32', 'linux64', 'win', 'win32', 'win64', 'osx',
] ]
from setup.installers import Linux, Win, OSX, Linux32, Linux64, Win32, Win64
linux, linux32, linux64 = Linux(), Linux32(), Linux64()
win, win32, win64 = Win(), Win32(), Win64()
osx = OSX()
from setup.translations import POT, GetTranslations, Translations, ISO639, ISO3166 from setup.translations import POT, GetTranslations, Translations, ISO639, ISO3166
pot = POT() pot = POT()
@ -81,29 +83,6 @@ upload_to_server = UploadToServer()
upload_installers = UploadInstallers() upload_installers = UploadInstallers()
reupload = ReUpload() reupload = ReUpload()
from setup.installer import Rsync, Push
rsync = Rsync()
push = Push()
from setup.installer.linux import Linux, Linux32, Linux64
linux = Linux()
linux32 = Linux32()
linux64 = Linux64()
from setup.installer.linux.freeze2 import LinuxFreeze
linux_freeze = LinuxFreeze()
from setup.installer.osx import OSX
osx = OSX()
from setup.installer.osx.app.main import OSX32_Freeze
osx32_freeze = OSX32_Freeze()
from setup.installer.windows import Win, Win32, Win64
win = Win()
win32 = Win32()
win64 = Win64()
from setup.installer.windows.freeze import Win32Freeze
win32_freeze = Win32Freeze()
from setup.pypi import PyPIRegister, PyPIUpload from setup.pypi import PyPIRegister, PyPIUpload
pypi_register = PyPIRegister() pypi_register = PyPIRegister()
pypi_upload = PyPIUpload() pypi_upload = PyPIUpload()

View File

@ -1,233 +0,0 @@
#!/usr/bin/env python2
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import (unicode_literals, division, absolute_import, print_function)
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import subprocess, os, time, socket
from setup import Command, installer_name
from setup.build_environment import BUILD_HOST, PROJECT
BASE_RSYNC = ['rsync', '-av', '--delete', '--force']
EXCLUDES = []
for x in [
'/src/calibre/plugins', '/manual', '/translations', '/build', '/dist', '/imgsrc',
'/format_docs', '/.build-cache', '.bzr', '.git', '.build', '.svn', '*.pyc',
'*.pyo', '*.swp', '*.swo', '*.pyj-cached'
]:
EXCLUDES.extend(['--exclude', ('/calibre' + x) if x.startswith('/') else x])
SAFE_EXCLUDES = ['"%s"' % x if '*' in x else x for x in EXCLUDES]
def get_rsync_pw():
return open(os.environ['PENV'] + '/buildbot'
).read().decode('utf-8').partition(':')[-1].strip()
def is_vm_running(name):
qname = '"%s"' % name
try:
lines = subprocess.check_output('VBoxManage list runningvms'.split()
).decode('utf-8').splitlines()
except Exception:
time.sleep(1)
lines = subprocess.check_output('VBoxManage list runningvms'.split()
).decode('utf-8').splitlines()
for line in lines:
if line.startswith(qname):
return True
return False
def is_host_reachable(name, timeout=1):
try:
socket.create_connection((name, 22), timeout).close()
return True
except:
return False
class Rsync(Command):
description = 'Sync source tree from development machine'
SYNC_CMD = ' '.join(
BASE_RSYNC + SAFE_EXCLUDES +
['rsync://buildbot@{host}/work/{project}', '..']
)
def run(self, opts):
cmd = self.SYNC_CMD.format(host=BUILD_HOST, project=PROJECT)
env = dict(os.environ)
env['RSYNC_PASSWORD'] = get_rsync_pw()
self.info(cmd)
subprocess.check_call(cmd, shell=True, env=env)
def push(host, vmname, available):
if vmname is None:
hostname = host.partition(':')[0].partition('@')[-1]
ok = is_host_reachable(hostname)
else:
ok = is_vm_running(vmname)
if ok:
available[vmname or host] = True
rcmd = BASE_RSYNC + EXCLUDES + ['.', host]
print('\n\nPushing to:', vmname or host, '\n')
subprocess.check_call(rcmd, stdout=open(os.devnull, 'wb'))
class Push(Command):
description = 'Push code to another host'
def run(self, opts):
from threading import Thread
threads, available = {}, {}
for host, vmname in {
r'Owner@winxp:/cygdrive/c/Documents\ and\ Settings/Owner/calibre':
'winxp',
'kovid@ox:calibre': None,
r'kovid@win7:/cygdrive/c/Users/kovid/calibre': 'Windows 7',
'kovid@win7-x64:calibre': 'win7-x64',
'kovid@tiny:calibre': None,
'kovid@getafix:calibre-src': None,
}.iteritems():
threads[vmname or host] = thread = Thread(
target=push, args=(host, vmname, available)
)
thread.start()
while threads:
for name, thread in tuple(threads.iteritems()):
thread.join(0.01)
if not thread.is_alive():
if available.get(name, False):
print('\n\n', name, 'done')
threads.pop(name)
class VMInstaller(Command):
INSTALLER_EXT = None
VM_NAME = None
FREEZE_COMMAND = None
FREEZE_TEMPLATE = 'python setup.py {freeze_command}'
SHUTDOWN_CMD = ['sudo', 'shutdown', '-h', 'now']
IS_64_BIT = False
BUILD_PREFIX = ['#!/bin/sh', 'export CALIBRE_BUILDBOT=1']
BUILD_RSYNC = [
'mkdir -p ~/build/{project}', r'cd ~/build/{project}', Rsync.SYNC_CMD
]
BUILD_CLEAN = ['rm -rf dist/* build/* src/calibre/plugins/*']
BUILD_BUILD = [
'python setup.py build',
]
FORCE_SHUTDOWN = 0 # number of seconds to wait before doing a forced power off (0 means disabled)
def add_options(self, parser):
if not parser.has_option('--dont-shutdown'):
parser.add_option(
'-s',
'--dont-shutdown',
default=False,
action='store_true',
help='Dont shutdown the VM after building'
)
if not parser.has_option('--dont-strip'):
parser.add_option(
'-x',
'--dont-strip',
default=False,
action='store_true',
help='Dont strip the generated binaries'
)
def get_build_script(self):
rs = ['export RSYNC_PASSWORD=%s' % get_rsync_pw()]
ans = '\n'.join(self.BUILD_PREFIX + rs) + '\n\n'
ans += ' && \\\n'.join(self.BUILD_RSYNC) + ' && \\\n'
ans += ' && \\\n'.join(self.BUILD_CLEAN) + ' && \\\n'
ans += ' && \\\n'.join(self.BUILD_BUILD) + ' && \\\n'
ans += self.FREEZE_TEMPLATE.format(freeze_command=self.FREEZE_COMMAND) + '\n'
ans = ans.format(project=PROJECT, host=BUILD_HOST)
return ans
def run_vm(self):
if is_vm_running(self.VM_NAME):
return True
self.__p = subprocess.Popen(
("VBoxManage startvm %s --type gui" % self.VM_NAME).split()
)
return False
def start_vm(self, sleep=75):
ssh_host = self.VM_NAME
already_running = self.run_vm()
if not already_running:
time.sleep(2)
print('Waiting for SSH server to start')
while not is_host_reachable(ssh_host, timeout=1):
time.sleep(0.1)
def run_vm_builder(self):
ssh_host = self.VM_NAME
build_script = self.get_build_script()
build_script = build_script.encode('utf-8') if isinstance(
build_script, unicode
) else build_script
print('Running VM builder')
p = subprocess.Popen(['ssh', ssh_host, 'bash -s'], stdin=subprocess.PIPE)
p.stdin.write(build_script), p.stdin.flush(), p.stdin.close()
# Save the build script on the build machine for convenient manual
# invocation, if needed
p2 = subprocess.Popen(['ssh', ssh_host, 'cat > build-calibre'],
stdin=subprocess.PIPE)
p2.stdin.write(build_script), p2.stdin.flush(), p2.stdin.close()
p2.wait()
rc = p.wait()
if rc != 0:
raise SystemExit('VM builder failed with error code: %s' % rc)
self.download_installer()
def installer(self):
return installer_name(self.INSTALLER_EXT, self.IS_64_BIT)
def run(self, opts):
if opts.dont_strip:
self.FREEZE_COMMAND += ' --dont-strip'
subprocess.call(['chmod', '-R', '+r', 'recipes'])
start_time = time.time()
self.start_vm()
startup_time = time.time() - start_time
start_time = time.time()
self.run_vm_builder()
print('Startup completed in %d seconds' % round(startup_time))
secs = time.time() - start_time
print('Build completed in %d minutes %d seconds' % (secs // 60, secs % 60))
if not opts.dont_shutdown:
print('Shutting down', self.VM_NAME)
subprocess.call(['ssh', self.VM_NAME] + self.SHUTDOWN_CMD)
if self.FORCE_SHUTDOWN:
while is_host_reachable(self.VM_NAME):
time.sleep(0.1) # wait for SSH server to shutdown
time.sleep(self.FORCE_SHUTDOWN)
subprocess.check_call(
('VBoxManage controlvm %s poweroff' % self.VM_NAME).split()
)
def download_installer(self):
installer = self.installer()
subprocess.check_call([
'scp', self.VM_NAME + ':build/calibre/' + installer, 'dist'
])
if not os.path.exists(installer):
raise SystemExit('Failed to download installer: ' + installer)
def clean(self):
installer = self.installer()
if os.path.exists(installer):
os.remove(installer)

View File

@ -1,33 +0,0 @@
#!/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'
from setup.installer import VMInstaller
from setup import Command
class Linux32(VMInstaller):
description = 'Build 32bit linux binary installer'
INSTALLER_EXT = 'txz'
VM_NAME = 'linux32-build'
FREEZE_COMMAND = 'linux_freeze'
FREEZE_TEMPLATE = 'python -OO setup.py {freeze_command}'
class Linux64(Linux32):
description = 'Build 64bit linux binary installer'
VM_NAME = 'linux64-build'
IS_64_BIT = True
class Linux(Command):
description = 'Build linux binary installers'
sub_commands = ['linux64', 'linux32']

View File

@ -1,7 +0,0 @@
#!/bin/sh
# Change the version of sqlite below (get the current version from https://sqlite.org/download.html)
# You might also need to change 2013 to 2014 in the setup.py script
cd $SW/build/apsw-* && rm -rf build/* && \
python setup.py fetch --version=3.8.5 --sqlite --missing-checksum-ok && python setup.py install

View File

@ -1,7 +0,0 @@
#!/bin/sh
LBZ2=libbz2.so.1.0.6
cd $SW/build/bzip2* && make -f Makefile-libbz2_so && \
rm -f $SW/lib/libbz2* && cp -a $LBZ2 $SW/lib && ln -s $LBZ2 $SW/lib/libbz2.so && ln -s $LBZ2 $SW/lib/libbz2.so.1 && ln -s $LBZ2 $SW/lib/libbz2.so.1.0 && \
cp -a bzlib.h $SW/include

View File

@ -1,4 +0,0 @@
#!/bin/bash
cd $SW/build/chmlib* && \
./configure --disable-dependency-tracking --prefix=$SW && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/dbus-python-* && \
./configure --prefix=$SW && make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/dbus-glib-* && ./configure --prefix=$SW --disable-static && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/expat-* &&\
./configure --prefix=$SW && make && make install

View File

@ -1,6 +0,0 @@
#!/bin/sh
export FREETYPE_CFLAGS="-I$SW/include/freetype2"
export FREETYPE_LIBS="-L$SW/lib -lfreetype -lz -lbz2"
cd $SW/build/fontconfig-2.* && \
./configure --prefix=$SW --disable-static --disable-docs --with-expat=$SW --with-add-fonts=/usr/X11/lib/X11/fonts --disable-dependency-tracking && make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/freetype* && \
./configure --disable-static --prefix=$SW && make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/glib-* && ./configure --prefix=$SW --disable-selinux --disable-fam --disable-static --with-libiconv=gnu && make && make install

View File

@ -1,9 +0,0 @@
#!/bin/sh
cd $SW/build/icu*/source && \
./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man --sbindir=/usr/bin && make && \
rm -rf $SW/icu && rm -rf $SW/include/layout $SW/include/unicode && rm -f $SW/lib/libicu* && \
make -j1 DESTDIR=$SW/icu install && \
cp -ar $SW/icu/usr/include/* $SW/include && cp -a $SW/icu/usr/lib/libicu* $SW/lib/ && \
rm -rf $SW/icu

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/libgcrypt-* && ./configure --prefix=$SW --disable-static && make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/libgpg-error* && ./configure --prefix=$SW --disable-static && make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/libiconv-* && \
./configure --disable-static --disable-dependency-tracking --enable-shared --prefix=$SW && make && make install

View File

@ -1,12 +0,0 @@
#!/bin/sh
export libusbmuxd_CFLAGS=-I$SW/include
export libusbmuxd_LIBS=-lusbmuxd
export libplist_CFLAGS=-I$SW/include
export libplist_LIBS=-lplist
export libplistmm_CFLAGS=-I$SW/include
export libplistmm_LIBS=-lplist++
export openssl_CFLAGS=-I$SW/include
export openssl_LIBS="-lcrypto -lssl"
cd $SW/build/libimobiledevice-* && ./configure --prefix=$SW --disable-dependency-tracking --without-cython --disable-static && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/bash
cd $SW/build/libjpeg-turbo* && \
./configure --disable-dependency-tracking --enable-shared --with-jpeg8 --prefix=$SW && make && make install

View File

@ -1,11 +0,0 @@
#!/bin/sh
export LIBUSB_CFLAGS="-I$SW/include/libusb-1.0"
export LIBUSB_LIBS="-L$SW/lib -lusb-1.0"
export CFLAGS="$CFLAGS -DHAVE_ICONV"
export LDFLAGS="$LDFLAGS -liconv"
cd $SW/build/libmtp-* && \
./configure --disable-mtpz --disable-dependency-tracking --disable-static --prefix=$SW --with-libiconv-prefix=$SW --with-udev=$SW/udev && \
make && make install

View File

@ -1,7 +0,0 @@
#!/bin/bash
export CPPFLAGS=$CFLAGS
cd $SW/build/libpng* && \
./configure --prefix=$SW --disable-dependency-tracking --disable-static && make && make install

View File

@ -1,6 +0,0 @@
#!/bin/sh
cd $SW/build/libusb-* && \
./configure --disable-udev --disable-dependency-tracking --disable-static --prefix=$SW && \
make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/libwebp-* && ./configure --prefix=$SW --disable-static && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/libxml2-2.* && \
./configure --prefix=$SW --enable-shared --disable-static --with-iconv=$SW --with-zlib=$SW --without-python --without-debug --disable-dependency-tracking && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/libxslt-*
./configure --prefix=$SW --enable-shared --disable-static --without-python --without-debug --disable-dependency-tracking --with-libxml-prefix=$SW && make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/lxml-3* && rm -rf build/* && python setup.py install

View File

@ -1,7 +0,0 @@
#!/bin/bash
export CPPFLAGS=$CFLAGS
cd $SW/build/mozjpeg && \
./configure --prefix=$SW/private/mozjpeg --disable-dependency-tracking --disable-shared --with-jpeg8 --without-turbojpeg && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/bash
cd $SW/build/nasm* && \
./configure --prefix=$SW && make -j2 && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/ncurses-* && \
./configure --prefix=$SW --with-shared --without-debug --without-ada --enable-widec && make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/netifaces-* && python setup.py build && cp build/*/netifaces.so $SW/lib/python*/site-packages/

View File

@ -1,14 +0,0 @@
#!/bin/bash
if [[ `uname -m` == "i686" ]]; then
openssltarget=linux-elf;
optflags=''
else
openssltarget=linux-x86_64;
optflags='enable-ec_nistp_64_gcc_128';
fi
cd $SW/build/openssl-* && \
./Configure --prefix=/usr --openssldir=/etc/ssl shared zlib $optflags $openssltarget -Wa,--noexecstack $CFLAGS $LDFLAGS && make && make test && \
rm -rf $SW/openssl && rm -rf $SW/include/openssl && rm -f $SW/lib/libcrypto* $SW/lib/libssl* && \
make INSTALL_PREFIX=$SW/openssl install_sw && cp -ra $SW/openssl/usr/include/openssl $SW/include/ && cp -a $SW/openssl/usr/lib/lib*.so* $SW/lib && \
rm -rf $SW/openssl

View File

@ -1,7 +0,0 @@
#!/bin/bash
export CPPFLAGS=$CFLAGS
cd $SW/build/optipng* && \
./configure -prefix=$SW -with-system-libs && make && make install

View File

@ -1,7 +0,0 @@
#!/bin/bash
cd $SW/build/Pillow* && \
echo Disabling zip_safe && \
python -c "f = open('setup.py', 'r+b'); raw = f.read(); import re; raw = re.sub(r'zip_safe\s*=\s*True', 'zip_safe=False', raw); f.seek(0); f.truncate(0); f.write(raw)" && \
python setup.py install

View File

@ -1,5 +0,0 @@
#!/bin/sh
cd $SW/build/libplist-* && \
./configure --without-cython --disable-dependency-tracking --prefix=$SW && \
make && make install

View File

@ -1,25 +0,0 @@
#!/bin/sh
export CMAKE_INCLUDE_PATH=$SW/include
export CMAKE_LIBRARY_PATH=$SW/lib
cd $SW/build/podofo* && \
rm -rf $SW/include/podofo && \
rm -rf podofo-build && mkdir podofo-build && \
cd podofo-build && \
echo "Running cmake..." && \
cmake -G "Unix Makefiles" -Wno-dev \
-DFREETYPE_INCLUDE_DIR=$SW/include/freetype2 \
-DFREETYPE_LIBRARIES=-lfreetype \
-DCMAKE_BUILD_TYPE=RELEASE \
-DPODOFO_BUILD_SHARED:BOOL=TRUE \
-DPODOFO_BUILD_STATIC:BOOL=FALSE \
-DCMAKE_INSTALL_PREFIX=$SW \
.. && \
make VERBOSE=0 podofo_shared && \
rm -rf $SW/lib/libpodofo* $SW/include/podofo && \
mkdir $SW/include/podofo && \
cp src/libpodofo* $SW/lib && \
cp -r podofo_config.h ../src/* $SW/include/podofo/

View File

@ -1,15 +0,0 @@
#!/bin/bash
export CXXFLAGS="$CFLAGS"
export FONTCONFIG_CFLAGS="-I$SW/include/fontconfig -I$SW/include"
export FONTCONFIG_LIBS="-L$SW/lib -lfontconfig"
export FREETYPE_CFLAGS="-I$SW/include/freetype2 -I$SW/include"
export FREETYPE_LIBS="-L$SW/lib -lfreetype -lz"
export FREETYPE_CONFIG="$SW/bin/freetype-config"
export LIBJPEG_LIBS="-L$SW/lib -ljpeg"
export LIBPNG_LIBS="-L$SW/lib -lpng"
export LIBPNG_CFLAGS="-I$SW/include/libpng16"
cd $SW/build/poppler* && \
./configure --prefix $SW --without-x --enable-shared --disable-dependency-tracking --disable-silent-rules --enable-zlib --enable-splash-output --disable-cairo-output --disable-poppler-glib --disable-poppler-qt4 --disable-poppler-qt5 --disable-poppler-cpp --disable-gtk-test --enable-libjpeg --enable-compile-warnings=no && make V=1 && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/psutil-* && python setup.py build && cp -r build/lib*/* $SW/lib/python2.7/site-packages/

View File

@ -1,5 +0,0 @@
#!/bin/sh
cd $SW/build/PyQt-gpl-* && \
python configure.py --verbose --confirm-license -c -j10 --no-designer-plugin --no-qml-plugin --no-docstrings && \
make -j2 && make install

View File

@ -1,12 +0,0 @@
#!/bin/sh
export CFLAGS="$CFLAGS -DHAVE_LOAD_EXTENSION"
# Needed otherwise _ssl module fails to import because system openssl is too old
export LD_LIBRARY_PATH=$SW/lib
cd $SW/build/Python-* && \
./configure --prefix=$SW --enable-ipv6 --enable-unicode=ucs4 --with-signal-module --with-threads --with-pymalloc --with-system-expat --enable-shared && make -j2 && make install
# Install setuptools as described in windows/notes.
# Use setuptools to install the various python packages

View File

@ -1,18 +0,0 @@
#!/bin/bash
# See windows/notes.rst for instructions on slimming down Qt.
# We disable loading of bearer plugins because many distros ship with broken bearer plugins that cause hangs.
# At least, this was the case in Qt 4.x Dont know if it is still true for Qt 5 but since we dont need bearers anyway, it cant hurt.
cd $SW/build/qt-* && sed -i -e 's:/bearer":/bearer-disabled-by-kovid":' qtbase/src/network/bearer/qnetworkconfigmanager_p.cpp || die "sed for bearer failed."
# Change pointing_hand to hand2, see https://bugreports.qt.io/browse/QTBUG-41151
cd $SW/build/qt-* && sed -i -e 's:pointing_hand":hand2":' qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp || die "sed for pointing_hand failed."
# libudev is disabled because systemd based distros use libudev.so.1 while non systemd based distros use libudev.so.0 (debian stable currently uses libudev.so.0). And according to the incompetent udev developers, we cannot use mismatching udev client and daemon versions. http://www.marshut.com/yiqmk/can-apps-ship-their-own-copy-of-libudev.html
rm -rf build && mkdir build && cd build && \
../configure -opensource -confirm-license -prefix $SW/qt -release -nomake examples -nomake tests -no-sql-odbc -no-sql-psql -no-qml-debug -qt-xcb -cups -no-c++11 -force-pkg-config -pulseaudio -no-libudev -openssl -gtkstyle -icu $CFLAGS $LDFLAGS && \
make -j4 && rm -rf $SW/qt && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/readline* && \
./configure --prefix=$SW --disable-static && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/sip-* && \
python configure.py && make && make install

View File

@ -1,5 +0,0 @@
#!/bin/sh
export CFLAGS="$CFLAGS"
cd $SW/build/sqlite-* &&\
./configure --prefix=$SW --disable-dependency-tracking --disable-static && make && make install

View File

@ -1,12 +0,0 @@
#!/bin/sh
# Apply the patch to prevent detection of WIFI devices, from http://www.mobileread.com/forums/showthread.php?t=255234
export libplist_CFLAGS="-I$SW/include"
export libplist_LIBS="-L$SW/lib -lplist"
export CPPFLAGS="$CFLAGS"
export CXXFLAGS="$CFLAGS"
cd $SW/build/libusbmuxd-* && \
./configure --prefix=$SW --disable-dependency-tracking && \
make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/xpyb && ./autogen.sh && ./configure --prefix=$SW && make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/zlib-* && \
./configure --prefix=$SW && make && make install

View File

@ -1,8 +0,0 @@
#!/bin/sh
cd $HOME
rm sw-linux*;
cp /usr/lib/x86_64-linux-gnu/libffi.so.5 /lib/x86_64-linux-gnu/libdbus-1.so.3 ~/sw/lib/
echo "[Paths]\nPrefix = .." > ~/sw/qt/bin/qt.conf && cat ~/sw/qt/bin/qt.conf
echo "[Paths]\nPrefix = ../qt" > ~/sw/bin/qt.conf && cat ~/sw/bin/qt.conf
tar cf sw-linux.tar --exclude sw/build --exclude sw/sources --exclude sw/man --exclude '*.pyc' --exclude '*.pyo' --exclude 'sw/share/doc' --exclude sw/share/gtk-doc --exclude sw/share/man --exclude sw/share/info sw && xz -9 sw-linux.tar
rm ~/sw/lib/libffi.so.5 ~/sw/lib/libdbus-1.so.3 ~/sw/qt/bin/qt.conf ~/sw/bin/qt.conf

View File

@ -1,451 +0,0 @@
#!/usr/bin/env python2
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
'''
Setup instructions for linux build-system
Edit /etc/network/interfaces and add
iface eth1 inet static
address 192.168.xxx.xxx
Also add eth1 to the auto line (use sudo ifup eth1 to start eth1 without rebooting)
sudo visudo (all no password actions for user)
sudo apt-get install build-essential module-assistant vim zsh vim-scripts rsync \
htop nasm unzip libdbus-1-dev cmake libltdl-dev libudev-dev apt-file p7zip \
libdbus-glib-1-dev libcups2-dev "^libxcb.*" libx11-xcb-dev libglu1-mesa-dev \
libxrender-dev flex bison gperf libasound2-dev libgstreamer0.10-dev \
libgstreamer-plugins-base0.10-dev libpulse-dev libgtk2.0-dev libffi-dev xcb-proto python-xcbgen dh-autoreconf
apt-file update
# For recent enough version of debian (>= sid) also install libxkbcommon-dev
mkdir -p ~/bin ~/sw/sources ~/sw/build
chsh -s /bin/zsh
Edit /etc/default/grub and change the GRUB_TIMEOUT to 1, then run
sudo update-grub
Copy over authorized_keys, .vimrc and .zshrc
Create ~/.zshenv as
export SW=$HOME/sw
export MAKEOPTS="-j2"
export CFLAGS=-I$SW/include
export LDFLAGS=-L$SW/lib
export LD_LIBRARY_PATH=$SW/lib
export PKG_CONFIG_PATH=$SW/lib/pkgconfig:$PKG_CONFIG_PATH
typeset -U path
path=($SW/bin "$path[@]")
path=($SW/qt/bin "$path[@]")
path=(~/bin "$path[@]")
'''
import sys, os, shutil, platform, subprocess, stat, py_compile, glob, textwrap, tarfile, time
from functools import partial
from setup import Command, modules, basenames, functions, __version__, __appname__
from setup.build_environment import QT_DLLS, QT_PLUGINS, qt, PYQT_MODULES, sw as SW
from setup.parallel_build import create_job, parallel_build
j = os.path.join
is64bit = platform.architecture()[0] == '64bit'
py_ver = '.'.join(map(str, sys.version_info[:2]))
arch = 'x86_64' if is64bit else 'i686'
def binary_includes():
return [
j(SW, 'bin', x) for x in ('pdftohtml', 'pdfinfo', 'pdftoppm', 'optipng')] + [
j(SW, 'private', 'mozjpeg', 'bin', x) for x in ('jpegtran', 'cjpeg')] + [
j(SW, 'lib', 'lib' + x) for x in (
'usb-1.0.so.0', 'mtp.so.9', 'expat.so.1', 'sqlite3.so.0',
'podofo.so.0.9.3', 'z.so.1', 'bz2.so.1.0', 'poppler.so.56',
'iconv.so.2', 'xml2.so.2', 'xslt.so.1', 'jpeg.so.8', 'png16.so.16', 'webp.so.5',
'exslt.so.0', 'imobiledevice.so.5', 'usbmuxd.so.4', 'plist.so.3',
'ssl.so.1.0.0', 'crypto.so.1.0.0', 'readline.so.6', 'chm.so.0', 'icudata.so.53',
'icui18n.so.53', 'icuuc.so.53', 'icuio.so.53', 'python%s.so.1.0' % py_ver,
'gcrypt.so.20', 'gpg-error.so.0', 'gobject-2.0.so.0', 'glib-2.0.so.0',
'gthread-2.0.so.0', 'gmodule-2.0.so.0', 'gio-2.0.so.0', 'dbus-glib-1.so.2',
)] + [
glob.glob('/lib/*/lib' + x)[-1] for x in (
'dbus-1.so.3', 'pcre.so.3'
)] + [
glob.glob('/usr/lib/*/lib' + x)[-1] for x in (
'gstreamer-0.10.so.0', 'gstbase-0.10.so.0', 'gstpbutils-0.10.so.0',
'gstapp-0.10.so.0', 'gstinterfaces-0.10.so.0', 'gstvideo-0.10.so.0', 'orc-0.4.so.0',
'ffi.so.5',
# 'stdc++.so.6',
# We dont include libstdc++.so as the OpenGL dlls on the target
# computer fail to load in the QPA xcb plugin if they were compiled
# with a newer version of gcc than the one on the build computer.
# libstdc++, like glibc is forward compatible and I dont think any
# distros do not have libstdc++.so.6, so it should be safe to leave it out.
# https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html (The current
# debian stable libstdc++ is libstdc++.so.6.0.17)
)] + [
j(qt['libs'], 'lib%s.so.5' % x) for x in QT_DLLS]
def ignore_in_lib(base, items, ignored_dirs=None):
ans = []
if ignored_dirs is None:
ignored_dirs = {'.svn', '.bzr', '.git', 'test', 'tests', 'testing'}
for name in items:
path = os.path.join(base, name)
if os.path.isdir(path):
if name in ignored_dirs or not os.path.exists(j(path, '__init__.py')):
if name != 'plugins':
ans.append(name)
else:
if name.rpartition('.')[-1] not in ('so', 'py'):
ans.append(name)
return ans
def import_site_packages(srcdir, dest):
if not os.path.exists(dest):
os.mkdir(dest)
for x in os.listdir(srcdir):
ext = x.rpartition('.')[-1]
f = j(srcdir, x)
if ext in ('py', 'so'):
shutil.copy2(f, dest)
elif ext == 'pth' and x != 'setuptools.pth':
for line in open(f, 'rb').read().splitlines():
src = os.path.abspath(j(srcdir, line))
if os.path.exists(src) and os.path.isdir(src):
import_site_packages(src, dest)
elif os.path.exists(j(f, '__init__.py')):
shutil.copytree(f, j(dest, x), ignore=ignore_in_lib)
def is_elf(path):
with open(path, 'rb') as f:
return f.read(4) == b'\x7fELF'
STRIPCMD = ['strip']
def strip_files(files, argv_max=(256 * 1024)):
""" Strip a list of files """
while files:
cmd = list(STRIPCMD)
pathlen = sum(len(s) + 1 for s in cmd)
while pathlen < argv_max and files:
f = files.pop()
cmd.append(f)
pathlen += len(f) + 1
if len(cmd) > len(STRIPCMD):
all_files = cmd[len(STRIPCMD):]
unwritable_files = tuple(filter(None, (None if os.access(x, os.W_OK) else (x, os.stat(x).st_mode) for x in all_files)))
[os.chmod(x, stat.S_IWRITE | old_mode) for x, old_mode in unwritable_files]
subprocess.check_call(cmd)
[os.chmod(x, old_mode) for x, old_mode in unwritable_files]
class LinuxFreeze(Command):
def add_options(self, parser):
if not parser.has_option('--dont-strip'):
parser.add_option('-x', '--dont-strip', default=False,
action='store_true', help='Dont strip the generated binaries')
def run(self, opts):
self.drop_privileges()
self.opts = opts
self.src_root = self.d(self.SRC)
self.base = self.j(self.src_root, 'build', 'linfrozen')
self.lib_dir = self.j(self.base, 'lib')
self.bin_dir = self.j(self.base, 'bin')
self.initbase()
self.copy_libs()
self.copy_python()
self.build_launchers()
if not self.opts.dont_strip:
self.strip_files()
self.create_tarfile()
def initbase(self):
if os.path.exists(self.base):
shutil.rmtree(self.base)
os.makedirs(self.base)
def copy_libs(self):
self.info('Copying libs...')
os.mkdir(self.lib_dir)
os.mkdir(self.bin_dir)
for x in binary_includes():
dest = self.bin_dir if '/bin/' in x else self.lib_dir
shutil.copy2(x, dest)
base = qt['plugins']
dest = self.j(self.lib_dir, 'qt_plugins')
os.mkdir(dest)
for x in QT_PLUGINS:
shutil.copytree(self.j(base, x), self.j(dest, x))
def copy_python(self):
self.info('Copying python...')
srcdir = self.j(SW, 'lib/python'+py_ver)
self.py_dir = self.j(self.lib_dir, self.b(srcdir))
if not os.path.exists(self.py_dir):
os.mkdir(self.py_dir)
for x in os.listdir(srcdir):
y = self.j(srcdir, x)
ext = os.path.splitext(x)[1]
if os.path.isdir(y) and x not in ('test', 'hotshot', 'distutils',
'site-packages', 'idlelib', 'lib2to3', 'dist-packages'):
shutil.copytree(y, self.j(self.py_dir, x),
ignore=ignore_in_lib)
if os.path.isfile(y) and ext in ('.py', '.so'):
shutil.copy2(y, self.py_dir)
srcdir = self.j(srcdir, 'site-packages')
dest = self.j(self.py_dir, 'site-packages')
import_site_packages(srcdir, dest)
filter_pyqt = {x+'.so' for x in PYQT_MODULES}
pyqt = self.j(dest, 'PyQt5')
for x in os.listdir(pyqt):
if x.endswith('.so') and x not in filter_pyqt:
os.remove(self.j(pyqt, x))
for x in os.listdir(self.SRC):
c = self.j(self.SRC, x)
if os.path.exists(self.j(c, '__init__.py')):
shutil.copytree(c, self.j(dest, x), ignore=partial(ignore_in_lib, ignored_dirs={}))
elif os.path.isfile(c):
shutil.copy2(c, self.j(dest, x))
shutil.copytree(self.j(self.src_root, 'resources'), self.j(self.base,
'resources'))
self.create_site_py()
for x in os.walk(self.py_dir):
for f in x[-1]:
if f.endswith('.py'):
y = self.j(x[0], f)
rel = os.path.relpath(y, self.py_dir)
try:
py_compile.compile(y, dfile=rel, doraise=True)
os.remove(y)
z = y+'c'
if os.path.exists(z):
os.remove(z)
except:
if '/uic/port_v3/' not in y:
self.warn('Failed to byte-compile', y)
def run_builder(self, cmd, verbose=True):
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if verbose:
self.info(*cmd)
x = p.stdout.read() + p.stderr.read()
if x.strip():
self.info(x.strip())
if p.wait() != 0:
self.info('Failed to run builder')
sys.exit(1)
def create_tarfile(self):
self.info('Creating archive...')
base = self.j(self.d(self.SRC), 'dist')
if not os.path.exists(base):
os.mkdir(base)
dist = os.path.join(base, '%s-%s-%s.tar'%(__appname__, __version__, arch))
with tarfile.open(dist, mode='w', format=tarfile.PAX_FORMAT) as tf:
cwd = os.getcwd()
os.chdir(self.base)
try:
for x in os.listdir('.'):
tf.add(x)
finally:
os.chdir(cwd)
self.info('Compressing archive...')
ans = dist.rpartition('.')[0] + '.txz'
if False:
os.rename(dist, ans)
else:
start_time = time.time()
subprocess.check_call(['xz', '--threads=0', '-f', '-9', dist])
secs = time.time() - start_time
self.info('Compressed in %d minutes %d seconds' % (secs // 60, secs % 60))
os.rename(dist + '.xz', ans)
self.info('Archive %s created: %.2f MB'%(
os.path.basename(ans), os.stat(ans).st_size/(1024.**2)))
def build_launchers(self):
self.obj_dir = self.j(self.src_root, 'build', 'launcher')
if not os.path.exists(self.obj_dir):
os.makedirs(self.obj_dir)
base = self.j(self.src_root, 'setup', 'installer', 'linux')
sources = [self.j(base, x) for x in ['util.c']]
headers = [self.j(base, x) for x in ['util.h']]
objects = [self.j(self.obj_dir, self.b(x)+'.o') for x in sources]
cflags = '-fno-strict-aliasing -W -Wall -c -O2 -pipe -DPYTHON_VER="python%s"'%py_ver
cflags = cflags.split() + ['-I%s/include/python%s' % (SW, py_ver)]
for src, obj in zip(sources, objects):
if not self.newer(obj, headers+[src, __file__]):
continue
cmd = ['gcc'] + cflags + ['-fPIC', '-o', obj, src]
self.run_builder(cmd)
dll = self.j(self.lib_dir, 'libcalibre-launcher.so')
if self.newer(dll, objects):
cmd = ['gcc', '-O2', '-Wl,--rpath=$ORIGIN/../lib', '-fPIC', '-o', dll, '-shared'] + objects + \
['-L%s/lib'%SW, '-lpython'+py_ver]
self.info('Linking libcalibre-launcher.so')
self.run_builder(cmd)
src = self.j(base, 'main.c')
modules['console'].append('calibre.linux')
basenames['console'].append('calibre_postinstall')
functions['console'].append('main')
c_launcher = '/tmp/calibre-c-launcher'
lsrc = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'launcher.c')
cmd = ['gcc', '-O2', '-o', c_launcher, lsrc, ]
self.info('Compiling launcher')
self.run_builder(cmd, verbose=False)
jobs = []
self.info('Processing launchers')
for typ in ('console', 'gui', ):
for mod, bname, func in zip(modules[typ], basenames[typ],
functions[typ]):
xflags = list(cflags)
xflags.remove('-c')
xflags += ['-DGUI_APP='+('1' if typ == 'gui' else '0')]
xflags += ['-DMODULE="%s"'%mod, '-DBASENAME="%s"'%bname,
'-DFUNCTION="%s"'%func]
exe = self.j(self.bin_dir, bname)
if self.newer(exe, [src, __file__]+headers):
cmd = ['gcc'] + xflags + [src, '-o', exe, '-L' + self.lib_dir, '-lcalibre-launcher']
jobs.append(create_job(cmd))
sh = self.j(self.base, bname)
shutil.copy2(c_launcher, sh)
os.chmod(sh,
stat.S_IREAD|stat.S_IEXEC|stat.S_IWRITE|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH)
if jobs:
if not parallel_build(jobs, self.info, verbose=False):
raise SystemExit(1)
def strip_files(self):
from calibre import walk
files = {self.j(self.bin_dir, x) for x in os.listdir(self.bin_dir)} | {
x for x in {
self.j(self.d(self.bin_dir), x) for x in os.listdir(self.bin_dir)} if os.path.exists(x)}
for x in walk(self.lib_dir):
x = os.path.realpath(x)
if x not in files and is_elf(x):
files.add(x)
self.info('Stripping %d files...' % len(files))
before = sum(os.path.getsize(x) for x in files)
strip_files(files)
after = sum(os.path.getsize(x) for x in files)
self.info('Stripped %.1f MB' % ((before - after)/(1024*1024.)))
def create_site_py(self): # {{{
with open(self.j(self.py_dir, 'site.py'), 'wb') as f:
f.write(textwrap.dedent('''\
import sys
import encodings # noqa
import __builtin__
import locale
import os
import codecs
def set_default_encoding():
try:
locale.setlocale(locale.LC_ALL, '')
except:
print ('WARNING: Failed to set default libc locale, using en_US.UTF-8')
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
try:
enc = locale.getdefaultlocale()[1]
except Exception:
enc = None
if not enc:
enc = locale.nl_langinfo(locale.CODESET)
if not enc or enc.lower() == 'ascii':
enc = 'UTF-8'
try:
enc = codecs.lookup(enc).name
except LookupError:
enc = 'UTF-8'
sys.setdefaultencoding(enc)
del sys.setdefaultencoding
class _Helper(object):
"""Define the builtin 'help'.
This is a wrapper around pydoc.help (with a twist).
"""
def __repr__(self):
return "Type help() for interactive help, " \
"or help(object) for help about object."
def __call__(self, *args, **kwds):
import pydoc
return pydoc.help(*args, **kwds)
def set_helper():
__builtin__.help = _Helper()
def setup_openssl_environment():
# Workaround for Linux distros that have still failed to get their heads
# out of their asses and implement a common location for SSL certificates.
# It's not that hard people, there exists a wonderful tool called the symlink
# See http://www.mobileread.com/forums/showthread.php?t=256095
if b'SSL_CERT_FILE' not in os.environ and b'SSL_CERT_DIR' not in os.environ:
if os.access('/etc/pki/tls/certs/ca-bundle.crt', os.R_OK):
os.environ['SSL_CERT_FILE'] = '/etc/pki/tls/certs/ca-bundle.crt'
elif os.path.isdir('/etc/ssl/certs'):
os.environ['SSL_CERT_DIR'] = '/etc/ssl/certs'
def main():
try:
sys.argv[0] = sys.calibre_basename
dfv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
if dfv and os.path.exists(dfv):
sys.path.insert(0, os.path.abspath(dfv))
set_default_encoding()
set_helper()
setup_openssl_environment()
mod = __import__(sys.calibre_module, fromlist=[1])
func = getattr(mod, sys.calibre_function)
return func()
except SystemExit as err:
if err.code is None:
return 0
if isinstance(err.code, int):
return err.code
print (err.code)
return 1
except:
import traceback
traceback.print_exc()
return 1
'''))
# }}}

View File

@ -1,55 +0,0 @@
/*
* launcher.c
* Copyright (C) 2014 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <libgen.h>
#include <stdlib.h>
#define PATHLEN 1023
#define SET(x, y) if (setenv(x, y, 1) != 0) { fprintf(stderr, "Failed to set environment variable with error: %s\n", strerror(errno)); return 1; }
int main(int argc, char **argv) {
static char buf[PATHLEN+1] = {0}, lib[PATHLEN+1] = {0}, base[PATHLEN+1] = {0}, exe[PATHLEN+1] = {0}, *ldp = NULL;
if (readlink("/proc/self/exe", buf, PATHLEN) == -1) {
fprintf(stderr, "Failed to read path of executable with error: %s\n", strerror(errno));
return 1;
}
strncpy(lib, buf, PATHLEN);
strncpy(base, dirname(lib), PATHLEN);
snprintf(exe, PATHLEN, "%s/bin/%s", base, basename(buf));
memset(lib, 0, PATHLEN);
snprintf(lib, PATHLEN, "%s/lib", base);
/* qt-at-spi causes crashes and performance issues in various distros, so disable it */
SET("QT_ACCESSIBILITY", "0")
memset(buf, 0, PATHLEN);
ldp = getenv("QT_PLUGIN_PATH");
if (ldp == NULL) snprintf(buf, PATHLEN, "%s/qt_plugins", lib);
else snprintf(buf, PATHLEN, "%s/qt_plugins:%s", lib, ldp);
SET("QT_PLUGIN_PATH", buf);
memset(buf, 0, PATHLEN);
ldp = getenv("LD_LIBRARY_PATH");
if (ldp == NULL) strncpy(buf, lib, PATHLEN);
else snprintf(buf, PATHLEN, "%s:%s", lib, ldp);
SET("LD_LIBRARY_PATH", buf)
argv[0] = exe;
if (execv(exe, argv) == -1) {
fprintf(stderr, "Failed to execute binary: %s with error: %s\n", exe, strerror(errno));
return 1;
}
return 0;
}

View File

@ -1,13 +0,0 @@
#include "util.h"
#include <stdlib.h>
int main(int argc, char **argv) {
int ret = 0;
set_gui_app(GUI_APP);
ret = execute_python_entrypoint(argc, argv, BASENAME, MODULE, FUNCTION, NULL, NULL);
return ret;
}

View File

@ -1,263 +0,0 @@
#include "util.h"
#include <Python.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
#include <errno.h>
static bool GUI_APP = False;
static char exe_path[PATH_MAX];
static char base_dir[PATH_MAX];
static char bin_dir[PATH_MAX];
static char lib_dir[PATH_MAX];
static char extensions_dir[PATH_MAX];
static char resources_dir[PATH_MAX];
void set_gui_app(bool yes) { GUI_APP = yes; }
int report_error(const char *msg, int code) {
fprintf(stderr, "%s\n", msg);
return code;
}
int report_libc_error(const char *msg) {
char buf[2000];
int err = errno;
snprintf(buf, 2000, "%s::%s", msg, strerror(err));
return report_error(buf, err);
}
int pyobject_to_int(PyObject *res) {
int ret = 0; PyObject *tmp;
if (res != NULL) {
tmp = PyNumber_Int(res);
if (tmp == NULL) ret = (PyObject_IsTrue(res)) ? 1 : 0;
else ret = (int)PyInt_AS_LONG(tmp);
}
return ret;
}
int handle_sysexit(PyObject *e) {
PyObject *code;
code = PyObject_GetAttrString(e, "code");
if (!code) return 0;
return pyobject_to_int(code);
}
int report_python_error(const char *preamble, int code) {
PyObject *exc, *val, *tb, *str;
int ret, issysexit = 0; char *i, *buf;
if (!PyErr_Occurred()) return code;
issysexit = PyErr_ExceptionMatches(PyExc_SystemExit);
PyErr_Fetch(&exc, &val, &tb);
if (exc != NULL) {
PyErr_NormalizeException(&exc, &val, &tb);
if (issysexit) {
return (val) ? handle_sysexit(val) : 0;
}
if (val != NULL) {
str = PyObject_Unicode(val);
if (str == NULL) {
PyErr_Clear();
str = PyObject_Str(val);
}
i = PyString_AsString(str);
if (i == NULL) OOM;
buf = (char*)calloc(strlen(i)+strlen(preamble)+5, sizeof(char));
if (buf == NULL) OOM;
sprintf(buf, "%s::%s", preamble, i);
ret = report_error(buf, code);
if (buf) free(buf);
if (tb != NULL) {
PyErr_Restore(exc, val, tb);
PyErr_Print();
}
return ret;
}
}
return report_error(preamble, code);
}
static void get_paths()
{
char linkname[256]; /* /proc/<pid>/exe */
char *p;
pid_t pid;
int ret;
pid = getpid();
if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", pid) < 0)
{
/* This should only happen on large word systems. I'm not sure
what the proper response is here.
Since it really is an assert-like condition, aborting the
program seems to be in order. */
exit(report_error("PID too large", EXIT_FAILURE));
}
ret = readlink(linkname, exe_path, PATH_MAX);
if (ret == -1) {
exit(report_error("Failed to read exe path.", EXIT_FAILURE));
}
if (ret >= PATH_MAX) {
exit(report_error("exe path buffer too small.", EXIT_FAILURE));
}
exe_path[ret] = 0;
p = rindex(exe_path, '/');
if (p == NULL) {
exit(report_error("No path separators in executable path", EXIT_FAILURE));
}
strncat(base_dir, exe_path, p - exe_path);
p = rindex(base_dir, '/');
if (p == NULL) {
exit(report_error("Only one path separator in executable path", EXIT_FAILURE));
}
*p = 0;
snprintf(bin_dir, PATH_MAX, "%s/bin", base_dir);
snprintf(lib_dir, PATH_MAX, "%s/lib", base_dir);
snprintf(resources_dir, PATH_MAX, "%s/resources", base_dir);
snprintf(extensions_dir, PATH_MAX, "%s/%s/site-packages/calibre/plugins", lib_dir, PYTHON_VER);
}
void setup_stream(const char *name, const char *errors) {
PyObject *stream;
char buf[100];
snprintf(buf, 20, "%s", name);
stream = PySys_GetObject(buf);
snprintf(buf, 20, "%s", "utf-8");
snprintf(buf+21, 30, "%s", errors);
if (!PyFile_SetEncodingAndErrors(stream, buf, buf+21))
exit(report_python_error("Failed to set stream encoding", 1));
}
void setup_streams() {
if (!GUI_APP) { // Remove buffering
setvbuf(stdin, NULL, _IONBF, 2);
setvbuf(stdout, NULL, _IONBF, 2);
setvbuf(stderr, NULL, _IONBF, 2);
}
/*setup_stream("stdin", "strict");
setup_stream("stdout", "strict");
setup_stream("stderr", "strict");*/
}
void initialize_interpreter(int argc, char **argv, char *outr, char *errr,
const char *basename, const char *module, const char *function) {
char *path, *encoding, *p;
get_paths();
path = (char*)calloc(3*PATH_MAX, sizeof(char));
if (!path) OOM;
snprintf(path, 3*PATH_MAX,
"%s/%s:%s/%s/plat-linux2:%s/%s/lib-dynload:%s/%s/site-packages",
lib_dir, PYTHON_VER, lib_dir, PYTHON_VER, lib_dir, PYTHON_VER,
lib_dir, PYTHON_VER);
Py_OptimizeFlag = 2;
Py_NoSiteFlag = 1;
Py_DontWriteBytecodeFlag = 1;
Py_IgnoreEnvironmentFlag = 1;
Py_NoUserSiteDirectory = 1;
Py_VerboseFlag = 0;
Py_DebugFlag = 0;
Py_HashRandomizationFlag = 1;
Py_SetProgramName(exe_path);
Py_SetPythonHome(base_dir);
//printf("Path before Py_Initialize(): %s\r\n\n", Py_GetPath());
Py_Initialize();
if (!Py_FileSystemDefaultEncoding) {
encoding = getenv("PYTHONIOENCODING");
if (encoding != NULL) {
Py_FileSystemDefaultEncoding = strndup(encoding, 20);
p = index(Py_FileSystemDefaultEncoding, ':');
if (p != NULL) *p = 0;
} else
Py_FileSystemDefaultEncoding = strndup("UTF-8", 10);
}
setup_streams();
PySys_SetArgv(argc, argv);
//printf("Path after Py_Initialize(): %s\r\n\n", Py_GetPath());
PySys_SetPath(path);
//printf("Path set by me: %s\r\n\n", path);
PySys_SetObject("gui_app", PyBool_FromLong((long)GUI_APP));
PySys_SetObject("calibre_basename", PyBytes_FromString(basename));
PySys_SetObject("calibre_module", PyBytes_FromString(module));
PySys_SetObject("calibre_function", PyBytes_FromString(function));
PySys_SetObject("extensions_location", PyBytes_FromString(extensions_dir));
PySys_SetObject("resources_location", PyBytes_FromString(resources_dir));
PySys_SetObject("executables_location", PyBytes_FromString(base_dir));
PySys_SetObject("frozen_path", PyBytes_FromString(base_dir));
PySys_SetObject("frozen", Py_True);
Py_INCREF(Py_True);
if (GUI_APP && outr && errr) {
// PySys_SetObject("stdout_redirect", PyUnicode_FromWideChar(outr, wcslen(outr)));
// PySys_SetObject("stderr_redirect", PyUnicode_FromWideChar(errr, wcslen(outr)));
}
}
int execute_python_entrypoint(int argc, char **argv, const char *basename, const char *module, const char *function,
char *outr, char *errr) {
PyObject *site, *pmain, *res;
int ret = 0;
initialize_interpreter(argc, argv, outr, errr, basename, module, function);
site = PyImport_ImportModule("site");
if (site == NULL)
ret = report_python_error("Failed to import site module", 1);
else {
Py_XINCREF(site);
pmain = PyObject_GetAttrString(site, "main");
if (pmain == NULL || !PyCallable_Check(pmain))
ret = report_python_error("site module has no main function", 1);
else {
Py_XINCREF(pmain);
res = PyObject_CallObject(pmain, NULL);
if (res == NULL)
ret = report_python_error("Python function terminated unexpectedly", 1);
ret = pyobject_to_int(res);
}
}
PyErr_Clear();
Py_Finalize();
//printf("11111 Returning: %d\r\n", ret);
return ret;
}

View File

@ -1,18 +0,0 @@
#pragma once
#define UNICODE
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#define OOM exit(report_error("Out of memory", EXIT_FAILURE))
#define True 1
#define False 0
typedef int bool;
void set_gui_app(bool yes);
int execute_python_entrypoint(int argc, char **argv, const char *basename,
const char *module, const char *function,
char *outr, char *errr);

View File

@ -1,20 +0,0 @@
#!/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'
from setup.installer import VMInstaller
class OSX(VMInstaller):
description = 'Build OS X binary installer'
INSTALLER_EXT = 'dmg'
VM_NAME = 'osx-build'
FREEZE_TEMPLATE = 'python -OO setup.py {freeze_command}'
FREEZE_COMMAND = 'osx32_freeze'
FORCE_SHUTDOWN = 10 # number of seconds to wait before doing a forced power off

View File

@ -1,10 +0,0 @@
#!/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'

View File

@ -1,17 +0,0 @@
#include "util.h"
#include <stdlib.h>
// These variables must be filled in before compiling
static const char *ENV_VARS[] = { /*ENV_VARS*/ NULL };
static const char *ENV_VAR_VALS[] = { /*ENV_VAR_VALS*/ NULL};
static char PROGRAM[] = "**PROGRAM**";
static const char MODULE[] = "**MODULE**";
static const char FUNCTION[] = "**FUNCTION**";
static const char PYVER[] = "**PYVER**";
int
main(int argc, const char **argv, const char **envp) {
return run(ENV_VARS, ENV_VAR_VALS, PROGRAM, MODULE, FUNCTION, PYVER, **IS_GUI**, argc, argv, envp);
}

View File

@ -1,726 +0,0 @@
#!/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 sys, os, shutil, plistlib, subprocess, glob, zipfile, tempfile, \
py_compile, stat, operator, time
from functools import partial
from contextlib import contextmanager
from itertools import repeat
abspath, join, basename = os.path.abspath, os.path.join, os.path.basename
from setup import (
__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
from setup.installer.osx.app.sign import current_dir, sign_app
LICENSE = open('LICENSE', 'rb').read()
ENV = dict(
FONTCONFIG_PATH='@executable_path/../Resources/fonts',
FONTCONFIG_FILE='@executable_path/../Resources/fonts/fonts.conf',
QT_PLUGIN_PATH='@executable_path/../MacOS/qt-plugins',
PYTHONIOENCODING='UTF-8',
SSL_CERT_FILE='@executable_path/../Resources/resources/mozilla-ca-certs.pem',
)
info = warn = None
@contextmanager
def timeit():
times = [0, 0]
st = time.time()
yield times
dt = time.time() - st
times[0], times[1] = dt // 60, dt % 60
class OSX32_Freeze(Command):
description = 'Freeze OSX calibre installation'
def add_options(self, parser):
parser.add_option('--test-launchers', default=False,
action='store_true',
help='Only build launchers')
if not parser.has_option('--dont-strip'):
parser.add_option('-x', '--dont-strip', default=False,
action='store_true', help='Dont strip the generated binaries')
def run(self, opts):
global info, warn
info, warn = self.info, self.warn
main(opts.test_launchers, opts.dont_strip)
def compile_launcher_lib(contents_dir, gcc, base):
info('\tCompiling calibre_launcher.dylib')
fd = join(contents_dir, 'Frameworks')
dest = join(fd, 'calibre-launcher.dylib')
src = join(base, 'util.c')
cmd = [gcc] + '-Wall -dynamiclib -std=gnu99'.split() + [src] + \
['-I'+base] + \
['-I%s/python/Python.framework/Versions/Current/Headers' % SW] + \
'-current_version 1.0 -compatibility_version 1.0'.split() + \
'-fvisibility=hidden -o'.split() + [dest] + \
['-install_name',
'@executable_path/../Frameworks/'+os.path.basename(dest)] + \
[('-F%s/python' % SW), '-framework', 'Python', '-framework', 'CoreFoundation', '-headerpad_max_install_names']
# info('\t'+' '.join(cmd))
sys.stdout.flush()
subprocess.check_call(cmd)
return dest
def compile_launchers(contents_dir, xprograms, pyver):
gcc = os.environ.get('CC', 'gcc')
base = os.path.dirname(__file__)
lib = compile_launcher_lib(contents_dir, gcc, base)
src = open(join(base, 'launcher.c'), 'rb').read()
env, env_vals = [], []
for key, val in ENV.items():
env.append('"%s"'% key)
env_vals.append('"%s"'% val)
env = ', '.join(env)+', '
env_vals = ', '.join(env_vals)+', '
src = src.replace('/*ENV_VARS*/', env)
src = src.replace('/*ENV_VAR_VALS*/', env_vals)
programs = [lib]
for program, x in xprograms.iteritems():
module, func, ptype = x
info('\tCompiling', program)
out = join(contents_dir, 'MacOS', program)
programs.append(out)
psrc = src.replace('**PROGRAM**', program)
psrc = psrc.replace('**MODULE**', module)
psrc = psrc.replace('**FUNCTION**', func)
psrc = psrc.replace('**PYVER**', pyver)
psrc = psrc.replace('**IS_GUI**', ('1' if ptype == 'gui' else '0'))
fsrc = '/tmp/%s.c'%program
with open(fsrc, 'wb') as f:
f.write(psrc)
cmd = [gcc, '-Wall', '-I'+base, fsrc, lib, '-o', out,
'-headerpad_max_install_names']
# info('\t'+' '.join(cmd))
sys.stdout.flush()
subprocess.check_call(cmd)
return programs
def flipwritable(fn, mode=None):
"""
Flip the writability of a file and return the old mode. Returns None
if the file is already writable.
"""
if os.access(fn, os.W_OK):
return None
old_mode = os.stat(fn).st_mode
os.chmod(fn, stat.S_IWRITE | old_mode)
return old_mode
STRIPCMD = ['/usr/bin/strip', '-x', '-S', '-']
def strip_files(files, argv_max=(256 * 1024)):
"""
Strip a list of files
"""
tostrip = [(fn, flipwritable(fn)) for fn in files if os.path.exists(fn)]
while tostrip:
cmd = list(STRIPCMD)
flips = []
pathlen = reduce(operator.add, [len(s) + 1 for s in cmd])
while pathlen < argv_max:
if not tostrip:
break
added, flip = tostrip.pop()
pathlen += len(added) + 1
cmd.append(added)
flips.append((added, flip))
else:
cmd.pop()
tostrip.append(flips.pop())
os.spawnv(os.P_WAIT, cmd[0], cmd)
for args in flips:
flipwritable(*args)
def flush(func):
def ff(*args, **kwargs):
sys.stdout.flush()
sys.stderr.flush()
ret = func(*args, **kwargs)
sys.stdout.flush()
sys.stderr.flush()
return ret
return ff
class Py2App(object):
FID = '@executable_path/../Frameworks'
def __init__(self, build_dir, test_launchers=False, dont_strip=False):
self.build_dir = build_dir
self.dont_strip = dont_strip
self.contents_dir = join(self.build_dir, 'Contents')
self.resources_dir = join(self.contents_dir, 'Resources')
self.frameworks_dir = join(self.contents_dir, 'Frameworks')
self.version_info = '.'.join(map(str, sys.version_info[:2]))
self.site_packages = join(self.resources_dir, 'Python', 'site-packages')
self.to_strip = []
self.warnings = []
self.run(test_launchers)
def warn(self, *args):
warn(*args)
def run(self, test_launchers):
ret = 0
if not test_launchers:
if os.path.exists(self.build_dir):
shutil.rmtree(self.build_dir)
os.makedirs(self.build_dir)
self.create_skeleton()
self.create_plist()
self.add_python_framework()
self.add_site_packages()
self.add_stdlib()
self.add_qt_frameworks()
self.add_calibre_plugins()
self.add_podofo()
self.add_poppler()
self.add_imaging_libs()
self.add_fontconfig()
self.add_misc_libraries()
self.add_resources()
self.compile_py_modules()
self.copy_site()
self.create_exe()
if not test_launchers and not self.dont_strip:
self.strip_files()
if not test_launchers:
self.create_console_app()
self.create_gui_apps()
ret = self.makedmg(self.build_dir, APPNAME+'-'+VERSION)
return ret
@flush
def add_resources(self):
shutil.copytree('resources', os.path.join(self.resources_dir,
'resources'))
@flush
def strip_files(self):
info('\nStripping files...')
strip_files(self.to_strip)
@flush
def create_exe(self):
info('\nCreating launchers')
programs = {}
progs = []
for x in ('console', 'gui'):
progs += list(zip(basenames[x], main_modules[x], main_functions[x], repeat(x)))
for program, module, func, ptype in progs:
programs[program] = (module, func, ptype)
programs = compile_launchers(self.contents_dir, programs,
self.version_info)
for out in programs:
self.fix_dependencies_in_lib(out)
@flush
def set_id(self, path_to_lib, new_id):
old_mode = flipwritable(path_to_lib)
subprocess.check_call(['install_name_tool', '-id', new_id, path_to_lib])
if old_mode is not None:
flipwritable(path_to_lib, old_mode)
@flush
def get_dependencies(self, path_to_lib):
install_name = subprocess.check_output(['otool', '-D', path_to_lib]).splitlines()[-1].strip()
raw = subprocess.check_output(['otool', '-L', path_to_lib])
for line in raw.splitlines():
if 'compatibility' not in line or line.strip().endswith(':'):
continue
idx = line.find('(')
path = line[:idx].strip()
yield path, path == install_name
@flush
def get_local_dependencies(self, path_to_lib):
for x, is_id in self.get_dependencies(path_to_lib):
if x.startswith('@rpath/Qt'):
yield x, x[len('@rpath/'):], is_id
else:
for y in (SW+'/lib/', SW+'/python/Python.framework/', SW+'/private/ssl/lib/'):
if x.startswith(y):
if y == SW+'/python/Python.framework/':
y = SW+'/python/'
yield x, x[len(y):], is_id
break
@flush
def change_dep(self, old_dep, new_dep, is_id, path_to_lib):
cmd = ['-id', new_dep] if is_id else ['-change', old_dep, new_dep]
subprocess.check_call(['install_name_tool'] + cmd + [path_to_lib])
@flush
def fix_dependencies_in_lib(self, path_to_lib):
self.to_strip.append(path_to_lib)
old_mode = flipwritable(path_to_lib)
for dep, bname, is_id in self.get_local_dependencies(path_to_lib):
ndep = self.FID+'/'+bname
self.change_dep(dep, ndep, is_id, path_to_lib)
ldeps = list(self.get_local_dependencies(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:
flipwritable(path_to_lib, old_mode)
@flush
def add_python_framework(self):
info('\nAdding Python framework')
src = join(SW + '/python', 'Python.framework')
x = join(self.frameworks_dir, 'Python.framework')
curr = os.path.realpath(join(src, 'Versions', 'Current'))
currd = join(x, 'Versions', basename(curr))
rd = join(currd, 'Resources')
os.makedirs(rd)
shutil.copy2(join(curr, 'Resources', 'Info.plist'), rd)
shutil.copy2(join(curr, 'Python'), currd)
self.set_id(join(currd, 'Python'),
self.FID+'/Python.framework/Versions/%s/Python'%basename(curr))
# The following is needed for codesign in OS X >= 10.9.5
with current_dir(x):
os.symlink(basename(curr), 'Versions/Current')
for y in ('Python', 'Resources'):
os.symlink('Versions/Current/%s'%y, y)
@flush
def add_qt_frameworks(self):
info('\nAdding Qt Frameworks')
for f in QT_FRAMEWORKS:
self.add_qt_framework(f)
pdir = join(SW, 'qt', 'plugins')
ddir = join(self.contents_dir, 'MacOS', 'qt-plugins')
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)
x = os.path.relpath(l, ddir)
self.set_id(l, '@executable_path/'+x)
def add_qt_framework(self, f):
libname = f
f = f+'.framework'
src = join(SW, 'qt', 'lib', f)
ignore = shutil.ignore_patterns('Headers', '*.h', 'Headers/*')
dest = join(self.frameworks_dir, f)
shutil.copytree(src, dest, symlinks=True,
ignore=ignore)
lib = os.path.realpath(join(dest, libname))
rpath = os.path.relpath(lib, self.frameworks_dir)
self.set_id(lib, self.FID+'/'+rpath)
self.fix_dependencies_in_lib(lib)
# The following is needed for codesign in OS X >= 10.9.5
# The presence of the .prl file in the root of the framework causes
# codesign to fail.
with current_dir(dest):
for x in os.listdir('.'):
if x != 'Versions' and not os.path.islink(x):
os.remove(x)
@flush
def create_skeleton(self):
c = join(self.build_dir, 'Contents')
for x in ('Frameworks', 'MacOS', 'Resources'):
os.makedirs(join(c, x))
for x in glob.glob(join('icons', 'icns', '*.iconset')):
subprocess.check_call([
'iconutil', '-c', 'icns', x, '-o', join(
self.resources_dir, basename(x).partition('.')[0] + '.icns')])
@flush
def add_calibre_plugins(self):
dest = join(self.frameworks_dir, 'plugins')
os.mkdir(dest)
for f in glob.glob('src/calibre/plugins/*.so'):
shutil.copy2(f, dest)
self.fix_dependencies_in_lib(join(dest, basename(f)))
@flush
def create_plist(self):
from calibre.ebooks import BOOK_EXTENSIONS
env = dict(**ENV)
env['CALIBRE_LAUNCHED_FROM_BUNDLE']='1'
docs = [{'CFBundleTypeName':'E-book',
'CFBundleTypeExtensions':list(BOOK_EXTENSIONS),
'CFBundleTypeIconFile':'book.icns',
'CFBundleTypeRole':'Viewer',
}]
pl = dict(
CFBundleDevelopmentRegion='English',
CFBundleDisplayName=APPNAME,
CFBundleName=APPNAME,
CFBundleIdentifier='net.kovidgoyal.calibre',
CFBundleVersion=VERSION,
CFBundleShortVersionString=VERSION,
CFBundlePackageType='APPL',
CFBundleSignature='????',
CFBundleExecutable='calibre',
CFBundleDocumentTypes=docs,
LSMinimumSystemVersion='10.7.2',
LSRequiresNativeExecution=True,
NSAppleScriptEnabled=False,
NSHumanReadableCopyright=time.strftime('Copyright %Y, Kovid Goyal'),
CFBundleGetInfoString=('calibre, an E-book management '
'application. Visit https://calibre-ebook.com for details.'),
CFBundleIconFile='calibre.icns',
NSHighResolutionCapable=True,
LSApplicationCategoryType='public.app-category.productivity',
LSEnvironment=env
)
plistlib.writePlist(pl, join(self.contents_dir, 'Info.plist'))
@flush
def install_dylib(self, path, set_id=True):
shutil.copy2(path, self.frameworks_dir)
if set_id:
self.set_id(join(self.frameworks_dir, basename(path)),
self.FID+'/'+basename(path))
self.fix_dependencies_in_lib(join(self.frameworks_dir, basename(path)))
@flush
def add_podofo(self):
info('\nAdding PoDoFo')
pdf = join(SW, 'lib', 'libpodofo.0.9.3.dylib')
self.install_dylib(pdf)
@flush
def add_poppler(self):
info('\nAdding poppler')
for x in ('libpoppler.56.dylib',):
self.install_dylib(os.path.join(SW, 'lib', x))
for x in ('pdftohtml', 'pdftoppm', 'pdfinfo'):
self.install_dylib(os.path.join(SW, 'bin', x), False)
@flush
def add_imaging_libs(self):
info('\nAdding libjpeg, libpng, libwebp, optipng and mozjpeg')
for x in ('jpeg.8', 'png16.16', 'webp.5'):
self.install_dylib(os.path.join(SW, 'lib', 'lib%s.dylib' % x))
self.install_dylib(os.path.join(SW, 'bin', 'optipng'), False)
for x in ('jpegtran', 'cjpeg'):
self.install_dylib(os.path.join(SW, 'private', 'mozjpeg', 'bin', x), False)
@flush
def add_fontconfig(self):
info('\nAdding fontconfig')
for x in ('fontconfig.1', 'freetype.6', 'expat.1',
'plist.3', 'usbmuxd.4', 'imobiledevice.5'):
src = os.path.join(SW, 'lib', 'lib'+x+'.dylib')
self.install_dylib(src)
dst = os.path.join(self.resources_dir, 'fonts')
if os.path.exists(dst):
shutil.rmtree(dst)
src = os.path.join(SW, 'etc', 'fonts')
shutil.copytree(src, dst, symlinks=False)
fc = os.path.join(dst, 'fonts.conf')
raw = open(fc, 'rb').read()
raw = raw.replace('<dir>/usr/share/fonts</dir>', '''\
<dir>/Library/Fonts</dir>
<dir>/System/Library/Fonts</dir>
<dir>/usr/X11R6/lib/X11/fonts</dir>
<dir>/usr/share/fonts</dir>
<dir>/var/root/Library/Fonts</dir>
<dir>/usr/share/fonts</dir>
''')
open(fc, 'wb').write(raw)
@flush
def add_misc_libraries(self):
# Reminder to self to add iconv.dylib in the new freeze code
for x in (
'usb-1.0.0', 'mtp.9', 'ltdl.7', 'chm.0', 'sqlite3.0',
'icudata.53', 'icui18n.53', 'icuio.53', 'icuuc.53',
'crypto.1.0.0', 'ssl.1.0.0', # 'iconv.2'
):
info('\nAdding', x)
x = 'lib%s.dylib'%x
src = join(SW, 'private', 'ssl', 'lib', x) if ('ssl' in x or 'crypto' in x) else join(SW, 'lib', x)
shutil.copy2(src, self.frameworks_dir)
dest = join(self.frameworks_dir, x)
self.set_id(dest, self.FID+'/'+x)
self.fix_dependencies_in_lib(dest)
@flush
def add_site_packages(self):
info('\nAdding site-packages')
os.makedirs(self.site_packages)
paths = reversed(map(abspath, [x for x in sys.path if x.startswith('/')]))
upaths = []
for x in paths:
if x not in upaths and (x.endswith('.egg') or
x.endswith('/site-packages')):
upaths.append(x)
upaths.append(os.path.expanduser('~/build/calibre/src'))
for x in upaths:
info('\t', x)
tdir = None
try:
if not os.path.isdir(x):
try:
zf = zipfile.ZipFile(x)
except:
self.warn(x, 'is neither a directory nor a zipfile')
continue
tdir = tempfile.mkdtemp()
zf.extractall(tdir)
x = tdir
self.add_modules_from_dir(x)
self.add_packages_from_dir(x)
finally:
if tdir is not None:
shutil.rmtree(tdir)
shutil.rmtree(os.path.join(self.site_packages, 'calibre', 'plugins'))
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
def add_modules_from_dir(self, src):
for x in glob.glob(join(src, '*.py'))+glob.glob(join(src, '*.so')):
shutil.copy2(x, self.site_packages)
if x.endswith('.so'):
self.fix_dependencies_in_lib(x)
@flush
def add_packages_from_dir(self, src):
for x in os.listdir(src):
x = join(src, x)
if os.path.isdir(x) and os.path.exists(join(x, '__init__.py')):
if self.filter_package(basename(x)):
continue
self.add_package_dir(x)
@flush
def add_package_dir(self, x, dest=None):
def ignore(root, files):
ans = []
for y in files:
ext = os.path.splitext(y)[1]
if ext not in ('', '.py', '.so') or \
(not ext and not os.path.isdir(join(root, y))):
ans.append(y)
return ans
if dest is None:
dest = self.site_packages
dest = join(dest, basename(x))
shutil.copytree(x, dest, symlinks=True, ignore=ignore)
self.postprocess_package(x, dest)
for x in os.walk(dest):
for f in x[-1]:
if f.endswith('.so'):
f = join(x[0], f)
self.fix_dependencies_in_lib(f)
@flush
def filter_package(self, name):
return name in ('Cython', 'modulegraph', 'macholib', 'py2app',
'bdist_mpkg', 'altgraph')
@flush
def postprocess_package(self, src_path, dest_path):
pass
@flush
def add_stdlib(self):
info('\nAdding python stdlib')
src = SW + '/python/Python.framework/Versions/Current/lib/python'
src += self.version_info
dest = join(self.resources_dir, 'Python', 'lib', 'python')
dest += self.version_info
os.makedirs(dest)
for x in os.listdir(src):
if x in ('site-packages', 'config', 'test', 'lib2to3', 'lib-tk',
'lib-old', 'idlelib', 'plat-mac', 'plat-darwin', 'site.py'):
continue
x = join(src, x)
if os.path.isdir(x):
self.add_package_dir(x, dest)
elif os.path.splitext(x)[1] in ('.so', '.py'):
shutil.copy2(x, dest)
dest2 = join(dest, basename(x))
if dest2.endswith('.so'):
self.fix_dependencies_in_lib(dest2)
self.remove_bytecode(join(self.resources_dir, 'Python', 'lib'))
confdir = join(self.resources_dir, 'Python',
'lib/python%s/config'%self.version_info)
os.makedirs(confdir)
shutil.copy2(join(src, 'config/Makefile'), confdir)
incdir = join(self.resources_dir, 'Python',
'include/python'+self.version_info)
os.makedirs(incdir)
shutil.copy2(join(src.replace('/lib/', '/include/'), 'pyconfig.h'),
incdir)
@flush
def remove_bytecode(self, dest):
for x in os.walk(dest):
root = x[0]
for f in x[-1]:
if os.path.splitext(f) in ('.pyc', '.pyo'):
os.remove(join(root, f))
@flush
def compile_py_modules(self):
info('\nCompiling Python modules')
base = join(self.resources_dir, 'Python')
for x in os.walk(base):
root = x[0]
for f in x[-1]:
if f.endswith('.py'):
y = join(root, f)
rel = os.path.relpath(y, base)
try:
py_compile.compile(y, dfile=rel, doraise=True)
os.remove(y)
except:
self.warn('WARNING: Failed to byte-compile', y)
def create_app_clone(self, name, specialise_plist, remove_doc_types=True):
info('\nCreating ' + name)
cc_dir = os.path.join(self.contents_dir, name, 'Contents')
exe_dir = join(cc_dir, 'MacOS')
os.makedirs(exe_dir)
for x in os.listdir(self.contents_dir):
if x.endswith('.app'):
continue
if x == 'Info.plist':
plist = plistlib.readPlist(join(self.contents_dir, x))
specialise_plist(plist)
if remove_doc_types:
plist.pop('CFBundleDocumentTypes')
exe = plist['CFBundleExecutable']
# We cannot symlink the bundle executable as if we do,
# codesigning fails
nexe = plist['CFBundleExecutable'] = exe + '-placeholder-for-codesigning'
shutil.copy2(join(self.contents_dir, 'MacOS', exe), join(exe_dir, nexe))
exe = join(exe_dir, plist['CFBundleExecutable'])
plistlib.writePlist(plist, join(cc_dir, x))
elif x == 'MacOS':
for item in os.listdir(join(self.contents_dir, 'MacOS')):
os.symlink('../../../MacOS/'+item, join(exe_dir, item))
else:
os.symlink(join('../..', x), join(cc_dir, x))
@flush
def create_console_app(self):
def specialise_plist(plist):
plist['LSBackgroundOnly'] = '1'
plist['CFBundleIdentifier'] = 'com.calibre-ebook.console'
plist['CFBundleExecutable'] = 'calibre-parallel'
self.create_app_clone('console.app', specialise_plist)
# Comes from the terminal-notifier project:
# https://github.com/alloy/terminal-notifier
dest = join(self.contents_dir, 'calibre-notifier.app')
shutil.copytree(join(SW, 'build/notifier.app'), dest)
shutil.copy2(join(self.resources_dir, 'calibre.icns'), join(dest, 'Contents', 'Resources', 'library.icns'))
@flush
def create_gui_apps(self):
from calibre.customize.ui import all_input_formats
def specialise_plist(launcher, remove_types, plist):
plist['CFBundleDisplayName'] = plist['CFBundleName'] = {
'ebook-viewer':'E-book Viewer', 'ebook-edit':'Edit Book', 'calibre-debug': 'calibre (debug)',
}[launcher]
plist['CFBundleExecutable'] = launcher
if launcher != 'calibre-debug':
plist['CFBundleIconFile'] = launcher + '.icns'
plist['CFBundleIdentifier'] = 'com.calibre-ebook.' + launcher
if not remove_types:
input_formats = sorted(all_input_formats())
e = plist['CFBundleDocumentTypes'][0]
exts = 'epub azw3'.split() if launcher == 'ebook-edit' else input_formats
e['CFBundleTypeExtensions'] = exts
for launcher in ('ebook-viewer', 'ebook-edit', 'calibre-debug'):
remove_types = launcher == 'calibre-debug'
self.create_app_clone(launcher + '.app', partial(specialise_plist, launcher, remove_types), remove_doc_types=remove_types)
@flush
def copy_site(self):
base = os.path.dirname(__file__)
shutil.copy2(join(base, 'site.py'), join(self.resources_dir, 'Python',
'lib', 'python'+self.version_info))
@flush
def makedmg(self, d, volname,
destdir='dist',
internet_enable=True,
format='UDBZ'):
''' Copy a directory d into a dmg named volname '''
info('\nSigning...')
sys.stdout.flush()
if not os.path.exists(destdir):
os.makedirs(destdir)
dmg = os.path.join(destdir, volname+'.dmg')
if os.path.exists(dmg):
os.unlink(dmg)
tdir = tempfile.mkdtemp()
appdir = os.path.join(tdir, os.path.basename(d))
shutil.copytree(d, appdir, symlinks=True)
with timeit() as times:
sign_app(appdir)
info('Signing completed in %d minutes %d seconds' % tuple(times))
os.symlink('/Applications', os.path.join(tdir, 'Applications'))
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]
if 190 < size_in_mb < 250:
# We need -size 255m because of a bug in hdiutil. When the size of
# srcfolder is close to 200MB hdiutil fails with
# diskimages-helper: resize request is above maximum size allowed.
cmd += ['-size', '255m']
info('\nCreating dmg...')
with timeit() as times:
subprocess.check_call(cmd + [dmg])
if internet_enable:
subprocess.check_call(['/usr/bin/hdiutil', 'internet-enable', '-yes', dmg])
info('dmg created in %d minutes and %d seconds' % tuple(times))
shutil.rmtree(tdir)
size = os.stat(dmg).st_size/(1024*1024.)
info('\nInstaller size: %.2fMB\n'%size)
return dmg
def test_exe():
build_dir = abspath(join('build', APPNAME+'.app'))
py2app = Py2App(build_dir)
py2app.create_exe()
return 0
def main(test=False, dont_strip=False):
if 'test_exe' in sys.argv:
return test_exe()
build_dir = abspath(join(os.path.dirname(SRC), 'build', APPNAME+'.app'))
Py2App(build_dir, test_launchers=test, dont_strip=dont_strip)
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -1,85 +0,0 @@
#!/usr/bin/env python2
# vim:fileencoding=utf-8
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
import subprocess, os, sys, plistlib
from contextlib import contextmanager
from glob import glob
@contextmanager
def current_dir(path):
cwd = os.getcwd()
os.chdir(path)
yield path
os.chdir(cwd)
def codesign(items):
if isinstance(items, basestring):
items = [items]
# If you get errors while codesigning that look like "A timestamp was
# expected but not found" it means that codesign failed to contact Apple's time
# servers, probably due to network congestion, so add --timestamp=none to
# this command line. That means the signature will fail once your code
# signing key expires and key revocation wont work, but...
subprocess.check_call(['codesign', '-s', 'Kovid Goyal'] + list(items))
def files_in(folder):
for record in os.walk(folder):
for f in record[-1]:
yield os.path.join(record[0], f)
def expand_dirs(items):
items = set(items)
dirs = set(x for x in items if os.path.isdir(x))
items.difference_update(dirs)
for x in dirs:
items.update(set(files_in(x)))
return items
def get_executable(info_path):
return plistlib.readPlist(info_path)['CFBundleExecutable']
def sign_app(appdir):
appdir = os.path.abspath(appdir)
key = open(os.path.expanduser('~/key')).read().strip()
subprocess.check_call(['security', 'unlock-keychain', '-p', key])
with current_dir(os.path.join(appdir, 'Contents')):
executables = {get_executable('Info.plist')}
# Sign the sub application bundles
sub_apps = glob('*.app')
for sa in sub_apps:
exe = get_executable(sa + '/Contents/Info.plist')
if exe in executables:
raise ValueError('Multiple app bundles share the same executable: %s' % exe)
executables.add(exe)
codesign(sub_apps)
# Sign everything in MacOS except the main executables of the various
# app bundles which will be signed automatically by codesign when
# signing the app bundles
with current_dir('MacOS'):
items = set(os.listdir('.')) - executables
codesign(expand_dirs(items))
# Sign everything in Frameworks
with current_dir('Frameworks'):
fw = set(glob('*.framework'))
codesign(fw)
items = set(os.listdir('.')) - fw
codesign(expand_dirs(items))
# Now sign the main app
codesign(appdir)
# Verify the signature
subprocess.check_call(['codesign', '--deep', '--verify', '-v', appdir])
subprocess.check_call('spctl --verbose=4 --assess --type execute'.split() + [appdir])
return 0
if __name__ == '__main__':
sign_app(sys.argv[-1])

View File

@ -1,154 +0,0 @@
"""
Append module search paths for third-party packages to sys.path.
This is stripped down and customized for use in py2app applications
"""
import sys
import os
def makepath(*paths):
dir = os.path.abspath(os.path.join(*paths))
return dir, os.path.normcase(dir)
def abs__file__():
"""Set all module __file__ attribute to an absolute path"""
for m in sys.modules.values():
if hasattr(m, '__loader__'):
continue # don't mess with a PEP 302-supplied __file__
try:
m.__file__ = os.path.abspath(m.__file__)
except AttributeError:
continue
# This ensures that the initial path provided by the interpreter contains
# only absolute pathnames, even if we're running from the build directory.
L = []
_dirs_in_sys_path = {}
dir = dircase = None # sys.path may be empty at this point
for dir in sys.path:
# Filter out duplicate paths (on case-insensitive file systems also
# if they only differ in case); turn relative paths into absolute
# paths.
dir, dircase = makepath(dir)
if dircase not in _dirs_in_sys_path:
L.append(dir)
_dirs_in_sys_path[dircase] = 1
sys.path[:] = L
del dir, dircase, L
_dirs_in_sys_path = None
def _init_pathinfo():
global _dirs_in_sys_path
_dirs_in_sys_path = d = {}
for dir in sys.path:
if dir and not os.path.isdir(dir):
continue
dir, dircase = makepath(dir)
d[dircase] = 1
def addsitedir(sitedir):
global _dirs_in_sys_path
if _dirs_in_sys_path is None:
_init_pathinfo()
reset = 1
else:
reset = 0
sitedir, sitedircase = makepath(sitedir)
if sitedircase not in _dirs_in_sys_path:
sys.path.append(sitedir) # Add path component
try:
names = os.listdir(sitedir)
except os.error:
return
names.sort()
for name in names:
if name[-4:] == os.extsep + "pth":
addpackage(sitedir, name)
if reset:
_dirs_in_sys_path = None
def addpackage(sitedir, name):
global _dirs_in_sys_path
if _dirs_in_sys_path is None:
_init_pathinfo()
reset = 1
else:
reset = 0
fullname = os.path.join(sitedir, name)
try:
f = open(fullname)
except IOError:
return
while True:
dir = f.readline()
if not dir:
break
if dir[0] == '#':
continue
if dir.startswith("import"):
exec dir
continue
if dir[-1] == '\n':
dir = dir[:-1]
dir, dircase = makepath(sitedir, dir)
if dircase not in _dirs_in_sys_path and os.path.exists(dir):
sys.path.append(dir)
_dirs_in_sys_path[dircase] = 1
if reset:
_dirs_in_sys_path = None
# Remove sys.setdefaultencoding() so that users cannot change the
# encoding after initialization. The test for presence is needed when
# this module is run as a script, because this code is executed twice.
#
if hasattr(sys, "setdefaultencoding"):
sys.setdefaultencoding('utf-8')
del sys.setdefaultencoding
def run_entry_point():
bname, mod, func = sys.calibre_basename, sys.calibre_module, sys.calibre_function
sys.argv[0] = bname
pmod = __import__(mod, fromlist=[1], level=0)
return getattr(pmod, func)()
def add_calibre_vars(base):
sys.frameworks_dir = os.path.join(os.path.dirname(base), 'Frameworks')
sys.resources_location = os.path.abspath(os.path.join(base, 'resources'))
sys.extensions_location = os.path.join(sys.frameworks_dir, 'plugins')
sys.binaries_path = os.path.join(os.path.dirname(base), 'MacOS')
sys.console_binaries_path = os.path.join(os.path.dirname(base),
'console.app', 'Contents', 'MacOS')
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
if dv and os.path.exists(dv):
sys.path.insert(0, os.path.abspath(dv))
def nuke_stdout():
# Redirect stdout, stdin and stderr to /dev/null
from calibre.constants import plugins
plugins['speedup'][0].detach(os.devnull)
def main():
global __file__
# Needed on OS X <= 10.8, which passes -psn_... as a command line arg when
# starting via launch services
for arg in tuple(sys.argv[1:]):
if arg.startswith('-psn_'):
sys.argv.remove(arg)
base = sys.resourcepath
sys.frozen = 'macosx_app'
sys.new_app_bundle = True
abs__file__()
add_calibre_vars(base)
addsitedir(sys.site_packages)
if sys.calibre_is_gui_app and not (
sys.stdout.isatty() or sys.stderr.isatty() or sys.stdin.isatty()):
nuke_stdout()
return run_entry_point()

View File

@ -1,225 +0,0 @@
#include "util.h"
#include <stdlib.h>
#include <strings.h>
#include <CoreFoundation/CoreFoundation.h>
#include <mach-o/dyld.h>
#include <Python.h>
#define EXPORT __attribute__((visibility("default")))
static const char *ERR_OOM = "Out of memory";
static int
report_error(const char *msg) {
fprintf(stderr, "%s\n", msg);
fflush(stderr);
return -1;
}
static int
report_code(const char *preamble, const char* msg, int code) {
fprintf(stderr, "%s: %s\n", preamble, msg);
fflush(stderr);
return code;
}
#define EXE "@executable_path/.."
static void
set_env_vars(const char **ENV_VARS, const char **ENV_VAR_VALS, const char* exe_path) {
int i = 0;
char buf[3*PATH_MAX];
const char *env_var, *val;
while(1) {
env_var = ENV_VARS[i];
if (env_var == NULL) break;
val = ENV_VAR_VALS[i++];
if (strstr(val, EXE) == val && strlen(val) >= strlen(EXE)+1) {
strncpy(buf, exe_path, 3*PATH_MAX-150);
strncpy(buf+strlen(exe_path), val+strlen(EXE), 150);
setenv(env_var, buf, 1);
} else
setenv(env_var, val, 1);
}
return;
}
void initialize_interpreter(const char **ENV_VARS, const char **ENV_VAR_VALS,
char *PROGRAM, const char *MODULE, const char *FUNCTION, const char *PYVER, int IS_GUI,
const char* exe_path, const char *rpath, int argc, const char **argv) {
PyObject *pargv, *v;
int i;
Py_OptimizeFlag = 2;
Py_NoSiteFlag = 1;
Py_DontWriteBytecodeFlag = 1;
Py_IgnoreEnvironmentFlag = 1;
Py_NoUserSiteDirectory = 1;
Py_HashRandomizationFlag = 1;
//Py_VerboseFlag = 1;
//Py_DebugFlag = 1;
Py_SetProgramName(PROGRAM);
char pyhome[1000];
snprintf(pyhome, 1000, "%s/Python", rpath);
Py_SetPythonHome(pyhome);
set_env_vars(ENV_VARS, ENV_VAR_VALS, exe_path);
//printf("Path before Py_Initialize(): %s\r\n\n", Py_GetPath());
Py_Initialize();
char *dummy_argv[1] = {""};
PySys_SetArgv(1, dummy_argv);
//printf("Path after Py_Initialize(): %s\r\n\n", Py_GetPath());
char path[3000];
snprintf(path, 3000, "%s/lib/python%s:%s/lib/python%s/lib-dynload:%s/site-packages", pyhome, PYVER, pyhome, PYVER, pyhome);
PySys_SetPath(path);
//printf("Path set by me: %s\r\n\n", path);
PySys_SetObject("calibre_basename", PyBytes_FromString(PROGRAM));
PySys_SetObject("calibre_module", PyBytes_FromString(MODULE));
PySys_SetObject("calibre_function", PyBytes_FromString(FUNCTION));
PySys_SetObject("calibre_is_gui_app", ((IS_GUI) ? Py_True : Py_False));
PySys_SetObject("resourcepath", PyBytes_FromString(rpath));
snprintf(path, 3000, "%s/site-packages", pyhome);
PySys_SetObject("site_packages", PyBytes_FromString(pyhome));
pargv = PyList_New(argc);
if (pargv == NULL) exit(report_error(ERR_OOM));
for (i = 0; i < argc; i++) {
v = PyBytes_FromString(argv[i]);
if (v == NULL) exit(report_error(ERR_OOM));
PyList_SetItem(pargv, i, v);
}
PySys_SetObject("argv", pargv);
}
int pyobject_to_int(PyObject *res) {
int ret; PyObject *tmp;
tmp = PyNumber_Int(res);
if (tmp == NULL) ret = (PyObject_IsTrue(res)) ? 1 : 0;
else ret = (int)PyInt_AS_LONG(tmp);
return ret;
}
int handle_sysexit(PyObject *e) {
PyObject *code;
code = PyObject_GetAttrString(e, "code");
if (!code) return 0;
return pyobject_to_int(code);
}
int calibre_show_python_error(const char *preamble, int code) {
PyObject *exc, *val, *tb, *str;
int ret, issysexit = 0; char *i;
if (!PyErr_Occurred()) return code;
issysexit = PyErr_ExceptionMatches(PyExc_SystemExit);
PyErr_Fetch(&exc, &val, &tb);
if (exc != NULL) {
PyErr_NormalizeException(&exc, &val, &tb);
if (issysexit) {
return (val) ? handle_sysexit(val) : 0;
}
if (val != NULL) {
str = PyObject_Unicode(val);
if (str == NULL) {
PyErr_Clear();
str = PyObject_Str(val);
}
i = PyString_AsString(str);
ret = report_code(preamble, (i==NULL)?ERR_OOM:i, code);
if (tb != NULL) {
PyErr_Restore(exc, val, tb);
PyErr_Print();
}
return ret;
}
}
return report_code(preamble, "", code);
}
EXPORT
int
run(const char **ENV_VARS, const char **ENV_VAR_VALS, char *PROGRAM,
const char *MODULE, const char *FUNCTION, const char *PYVER,
int IS_GUI, int argc, const char **argv, const char **envp) {
char *pathPtr = NULL, *t = NULL;
char buf[3*PATH_MAX];
int ret = 0, i;
PyObject *site, *mainf, *res;
uint32_t buf_size = PATH_MAX+1;
char *ebuf = calloc(buf_size, sizeof(char));
ret = _NSGetExecutablePath(ebuf, &buf_size);
if (ret == -1) {
free(ebuf);
ebuf = calloc(buf_size, sizeof(char));
if (_NSGetExecutablePath(ebuf, &buf_size) != 0)
return report_error("Failed to find real path of executable.");
}
pathPtr = realpath(ebuf, buf);
if (pathPtr == NULL) {
return report_error(strerror(errno));
}
for (i = 0; i < 3; i++) {
t = rindex(pathPtr, '/');
if (t == NULL) return report_error("Failed to determine bundle path.");
*t = '\0';
}
if (strstr(pathPtr, "/calibre.app/Contents/") != NULL) {
// We are one of the duplicate executables created to workaround codesign's limitations
for (i = 0; i < 2; i++) {
t = rindex(pathPtr, '/');
if (t == NULL) return report_error("Failed to resolve bundle path in dummy executable");
*t = '\0';
}
}
char rpath[PATH_MAX+1], exe_path[PATH_MAX+1];
snprintf(exe_path, PATH_MAX+1, "%s/Contents", pathPtr);
snprintf(rpath, PATH_MAX+1, "%s/Resources", exe_path);
initialize_interpreter(ENV_VARS, ENV_VAR_VALS, PROGRAM, MODULE, FUNCTION, PYVER, IS_GUI,
exe_path, rpath, argc, argv);
site = PyImport_ImportModule("site");
if (site == NULL)
ret = calibre_show_python_error("Failed to import site module", -1);
else {
Py_XINCREF(site);
mainf = PyObject_GetAttrString(site, "main");
if (mainf == NULL || !PyCallable_Check(mainf))
ret = calibre_show_python_error("site module has no main function", -1);
else {
Py_XINCREF(mainf);
res = PyObject_CallObject(mainf, NULL);
if (res == NULL)
ret = calibre_show_python_error("Python function terminated unexpectedly", -1);
else {
}
}
}
PyErr_Clear();
Py_Finalize();
//printf("11111 Returning: %d\r\n", ret);
return ret;
}

View File

@ -1,5 +0,0 @@
#pragma once
int run(const char **ENV_VARS, const char **ENV_VAR_VALS, char *PROGRAM,
const char *MODULE, const char *FUNCTION, const char *PYVER, int IS_GUI,
int argc, const char **argv, const char **envp);

View File

@ -1,3 +0,0 @@
#!/bin/sh
easy_install --always-unzip -U appscript

View File

@ -1,7 +0,0 @@
#!/bin/sh
# Change the https URLs to http in setup.py
cd $SW/build/apsw-* && rm -rf build/* && \
python setup.py fetch --version=3.8.6 --sqlite --missing-checksum-ok && python setup.py install

View File

@ -1,5 +0,0 @@
#!/bin/bash
cd $SW/build/chmlib* && \
#cp /usr/share/libtool/config.* . && \
./configure --disable-dependency-tracking --disable-pread --disable-io64 --prefix=$SW && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/expat-* &&\
./configure --prefix=$SW && make && make install

View File

@ -1,6 +0,0 @@
#!/bin/sh
export FREETYPE_CFLAGS="-I$SW/include/freetype2"
export FREETYPE_LIBS="-L$SW/lib -lfreetype -lz -lbz2"
cd $SW/build/fontconfig-2.* && \
./configure --prefix=$SW --disable-static --disable-docs --with-expat=$SW --with-add-fonts=/usr/X11/lib/X11/fonts --disable-dependency-tracking && make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/freetype* && \
./configure --disable-static --prefix=$SW && make && make install

View File

@ -1,9 +0,0 @@
#!/bin/sh
export CFLAGS="$CFLAGS -DU_CHARSET_IS_UTF8=1"
export CPPFLAGS="$CFLAGS"
export CXXFLAGS="$CFLAGS"
cd $SW/build/icu*/source && \
./runConfigureICU MacOSX --disable-samples --prefix=$SW && make && make install && python ~/build/calibre/setup/installer/osx/fix_icu.py

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/libiconv-* && \
./configure --enable-static --disable-dependency-tracking --disable-shared --prefix=$SW && make && make install

View File

@ -1,12 +0,0 @@
#!/bin/sh
export libusbmuxd_CFLAGS=-I$SW/include
export libusbmuxd_LIBS=-lusbmuxd
export libplist_CFLAGS=-I$SW/include
export libplist_LIBS=-lplist
export libplistmm_CFLAGS=-I$SW/include
export libplistmm_LIBS=-lplist++
export openssl_CFLAGS=-I/usr/include
export openssl_LIBS="-lcrypto -lssl"
cd $SW/build/libimobiledevice-* && ./configure --prefix=$SW --disable-dependency-tracking --without-cython --disable-static && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/bash
cd $SW/build/libjpeg-turbo* && \
./configure --disable-dependency-tracking --enable-shared --with-jpeg8 --without-turbojpeg --prefix=$SW --host x86_64-apple-darwin NASM=$SW/bin/nasm && make -j2 && make install

View File

@ -1,5 +0,0 @@
#!/bin/sh
cd $SW/build/libtool*/libltdl && \
./configure --prefix=$SW --disable-dependency-tracking --enable-ltdl-install && \
make && make install

View File

@ -1,11 +0,0 @@
#!/bin/sh
export LIBUSB_CFLAGS="-I$SW/include/libusb-1.0"
export LIBUSB_LIBS="-L$SW/lib -lusb-1.0"
export CFLAGS="$CFLAGS -DHAVE_ICONV"
export LDFLAGS="$LDFLAGS -liconv"
cd $SW/build/libmtp-* && \
./configure --disable-dependency-tracking --disable-static --prefix=$SW --with-libiconv-prefix=$SW && \
make && make install

View File

@ -1,6 +0,0 @@
#!/bin/bash
export CPPFLAGS=$CFLAGS
cd $SW/build/libpng* && \
./configure --prefix=$SW --disable-dependency-tracking && make && make install

View File

@ -1,6 +0,0 @@
#!/bin/sh
cd $SW/build/libusb-* && \
./configure --disable-dependency-tracking --disable-static --prefix=$SW && \
make && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/libwebp-* && ./configure --prefix=$SW --disable-static && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/libxml2-2.* && \
./configure --prefix=$SW/private/libxml2 --disable-shared --enable-static --with-iconv=$SW --with-zlib=$SW --without-python --without-debug --disable-dependency-tracking && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/libxslt-*
./configure --prefix=$SW/private/libxml2 --disable-shared --without-python --without-debug --disable-dependency-tracking --with-libxml-prefix=$SW/private/libxml2 && make && make install

View File

@ -1,21 +0,0 @@
#!/bin/sh
# lxml must be built with statically linked libxml2 and libxslt as python on
# OS X loads the system version of these libraries, which can cause incompatibility
# First run python setup.py install and abort it when it reaches the compiling phase
CC=gcc
BTEMP=build/temp.macosx-10.7-x86_64-2.7
BLIB=build/lib.macosx-10.7-x86_64-2.7
PYH=$SW/python/Python.framework/Versions/Current/Headers
LXML=src/lxml/includes
LIBXML=$SW/private/libxml2
cd $SW/build/lxml-3* && rm -rf build/* && \
echo Builiding extension modules... && \
mkdir -p $BTEMP/src/lxml/ $BLIB/lxml/ && \
$CC $CFLAGS -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I$LIBXML/include/libxml2 -I$LIBXML/include/libxslt -I/usr/include -I$PYH -I$LXML -c src/lxml/lxml.etree.c -o $BTEMP/src/lxml/lxml.etree.o -w -flat_namespace && \
$CC $CFLAGS -bundle -undefined dynamic_lookup $BTEMP/src/lxml/lxml.etree.o $LIBXML/lib/libxml2.a $LIBXML/lib/libxslt.a $LIBXML/lib/libexslt.a $SW/lib/libz.a $SW/lib/libiconv.a -lm -o $BLIB/lxml/etree.so && \
$CC $CFLAGS -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I$LIBXML/include/libxml2 -I$LIBXML/include/libxslt -I/usr/include -I$PYH -I$LXML -c src/lxml/lxml.objectify.c -o $BTEMP/src/lxml/lxml.objectify.o -w -flat_namespace && \
$CC $CFLAGS -bundle -undefined dynamic_lookup $BTEMP/src/lxml/lxml.objectify.o $LIBXML/lib/libxml2.a $LIBXML/lib/libxslt.a $LIBXML/lib/libexslt.a $SW/lib/libz.a $SW/lib/libiconv.a -lm -o $BLIB/lxml/objectify.so && \
python setup.py install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/macfsevents* && \
python setup.py install

View File

@ -1,6 +0,0 @@
#!/bin/bash
export CPPFLAGS=$CFLAGS
cd $SW/build/mozjpeg && \
./configure --prefix=$SW/private/mozjpeg --disable-dependency-tracking --disable-shared --with-jpeg8 --without-turbojpeg && make && make install

View File

@ -1,4 +0,0 @@
#!/bin/bash
cd $SW/build/nasm* && \
./configure --prefix=$SW && make -j2 && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/netifaces-* && python setup.py build && cp build/*/netifaces.so $SW/python/Python.framework/Versions/Current/lib/python*/site-packages/

View File

@ -1,7 +0,0 @@
#!/bin/sh
SSLDIR=$SW/private/ssl
cd $SW/build/openssl-* && \
rm -rf $SSLDIR && \
./Configure darwin64-x86_64-cc shared enable-ec_nistp_64_gcc_128 no-ssl2 --openssldir=$SSLDIR && make && make install

View File

@ -1,6 +0,0 @@
#!/bin/bash
export CPPFLAGS=$CFLAGS
cd $SW/build/optipng* && \
./configure -prefix=$SW -with-system-libs && make && make install

View File

@ -1,11 +0,0 @@
#!/bin/bash
export CFLAGS="$CFLAGS -mmacosx-version-min=10.7"
export LDFLAGS="$LDFLAGS -Wl,-headerpad_max_install_names -mmacosx-version-min=10.7"
cd $SW/build/Pillow* && \
echo Disabling zip_safe && \
python -c "f = open('setup.py', 'r+b'); raw = f.read(); import re; raw = re.sub(r'zip_safe\s*=\s*True', 'zip_safe=False', raw); f.seek(0); f.truncate(0); f.write(raw)" && \
python setup.py install

View File

@ -1,8 +0,0 @@
#!/bin/sh
export libxml2_CFLAGS="-I/usr/include/libxml2"
export libxml2_LIBS="-L/usr/lib -lxml2"
cd $SW/build/libplist-* && \
./configure --without-cython --disable-dependency-tracking --prefix=$SW && \
make && make install

View File

@ -1,29 +0,0 @@
#!/bin/sh
export CMAKE_INCLUDE_PATH=$SW/include
export CMAKE_LIBRARY_PATH=$SW/lib
cd $SW/build/podofo* && \
rm -rf podofo-build && mkdir podofo-build && \
cd podofo-build && \
echo "Running cmake..." && \
# We set c++98 and libstdc++ as PoDoFo does not use C++11 and without that it
# will be compiled with C++11 and linked against libc++, which means the PoDoFo
# calibre extension would also have to be compiled and liked that way.
cmake -G "Unix Makefiles" -Wno-dev \
-DFREETYPE_INCLUDE_DIR=$SW/include/freetype2 \
-DFREETYPE_LIBRARIES=-lfreetype \
-DCMAKE_BUILD_TYPE=RELEASE \
-DPODOFO_BUILD_SHARED:BOOL=TRUE \
-DPODOFO_BUILD_STATIC:BOOL=FALSE \
-DCMAKE_CXX_FLAGS="${CFLAGS} -std=c++98 -stdlib=libstdc++" \
-DCMAKE_INSTALL_PREFIX=$SW \
.. && \
make VERBOSE=0 podofo_shared && \
rm -rf $SW/lib/libpodofo*.dylib $SW/include/podofo && \
mkdir $SW/include/podofo && \
cp src/libpodofo.*.dylib $SW/lib && \
cp -r podofo_config.h ../src/* $SW/include/podofo/ && \
cd $SW/lib/ && install_name_tool -id $SW/lib/libpodofo* $SW/lib/libpodofo.* && ln -s libpodofo*.dylib libpodofo.dylib

View File

@ -1,15 +0,0 @@
#!/bin/bash
export CXXFLAGS="$CFLAGS"
export FONTCONFIG_CFLAGS="-I$SW/include/fontconfig -I$SW/include"
export FONTCONFIG_LIBS="-L$SW/lib -lfontconfig"
export FREETYPE_CFLAGS="-I$SW/include/freetype2 -I$SW/include"
export FREETYPE_LIBS="-L$SW/lib -lfreetype -lz"
export FREETYPE_CONFIG="$SW/bin/freetype-config"
export LIBJPEG_LIBS="-L$SW/lib -ljpeg"
export LIBPNG_LIBS="-L$SW/lib -lpng"
export LIBPNG_CFLAGS="-I$SW/include/libpng12"
cd $SW/build/poppler* && \
./configure --prefix $SW --without-x --enable-shared --disable-dependency-tracking --disable-silent-rules --enable-zlib --enable-splash-output --disable-cairo-output --disable-poppler-glib --disable-poppler-qt4 --disable-poppler-cpp --disable-gtk-test --enable-libjpeg --enable-compile-warnings=no && make V=1 && make install

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd $SW/build/psutil-* && python setup.py build && cp -r build/lib*/* $SW/python/Python.framework/Versions/Current/lib/python*/site-packages/

View File

@ -1,5 +0,0 @@
#!/bin/sh
cd $SW/build/PyQt-gpl-* && \
python configure.py --verbose --confirm-license -c -j10 --no-designer-plugin --no-qml-plugin --no-docstrings && \
make -j2 && make install

View File

@ -1,16 +0,0 @@
#!/bin/sh
# Edit setup.py
# Disable Tk by adding return 0 to the start of detect_tkinter_darwin
OPENSSL=$SW/private/ssl
export CFLAGS="-I$OPENSSL/include $CFLAGS -DHAVE_LOAD_EXTENSION"
export LDFLAGS="-L$OPENSSL/lib $LDFLAGS"
cd $SW/build/Python-* && \
./configure --prefix=$SW --enable-framework=$SW/python --enable-ipv6 --enable-unicode=ucs2 --with-signal-module --with-threads --with-pymalloc --with-system-expat && make -j2 && make install
# Now create a symlink from ~/sw/bin/python to the newly installed python binary so that it becomes the default python
# Install setuptools as described in windows/notes. Create symlink for ~/sw/bin/easy_install
# Use setuptools to install the various python packages

View File

@ -1,11 +0,0 @@
#!/bin/bash
# See windows/notes.rst for instructions on slimming down Qt.
# For versions of Qt < 5.6 you need to apply this patch:
# https://codereview.qt-project.org/#/c/125923/
cd $SW/build/qt-* && \
rm -rf build && mkdir build && cd build && \
../configure -opensource -confirm-license -prefix $SW/qt -release -nomake examples -nomake tests -no-sql-odbc -no-sql-psql -no-qml-debug -I $SW/include -L $SW/lib && \
make -j2 && rm -rf $SW/qt && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/sip-* && \
python configure.py && make && make install

View File

@ -1,5 +0,0 @@
#!/bin/sh
export CFLAGS="$CFLAGS -O2 -DSQLITE_ENABLE_LOCKING_STYLE"
cd $SW/build/sqlite-* &&\
./configure --prefix=$SW --disable-dependency-tracking --disable-static && make && make install

View File

@ -1,12 +0,0 @@
#!/bin/sh
# Edit makefile.unix setting the vars as shown
CXX=g++
CXXFLAGS=-O2 -arch x86_64 -dynamic
DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_SILENT -DSILENT
STRIP=strip
DESTDIR=$SW
WHAT=RARDLL
cd $SW/unrar && make -fmakefile.unic lib && cp libunrar.so $SW/lib/libunrar.dylib

View File

@ -1,12 +0,0 @@
#!/bin/sh
# Apply the patch to prevent detection of WiFi devices from http://www.mobileread.com/forums/showthread.php?t=255234
export libplist_CFLAGS="-I$SW/include"
export libplist_LIBS="-L$SW/lib -lplist"
export CPPFLAGS="$CFLAGS"
export CXXFLAGS="$CFLAGS"
cd $SW/build/libusbmuxd-* && \
./configure --prefix=$SW --disable-dependency-tracking && \
make && make install

View File

@ -1,4 +0,0 @@
#!/bin/sh
cd $SW/build/zlib-* && \
./configure --prefix=$SW && make && \
libtool -static -o libz.a *.o && make install

View File

@ -1,7 +0,0 @@
#!/bin/sh
cd $HOME
rm sw-osx*;
echo "[Paths]\nPrefix = .." > ~/sw/qt/bin/qt.conf && cat ~/sw/qt/bin/qt.conf
echo "[Paths]\nPrefix = ../qt" > ~/sw/bin/qt.conf && cat ~/sw/bin/qt.conf
tar cf sw-osx.tar --exclude sw/build --exclude sw/sources --exclude sw/man --exclude '*.pyc' --exclude '*.pyo' --exclude 'sw/share/doc' --exclude sw/share/gtk-doc --exclude sw/share/man --exclude sw/share/info sw && bzip2 --best sw-osx.tar
rm ~/sw/qt/bin/qt.conf ~/sw/bin/qt.conf

View File

@ -1,40 +0,0 @@
#!/usr/bin/env python2
# vim:fileencoding=utf-8
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
# The ICU build system does not put correct install names in the dylibs it
# generates. This script will fix that.
import os, glob, subprocess, re
SW = os.environ['SW']
cc = subprocess.check_call
icu_libs = {os.path.abspath(os.path.realpath(x)) for x in glob.glob(os.path.join(SW, 'lib', 'libicu*.dylib'))}
def get_install_name(lib):
return subprocess.check_output(['otool', '-D', lib]).decode('utf-8').splitlines()[-1]
def get_dependencies(lib):
return [x.strip().partition(' ')[0] for x in
subprocess.check_output(['otool', '-L', lib]).decode('utf-8').splitlines()[2:]]
for lib in icu_libs:
install_name = os.path.basename(lib)
print ('Fixing install names in', install_name)
m = re.match(r'libicu[a-z0-9]+\.\d+', install_name)
install_name = m.group() + '.dylib' # We only want the major version in the install name
new_install_name = os.path.join(os.path.dirname(lib), install_name)
cc(['install_name_tool', '-id', new_install_name, lib])
for dep in get_dependencies(lib):
name = os.path.basename(dep)
if name.startswith('libicu'):
ndep = os.path.join(SW, 'lib', name)
if ndep != dep:
cc(['install_name_tool', '-change', dep, ndep, lib])

File diff suppressed because it is too large Load Diff

View File

@ -1,382 +0,0 @@
// XUnzip.h Version 1.3
//
// Authors: Mark Adler et al. (see below)
//
// Modified by: Lucian Wischik
// lu@wischik.com
//
// Version 1.0 - Turned C files into just a single CPP file
// - Made them compile cleanly as C++ files
// - Gave them simpler APIs
// - Added the ability to zip/unzip directly in memory without
// any intermediate files
//
// Modified by: Hans Dietrich
// hdietrich@gmail.com
//
///////////////////////////////////////////////////////////////////////////////
//
// Lucian Wischik's comments:
// --------------------------
// THIS FILE is almost entirely based upon code by info-zip.
// It has been modified by Lucian Wischik.
// The original code may be found at http://www.info-zip.org
// The original copyright text follows.
//
///////////////////////////////////////////////////////////////////////////////
//
// Original authors' comments:
// ---------------------------
// This is version 2002-Feb-16 of the Info-ZIP copyright and license. The
// definitive version of this document should be available at
// ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely.
//
// Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
//
// For the purposes of this copyright and license, "Info-ZIP" is defined as
// the following set of individuals:
//
// Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,
// Jean-loup Gailly, Hunter Goatley, Ian Gorman, Chris Herborth, Dirk Haase,
// Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,
// David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,
// Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,
// Kai Uwe Rommel, Steve Salisbury, Dave Smith, Christian Spieler,
// Antoine Verheijen, Paul von Behren, Rich Wales, Mike White
//
// This software is provided "as is", without warranty of any kind, express
// or implied. In no event shall Info-ZIP or its contributors be held liable
// for any direct, indirect, incidental, special or consequential damages
// arising out of the use of or inability to use this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. Redistributions of source code must retain the above copyright notice,
// definition, disclaimer, and this list of conditions.
//
// 2. Redistributions in binary form (compiled executables) must reproduce
// the above copyright notice, definition, disclaimer, and this list of
// conditions in documentation and/or other materials provided with the
// distribution. The sole exception to this condition is redistribution
// of a standard UnZipSFX binary as part of a self-extracting archive;
// that is permitted without inclusion of this license, as long as the
// normal UnZipSFX banner has not been removed from the binary or disabled.
//
// 3. Altered versions--including, but not limited to, ports to new
// operating systems, existing ports with new graphical interfaces, and
// dynamic, shared, or static library versions--must be plainly marked
// as such and must not be misrepresented as being the original source.
// Such altered versions also must not be misrepresented as being
// Info-ZIP releases--including, but not limited to, labeling of the
// altered versions with the names "Info-ZIP" (or any variation thereof,
// including, but not limited to, different capitalizations),
// "Pocket UnZip", "WiZ" or "MacZip" without the explicit permission of
// Info-ZIP. Such altered versions are further prohibited from
// misrepresentative use of the Zip-Bugs or Info-ZIP e-mail addresses or
// of the Info-ZIP URL(s).
//
// 4. Info-ZIP retains the right to use the names "Info-ZIP", "Zip", "UnZip",
// "UnZipSFX", "WiZ", "Pocket UnZip", "Pocket Zip", and "MacZip" for its
// own source and binary releases.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef XUNZIP_H
#define XUNZIP_H
#ifndef XZIP_H
DECLARE_HANDLE(HZIP); // An HZIP identifies a zip file that has been opened
#endif
typedef DWORD ZRESULT;
// return codes from any of the zip functions. Listed later.
#define ZIP_HANDLE 1
#define ZIP_FILENAME 2
#define ZIP_MEMORY 3
typedef struct
{ int index; // index of this file within the zip
char name[MAX_PATH]; // filename within the zip
DWORD attr; // attributes, as in GetFileAttributes.
FILETIME atime,ctime,mtime;// access, create, modify filetimes
long comp_size; // sizes of item, compressed and uncompressed. These
long unc_size; // may be -1 if not yet known (e.g. being streamed in)
} ZIPENTRY;
typedef struct
{ int index; // index of this file within the zip
TCHAR name[MAX_PATH]; // filename within the zip
DWORD attr; // attributes, as in GetFileAttributes.
FILETIME atime,ctime,mtime;// access, create, modify filetimes
long comp_size; // sizes of item, compressed and uncompressed. These
long unc_size; // may be -1 if not yet known (e.g. being streamed in)
} ZIPENTRYW;
///////////////////////////////////////////////////////////////////////////////
//
// OpenZip()
//
// Purpose: Open an existing zip archive file
//
// Parameters: z - archive file name if flags is ZIP_FILENAME; for other
// uses see below
// len - for memory (ZIP_MEMORY) should be the buffer size;
// for other uses, should be 0
// flags - indicates usage, see below; for files, this will be
// ZIP_FILENAME
//
// Returns: HZIP - non-zero if zip archive opened ok, otherwise 0
//
HZIP OpenZip(void *z, unsigned int len, DWORD flags);
// OpenZip - opens a zip file and returns a handle with which you can
// subsequently examine its contents. You can open a zip file from:
// from a pipe: OpenZip(hpipe_read,0, ZIP_HANDLE);
// from a file (by handle): OpenZip(hfile,0, ZIP_HANDLE);
// from a file (by name): OpenZip("c:\\test.zip",0, ZIP_FILENAME);
// from a memory block: OpenZip(bufstart, buflen, ZIP_MEMORY);
// If the file is opened through a pipe, then items may only be
// accessed in increasing order, and an item may only be unzipped once,
// although GetZipItem can be called immediately before and after unzipping
// it. If it's opened i n any other way, then full random access is possible.
// Note: pipe input is not yet implemented.
///////////////////////////////////////////////////////////////////////////////
//
// GetZipItem()
//
// Purpose: Get information about an item in an open zip archive
//
// Parameters: hz - handle of open zip archive
// index - index number (0 based) of item in zip
// ze - pointer to a ZIPENTRY (if ANSI) or ZIPENTRYW struct
// (if Unicode)
//
// Returns: ZRESULT - ZR_OK if success, otherwise some other value
//
#ifdef _UNICODE
#define GetZipItem GetZipItemW
#else
#define GetZipItem GetZipItemA
#endif
ZRESULT GetZipItemA(HZIP hz, int index, ZIPENTRY *ze);
ZRESULT GetZipItemW(HZIP hz, int index, ZIPENTRYW *ze);
// GetZipItem - call this to get information about an item in the zip.
// If index is -1 and the file wasn't opened through a pipe,
// then it returns information about the whole zipfile
// (and in particular ze.index returns the number of index items).
// Note: the item might be a directory (ze.attr & FILE_ATTRIBUTE_DIRECTORY)
// See below for notes on what happens when you unzip such an item.
// Note: if you are opening the zip through a pipe, then random access
// is not possible and GetZipItem(-1) fails and you can't discover the number
// of items except by calling GetZipItem on each one of them in turn,
// starting at 0, until eventually the call fails. Also, in the event that
// you are opening through a pipe and the zip was itself created into a pipe,
// then then comp_size and sometimes unc_size as well may not be known until
// after the item has been unzipped.
///////////////////////////////////////////////////////////////////////////////
//
// FindZipItem()
//
// Purpose: Find item by name and return information about it
//
// Parameters: hz - handle of open zip archive
// name - name of file to look for inside zip archive
// ic - TRUE = case insensitive
// index - pointer to index number returned, or -1
// ze - pointer to a ZIPENTRY (if ANSI) or ZIPENTRYW struct
// (if Unicode)
//
// Returns: ZRESULT - ZR_OK if success, otherwise some other value
//
#ifdef _UNICODE
#define FindZipItem FindZipItemW
#else
#define FindZipItem FindZipItemA
#endif
ZRESULT FindZipItemA(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze);
ZRESULT FindZipItemW(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRYW *ze);
// FindZipItem - finds an item by name. ic means 'insensitive to case'.
// It returns the index of the item, and returns information about it.
// If nothing was found, then index is set to -1 and the function returns
// an error code.
///////////////////////////////////////////////////////////////////////////////
//
// UnzipItem()
//
// Purpose: Find item by index and unzip it
//
// Parameters: hz - handle of open zip archive
// index - index number of file to unzip
// dst - target file name of unzipped file
// len - for memory (ZIP_MEMORY. length of buffer;
// otherwise 0
// flags - indicates usage, see below; for files, this will be
// ZIP_FILENAME
//
// Returns: ZRESULT - ZR_OK if success, otherwise some other value
//
ZRESULT UnzipItem(HZIP hz, int index, void *dst, unsigned int len, DWORD flags);
// UnzipItem - given an index to an item, unzips it. You can unzip to:
// to a pipe: UnzipItem(hz,i, hpipe_write,0,ZIP_HANDLE);
// to a file (by handle): UnzipItem(hz,i, hfile,0,ZIP_HANDLE);
// to a file (by name): UnzipItem(hz,i, ze.name,0,ZIP_FILENAME);
// to a memory block: UnzipItem(hz,i, buf,buflen,ZIP_MEMORY);
// In the final case, if the buffer isn't large enough to hold it all,
// then the return code indicates that more is yet to come. If it was
// large enough, and you want to know precisely how big, GetZipItem.
// Note: zip files are normally stored with relative pathnames. If you
// unzip with ZIP_FILENAME a relative pathname then the item gets created
// relative to the current directory - it first ensures that all necessary
// subdirectories have been created. Also, the item may itself be a directory.
// If you unzip a directory with ZIP_FILENAME, then the directory gets created.
// If you unzip it to a handle or a memory block, then nothing gets created
// and it emits 0 bytes.
///////////////////////////////////////////////////////////////////////////////
//
// CloseZip()
//
// Purpose: Close an open zip archive
//
// Parameters: hz - handle to an open zip archive
//
// Returns: ZRESULT - ZR_OK if success, otherwise some other value
//
ZRESULT CloseZip(HZIP hz);
// CloseZip - the zip handle must be closed with this function.
unsigned int FormatZipMessage(ZRESULT code, char *buf,unsigned int len);
// FormatZipMessage - given an error code, formats it as a string.
// It returns the length of the error message. If buf/len points
// to a real buffer, then it also writes as much as possible into there.
// These are the result codes:
#define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned,
#define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage.
// The following come from general system stuff (e.g. files not openable)
#define ZR_GENMASK 0x0000FF00
#define ZR_NODUPH 0x00000100 // couldn't duplicate the handle
#define ZR_NOFILE 0x00000200 // couldn't create/open the file
#define ZR_NOALLOC 0x00000300 // failed to allocate some resource
#define ZR_WRITE 0x00000400 // a general error writing to the file
#define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip
#define ZR_MORE 0x00000600 // there's still more data to be unzipped
#define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile
#define ZR_READ 0x00000800 // a general error reading the file
// The following come from mistakes on the part of the caller
#define ZR_CALLERMASK 0x00FF0000
#define ZR_ARGS 0x00010000 // general mistake with the arguments
#define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't
#define ZR_MEMSIZE 0x00030000 // the memory size is too small
#define ZR_FAILED 0x00040000 // the thing was already failed when you called this function
#define ZR_ENDED 0x00050000 // the zip creation has already been closed
#define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken
#define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped
#define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip
// The following come from bugs within the zip library itself
#define ZR_BUGMASK 0xFF000000
#define ZR_NOTINITED 0x01000000 // initialisation didn't work
#define ZR_SEEK 0x02000000 // trying to seek in an unseekable file
#define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed
#define ZR_FLATE 0x05000000 // an internal error in the de/inflation code
// e.g.
//
// SetCurrentDirectory("c:\\docs\\stuff");
// HZIP hz = OpenZip("c:\\stuff.zip",0,ZIP_FILENAME);
// ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
// for (int i=0; i<numitems; i++)
// { GetZipItem(hz,i,&ze);
// UnzipItem(hz,i,ze.name,0,ZIP_FILENAME);
// }
// CloseZip(hz);
//
//
// HRSRC hrsrc = FindResource(hInstance,MAKEINTRESOURCE(1),RT_RCDATA);
// HANDLE hglob = LoadResource(hInstance,hrsrc);
// void *zipbuf=LockResource(hglob);
// unsigned int ziplen=SizeofResource(hInstance,hrsrc);
// HZIP hz = OpenZip(zipbuf, ziplen, ZIP_MEMORY);
// - unzip to a membuffer -
// ZIPENTRY ze; int i; FindZipItem(hz,"file.dat",&i,&ze);
// char *ibuf = new char[ze.unc_size];
// UnzipItem(hz,i, ibuf, ze.unc_size,ZIP_MEMORY);
// delete[] buf;
// - unzip to a fixed membuff -
// ZIPENTRY ze; int i; FindZipItem(hz,"file.dat",&i,&ze);
// char ibuf[1024]; ZIPRESULT zr=ZR_MORE; unsigned long totsize=0;
// while (zr==ZR_MORE)
// { zr = UnzipItem(hz,i, ibuf,1024,ZIP_MEMORY);
// unsigned long bufsize=1024; if (zr==ZR_OK) bufsize=ze.unc_size-totsize;
// totsize+=bufsize;
// }
// - unzip to a pipe -
// HANDLE hthread=CreateWavReaderThread(&hread,&hwrite);
// FindZipItem(hz,"sound.wav",&i,&ze);
// UnzipItem(hz,i, hwrite,0,ZIP_HANDLE);
// CloseHandle(hwrite);
// WaitForSingleObject(hthread,INFINITE);
// CloseHandle(hread); CloseHandle(hthread);
// - finished -
// CloseZip(hz);
// // note: no need to free resources obtained through Find/Load/LockResource
//
//
// SetCurrentDirectory("c:\\docs\\pipedzipstuff");
// HANDLE hread,hwrite; CreatePipe(&hread,&hwrite);
// CreateZipWriterThread(hwrite);
// HZIP hz = OpenZip(hread,0,ZIP_HANDLE);
// for (int i=0; ; i++)
// { ZIPENTRY ze; ZRESULT res = GetZipItem(hz,i,&ze);
// if (res!=ZE_OK) break; // no more
// UnzipItem(hz,i, ze.name,0,ZIP_FILENAME);
// }
// CloseZip(hz);
//
// Now we indulge in a little skullduggery so that the code works whether
// the user has included just zip or both zip and unzip.
// Idea: if header files for both zip and unzip are present, then presumably
// the cpp files for zip and unzip are both present, so we will call
// one or the other of them based on a dynamic choice. If the header file
// for only one is present, then we will bind to that particular one.
HZIP OpenZipU(void *z,unsigned int len,DWORD flags);
ZRESULT CloseZipU(HZIP hz);
unsigned int FormatZipMessageU(ZRESULT code, char *buf,unsigned int len);
bool IsZipHandleU(HZIP hz);
#define OpenZip OpenZipU
#ifdef XZIP_H
#undef CloseZip
#define CloseZip(hz) (IsZipHandleU(hz)?CloseZipU(hz):CloseZipZ(hz))
#else
#define CloseZip CloseZipU
#define FormatZipMessage FormatZipMessageU
#endif
#endif //XUNZIP_H

Some files were not shown because too many files have changed in this diff Show More