More work on building calibre on windows

This commit is contained in:
Kovid Goyal 2019-06-19 12:15:30 +05:30
parent e804e48747
commit 947fb029d8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 54 additions and 47 deletions

View File

@ -31,8 +31,6 @@ dlls = [
'Sensors',
'Sql',
'Svg',
'WebKit',
'WebKitWidgets',
'WebEngineCore',
'WebEngine',
'WebEngineWidgets',
@ -49,7 +47,7 @@ if islinux:
elif ismacos:
dlls += ['MacExtras', 'DBus']
elif iswindows:
dlls += ['WinExtras', 'Angle']
dlls += ['WinExtras']
QT_DLLS = frozenset(
'Qt5' + x for x in dlls
@ -68,7 +66,7 @@ QT_PLUGINS = [
# 'audio', 'printsupport', 'bearer', 'position',
]
if not ismacos:
if not ismacos and not iswindows:
QT_PLUGINS.append('platforminputcontexts')
if islinux:
@ -88,8 +86,6 @@ PYQT_MODULES = (
'QtPrintSupport',
'QtSensors',
'QtSvg',
'QtWebKit',
'QtWebKitWidgets',
'QtWidgets',
'QtWebEngine',
'QtWebEngineCore',

View File

@ -1,4 +1,4 @@
# Requires installation of Visual Studio 2017 Community Edition, Git, Ruby, Python 3.7 and Perl
# Requires installation of Visual Studio 2017 Community Edition, WiX Toolset, Git, Ruby, Python 3.7 and Perl
# git.exe must be in PATH. Must have ~100GB available disk space and 8GB RAM
# Install certifi in python 3 with:
# py.exe -m pip install certifi

View File

@ -8,6 +8,7 @@ import errno
import glob
import os
import re
import runpy
import shutil
import stat
import subprocess
@ -15,12 +16,11 @@ import sys
import zipfile
from bypy.constants import (
PREFIX, SRC as CALIBRE_DIR, SW, is64bit, build_dir, python_major_minor_version
CL, LINK, PREFIX, RC, SRC as CALIBRE_DIR, SW, build_dir, is64bit,
python_major_minor_version
)
from bypy.utils import py_compile, run, walk
from .wix import create_installer
iv = globals()['init_env']
calibre_constants = iv['calibre_constants']
QT_PREFIX = os.path.join(PREFIX, 'qt')
@ -30,6 +30,9 @@ APPNAME, VERSION = calibre_constants['appname'], calibre_constants['version']
WINVER = VERSION + '.0'
machine = 'X64' if is64bit else 'X86'
j, d, a, b = os.path.join, os.path.dirname, os.path.abspath, os.path.basename
create_installer = runpy.run_path(
j(d(a(__file__)), 'wix.py'), {'calibre_constants': calibre_constants}
)['create_installer']
DESCRIPTIONS = {
'calibre': 'The main calibre program',
@ -51,7 +54,6 @@ DESCRIPTIONS = {
# https://msdn.microsoft.com/en-us/library/windows/desktop/dn481241(v=vs.85).aspx
SUPPORTED_OS = {
'vista': '{e2011457-1546-43c5-a5fe-008deee3d3f0}',
'w7': '{35138b9a-5d96-4fbd-8e2d-a2440225f93a}',
'w8': '{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}',
'w81': '{1f676c76-80e1-4239-95bb-83d0f6d0da78}',
@ -70,7 +72,6 @@ EXE_MANIFEST = '''\
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{vista}"/>
<supportedOS Id="{w7}"/>
<supportedOS Id="{w8}"/>
<supportedOS Id="{w81}"/>
@ -86,6 +87,10 @@ def printf(*args, **kw):
sys.stdout.flush()
def run_compiler(env, *cmd):
run(*cmd, cwd=env.obj_dir)
class Env(object):
def __init__(self, build_dir):
@ -160,6 +165,8 @@ def freeze(env, ext_dir):
printf('Adding Qt...')
for x in QT_DLLS:
copybin(os.path.join(QT_PREFIX, 'bin', x + '.dll'))
for x in 'libGLESv2 libEGL'.split():
copybin(os.path.join(QT_PREFIX, 'bin', x + '.dll'))
plugdir = j(QT_PREFIX, 'plugins')
tdir = j(env.app_base, 'qt_plugins')
for d in QT_PLUGINS:
@ -253,7 +260,7 @@ def extract_pyd_modules(env, site_packages_dir):
bpy = dest[:-1]
if os.path.exists(bpy):
with open(bpy, 'rb') as f:
raw = f.read().strip()
raw = f.read().strip().decode('utf-8')
if (not raw.startswith('def __bootstrap__') or not raw.endswith('__bootstrap__()')):
raise ValueError('The file %r has non bootstrap code' % bpy)
for ext in ('', 'c', 'o'):
@ -298,7 +305,7 @@ def embed_resources(env, module, desc=None, extra_data=None, product_description
icon_map = {'calibre': 'library', 'ebook-viewer': 'viewer', 'ebook-edit': 'ebook-edit',
'lrfviewer': 'viewer', 'calibre-portable': 'library'}
file_type = 'DLL' if module.endswith('.dll') else 'APP'
template = open(env.rc_template, 'rb').read()
template = open(env.rc_template, 'rb').read().decode('utf-8')
bname = b(module)
internal_name = os.path.splitext(bname)[0]
icon = icon_map.get(internal_name, 'command-prompt')
@ -316,7 +323,7 @@ def embed_resources(env, module, desc=None, extra_data=None, product_description
if product_description is None:
product_description = APPNAME + ' - E-book management'
rc = template.format(
icon=icon,
icon=icon.replace('\\', '/'),
file_type=e(file_type),
file_version=e(WINVER.replace('.', ',')),
file_version_str=e(WINVER),
@ -334,10 +341,10 @@ def embed_resources(env, module, desc=None, extra_data=None, product_description
rc += '\nextra extra "%s"' % extra_data
tdir = env.obj_dir
rcf = j(tdir, bname + '.rc')
with open(rcf, 'wb') as f:
with open(rcf, 'w') as f:
f.write(rc)
res = j(tdir, bname + '.res')
run('rc', '/n', '/fo' + res, rcf)
run(RC, '/n', '/fo' + res, rcf)
return res
@ -356,8 +363,8 @@ def build_portable_installer(env):
cflags.append(r'/I%s\include' % PREFIX)
cflags.append('/DUNCOMPRESSED_SIZE=%d' % usz)
printf('Compiling', obj)
cmd = ['cl.exe'] + cflags + ['/Fo' + obj, src]
run(*cmd)
cmd = [CL] + cflags + ['/Fo' + obj, src]
run_compiler(env, *cmd)
base = d(a(__file__))
src = j(base, 'portable-installer.cpp')
@ -371,8 +378,8 @@ def build_portable_installer(env):
printf('Linking', exe)
manifest = exe + '.manifest'
with open(manifest, 'wb') as f:
f.write(EXE_MANIFEST)
cmd = ['link.exe'] + [
f.write(EXE_MANIFEST.encode('utf-8'))
cmd = [LINK] + [
'/INCREMENTAL:NO', '/MACHINE:' + machine,
'/LIBPATH:' + env.obj_dir, '/SUBSYSTEM:WINDOWS',
'/LIBPATH:' + (PREFIX + r'\lib'),
@ -397,12 +404,12 @@ def build_portable(env):
cflags = '/c /EHsc /MT /W3 /Ox /nologo /D_UNICODE /DUNICODE'.split()
printf('Compiling', obj)
cmd = ['cl.exe'] + cflags + ['/Fo' + obj, '/Tc' + src]
run(*cmd)
cmd = [CL] + cflags + ['/Fo' + obj, '/Tc' + src]
run_compiler(env, *cmd)
exe = j(base, 'calibre-portable.exe')
printf('Linking', exe)
cmd = ['link.exe'] + [
cmd = [LINK] + [
'/INCREMENTAL:NO', '/MACHINE:' + machine,
'/LIBPATH:' + env.obj_dir, '/SUBSYSTEM:WINDOWS',
'/RELEASE',
@ -482,16 +489,16 @@ def build_utils(env):
def build(src, name, subsys='CONSOLE', libs='setupapi.lib'.split()):
printf('Building ' + name)
obj = j(env.obj_dir, (src) + '.obj')
obj = j(env.obj_dir, os.path.basename(src) + '.obj')
cflags = '/c /EHsc /MD /W3 /Ox /nologo /D_UNICODE'.split()
ftype = '/T' + ('c' if src.endswith('.c') else 'p')
cmd = ['cl.exe'] + cflags + ['/Fo' + obj, ftype + src]
run(*cmd)
cmd = [CL] + cflags + ['/Fo' + obj, ftype + src]
run_compiler(env, *cmd)
exe = j(env.dll_dir, name)
mf = exe + '.manifest'
with open(mf, 'wb') as f:
f.write(EXE_MANIFEST)
cmd = ['link.exe'] + [
f.write(EXE_MANIFEST.encode('utf-8'))
cmd = [LINK] + [
'/MACHINE:' + machine,
'/SUBSYSTEM:' + subsys, '/RELEASE', '/MANIFEST:EMBED', '/MANIFESTINPUT:' + mf,
'/OUT:' + exe] + [embed_resources(env, exe), obj] + libs
@ -512,12 +519,12 @@ def build_launchers(env, debug=False):
cflags = '/c /EHsc /W3 /Ox /nologo /D_UNICODE'.split()
cflags += ['/DPYDLL="python%s.dll"' % env.py_ver.replace('.', ''), '/I%s/include' % env.python_base]
for src, obj in zip(sources, objects):
cmd = ['cl.exe'] + cflags + dflags + ['/MD', '/Fo' + obj, '/Tc' + src]
run(*cmd)
cmd = [CL] + cflags + dflags + ['/MD', '/Fo' + obj, '/Tc' + src]
run_compiler(env, *cmd)
dll = j(env.obj_dir, 'calibre-launcher.dll')
ver = '.'.join(VERSION.split('.')[:2])
cmd = ['link.exe', '/DLL', '/VERSION:' + ver, '/LTCG', '/OUT:' + dll,
cmd = [LINK, '/DLL', '/VERSION:' + ver, '/LTCG', '/OUT:' + dll,
'/nologo', '/MACHINE:' + machine] + dlflags + objects + \
[embed_resources(env, dll),
'/LIBPATH:%s/libs' % env.python_base,
@ -542,16 +549,16 @@ def build_launchers(env, debug=False):
'/DFUNCTION="%s"' % func]
dest = j(env.obj_dir, bname + '.obj')
printf('Compiling', bname)
cmd = ['cl.exe'] + cflags + dflags + ['/Tc' + src, '/Fo' + dest]
run(*cmd)
cmd = [CL] + cflags + dflags + ['/Tc' + src, '/Fo' + dest]
run_compiler(env, *cmd)
exe = j(env.base, bname + '.exe')
lib = dll.replace('.dll', '.lib')
u32 = ['user32.lib']
printf('Linking', bname)
mf = dest + '.manifest'
with open(mf, 'wb') as f:
f.write(EXE_MANIFEST)
cmd = ['link.exe'] + [
f.write(EXE_MANIFEST.encode('utf-8'))
cmd = [LINK] + [
'/MACHINE:' + machine, '/NODEFAULTLIB', '/ENTRY:start_here',
'/LIBPATH:' + env.obj_dir, '/SUBSYSTEM:' + subsys,
'/LIBPATH:%s/libs' % env.python_base, '/RELEASE',
@ -689,3 +696,7 @@ def main():
build_portable_installer(env)
if args.sign_installers:
sign_installers(env)
if __name__ == '__main__':
main()

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
@ -8,16 +8,16 @@ from itertools import count
import os
import shutil
from pkgs.constants import is64bit
from pkgs.utils import run
from .. import calibre_constants
from bypy.constants import is64bit
from bypy.utils import run
WIXP = r'C:\Program Files (x86)\WiX Toolset v3.10'
WIXP = r'C:\Program Files (x86)\WiX Toolset v3.11'
if is64bit:
UPGRADE_CODE = '5DD881FF-756B-4097-9D82-8C0F11D521EA'
else:
UPGRADE_CODE = 'BEB2A80D-E902-4DAD-ADF9-8BD2DA42CFE1'
MINVERHUMAN = 'Windows Vista SP2'
MINVERHUMAN = 'Windows 7'
calibre_constants = globals()['calibre_constants']
CANDLE = WIXP + r'\bin\candle.exe'
LIGHT = WIXP + r'\bin\light.exe'
@ -29,7 +29,7 @@ def create_installer(env):
shutil.rmtree(env.installer_dir)
os.makedirs(env.installer_dir)
template = open(j(d(__file__), 'wix-template.xml'), 'rb').read()
template = open(j(d(__file__), 'wix-template.xml'), 'rb').read().decode('utf-8')
components, smap = get_components_from_files(env)
wxs = template.format(
@ -40,7 +40,7 @@ def create_installer(env):
ProgramFilesFolder='ProgramFiles64Folder' if is64bit else 'ProgramFilesFolder',
x64=' 64bit' if is64bit else '',
minverhuman=MINVERHUMAN,
minver='600',
minver='601',
fix_wix='<Custom Action="OverwriteWixSetDefaultPerMachineFolder" After="WixSetDefaultPerMachineFolder" />' if is64bit else '',
compression='high',
app_components=components,
@ -50,15 +50,15 @@ def create_installer(env):
editor_icon=j(env.src_root, 'icons', 'ebook-edit.ico'),
web_icon=j(env.src_root, 'icons', 'web.ico'),
)
template = open(j(d(__file__), 'en-us.xml'), 'rb').read()
template = open(j(d(__file__), 'en-us.xml'), 'rb').read().decode('utf-8')
enus = template.format(app=calibre_constants['appname'])
enusf = j(env.installer_dir, 'en-us.wxl')
wxsf = j(env.installer_dir, calibre_constants['appname'] + '.wxs')
with open(wxsf, 'wb') as f:
f.write(wxs)
f.write(wxs.encode('utf-8'))
with open(enusf, 'wb') as f:
f.write(enus)
f.write(enus.encode('utf-8'))
wixobj = j(env.installer_dir, calibre_constants['appname'] + '.wixobj')
arch = 'x64' if is64bit else 'x86'
cmd = [CANDLE, '-nologo', '-arch', arch, '-ext', 'WiXUtilExtension', '-o', wixobj, wxsf]