def py_compile(basedir): run(PYTHON, '-OO', '-c', 'import compileall; compileall.compile_dir("%s", force=True, quiet=True)' % basedir, library_path=True) for f in walk(basedir): ext = f.rpartition('.')[-1] if ext in ('py', 'pyc'): os.remove(f)
def cc(src, obj): cflags = '/c /EHsc /MT /W4 /Ox /nologo /D_UNICODE /DUNICODE /DPSAPI_VERSION=1'.split() 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)
def embed_resources(env, module, desc=None, extra_data=None, product_description=None): icon_base = j(env.src_root, 'icons') 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() bname = b(module) internal_name = os.path.splitext(bname)[0] icon = icon_map.get(internal_name, 'command-prompt') if internal_name.startswith('calibre-portable-'): icon = 'install' icon = j(icon_base, icon + '.ico') if desc is None: defdesc = 'A dynamic link library' if file_type == 'DLL' else \ 'An executable program' desc = DESCRIPTIONS.get(internal_name, defdesc) license = 'GNU GPL v3.0' def e(val): return val.replace('"', r'\"') if product_description is None: product_description = APPNAME + ' - E-book management' rc = template.format( icon=icon, file_type=e(file_type), file_version=e(WINVER.replace('.', ',')), file_version_str=e(WINVER), file_description=e(desc), internal_name=e(internal_name), original_filename=e(bname), product_version=e(WINVER.replace('.', ',')), product_version_str=e(VERSION), product_name=e(APPNAME), product_description=e(product_description), legal_copyright=e(license), legal_trademarks=e(APPNAME + ' is a registered U.S. trademark number 3,666,525')) if extra_data: rc += '\nextra extra "%s"' % extra_data tdir = env.obj_dir rcf = j(tdir, bname + '.rc') with open(rcf, 'wb') as f: f.write(rc) res = j(tdir, bname + '.res') run('rc', '/n', '/fo' + res, rcf) return res
def embed_manifests(env): printf('Embedding remaining manifests...') for manifest in walk(env.base): dll, ext = os.path.splitext(manifest) if ext != '.manifest': continue res = 2 if os.path.splitext(dll)[1] == '.exe': res = 1 if os.path.exists(dll) and open(manifest, 'rb').read().strip(): run('mt.exe', '-manifest', manifest, '-outputresource:%s;%d' % (dll, res)) os.remove(manifest)
def build_launchers(env, debug=False): if not os.path.exists(env.obj_dir): os.makedirs(env.obj_dir) dflags = (['/Zi'] if debug else []) dlflags = (['/DEBUG'] if debug else ['/INCREMENTAL:NO']) base = d(a(__file__)) sources = [j(base, x) for x in ['util.c', ]] objects = [j(env.obj_dir, b(x) + '.obj') for x in sources] 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) dll = j(env.obj_dir, 'calibre-launcher.dll') ver = '.'.join(VERSION.split('.')[:2]) cmd = ['link.exe', '/DLL', '/VERSION:' + ver, '/LTCG', '/OUT:' + dll, '/nologo', '/MACHINE:' + machine] + dlflags + objects + \ [embed_resources(env, dll), '/LIBPATH:%s/libs' % env.python_base, 'delayimp.lib', 'user32.lib', 'shell32.lib', 'python%s.lib' % env.py_ver.replace('.', ''), '/delayload:python%s.dll' % env.py_ver.replace('.', '')] printf('Linking calibre-launcher.dll') run(*cmd) src = j(base, 'main.c') shutil.copy2(dll, env.dll_dir) basenames, modules, functions = calibre_constants['basenames'], calibre_constants['modules'], calibre_constants['functions'] for typ in ('console', 'gui', ): printf('Processing %s launchers' % typ) subsys = 'WINDOWS' if typ == 'gui' else 'CONSOLE' for mod, bname, func in zip(modules[typ], basenames[typ], functions[typ]): cflags = '/c /EHsc /MT /W3 /O1 /nologo /D_UNICODE /DUNICODE /GS-'.split() if typ == 'gui': cflags += ['/DGUI_APP='] cflags += ['/DMODULE="%s"' % mod, '/DBASENAME="%s"' % bname, '/DFUNCTION="%s"' % func] dest = j(env.obj_dir, bname + '.obj') printf('Compiling', bname) cmd = ['cl.exe'] + cflags + dflags + ['/Tc' + src, '/Fo' + dest] run(*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'] + [ '/MACHINE:' + machine, '/NODEFAULTLIB', '/ENTRY:start_here', '/LIBPATH:' + env.obj_dir, '/SUBSYSTEM:' + subsys, '/LIBPATH:%s/libs' % env.python_base, '/RELEASE', '/MANIFEST:EMBED', '/MANIFESTINPUT:' + mf, 'user32.lib', 'kernel32.lib', '/OUT:' + exe] + u32 + dlflags + [embed_resources(env, exe), dest, lib] run(*cmd)
def build(src, name, subsys='CONSOLE', libs='setupapi.lib'.split()): printf('Building ' + name) obj = j(env.obj_dir, (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) exe = j(env.dll_dir, name) mf = exe + '.manifest' with open(mf, 'wb') as f: f.write(EXE_MANIFEST) cmd = ['link.exe'] + [ '/MACHINE:' + machine, '/SUBSYSTEM:' + subsys, '/RELEASE', '/MANIFEST:EMBED', '/MANIFESTINPUT:' + mf, '/OUT:' + exe] + [embed_resources(env, exe), obj] + libs run(*cmd)
def py_compile(basedir): run(PYTHON, '-OO', '-m', 'compileall', '-d', '', '-f', '-q', basedir, library_path=True) for f in walk(basedir): ext = f.rpartition('.')[-1] if ext in ('py', 'pyc'): os.remove(f)
def build_portable_installer(env): zf = a(j(env.dist, 'calibre-portable-%s.zip.lz' % VERSION)) usz = env.portable_uncompressed_size or os.path.getsize(zf) def cc(src, obj): cflags = '/c /EHsc /MT /W4 /Ox /nologo /D_UNICODE /DUNICODE /DPSAPI_VERSION=1'.split( ) 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) base = d(a(__file__)) src = j(base, 'portable-installer.cpp') obj = j(env.obj_dir, b(src) + '.obj') xsrc = j(base, 'XUnzip.cpp') xobj = j(env.obj_dir, b(xsrc) + '.obj') cc(src, obj) cc(xsrc, xobj) exe = j(env.dist, 'calibre-portable-installer-%s.exe' % VERSION) printf('Linking', exe) manifest = exe + '.manifest' with open(manifest, 'wb') as f: f.write(EXE_MANIFEST) cmd = ['link.exe'] + [ '/INCREMENTAL:NO', '/MACHINE:' + machine, '/LIBPATH:' + env.obj_dir, '/SUBSYSTEM:WINDOWS', '/LIBPATH:' + (PREFIX + r'\lib'), '/RELEASE', '/MANIFEST:EMBED', '/MANIFESTINPUT:' + manifest, '/ENTRY:wWinMainCRTStartup', '/OUT:' + exe, embed_resources(env, exe, desc='Calibre Portable Installer', extra_data=zf, product_description='Calibre Portable Installer'), xobj, obj, 'User32.lib', 'Shell32.lib', 'easylzma_s.lib', 'Ole32.lib', 'Shlwapi.lib', 'Kernel32.lib', 'Psapi.lib' ] run(*cmd) os.remove(zf)
def build_portable(env): base = env.portable_base if os.path.exists(base): shutil.rmtree(base) os.makedirs(base) root = d(a(__file__)) src = j(root, 'portable.c') obj = j(env.obj_dir, b(src) + '.obj') cflags = '/c /EHsc /MT /W3 /Ox /nologo /D_UNICODE /DUNICODE'.split() printf('Compiling', obj) cmd = ['cl.exe'] + cflags + ['/Fo' + obj, '/Tc' + src] run(*cmd) exe = j(base, 'calibre-portable.exe') printf('Linking', exe) cmd = ['link.exe'] + [ '/INCREMENTAL:NO', '/MACHINE:' + machine, '/LIBPATH:' + env.obj_dir, '/SUBSYSTEM:WINDOWS', '/RELEASE', '/ENTRY:wWinMainCRTStartup', '/OUT:' + exe, embed_resources( env, exe, desc='Calibre Portable', product_description='Calibre Portable'), obj, 'User32.lib' ] run(*cmd) printf('Creating portable installer') shutil.copytree(env.base, j(base, 'Calibre')) os.mkdir(j(base, 'Calibre Library')) os.mkdir(j(base, 'Calibre Settings')) name = '%s-portable-%s.zip' % (APPNAME, VERSION) name = j(env.dist, name) with zipfile.ZipFile(name, 'w', zipfile.ZIP_STORED) as zf: add_dir_to_zip(zf, base, 'Calibre Portable') env.portable_uncompressed_size = os.path.getsize(name) subprocess.check_call([PREFIX + r'\bin\elzma.exe', '-9', '--lzip', name])
def build_launchers(env): base = self_dir sources = [j(base, x) for x in ['util.c']] objects = [j(env.obj_dir, os.path.basename(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' % (PREFIX, py_ver)] for src, obj in zip(sources, objects): cmd = ['gcc'] + cflags + ['-fPIC', '-o', obj, src] run(*cmd) dll = j(env.lib_dir, 'libcalibre-launcher.so') cmd = ['gcc', '-O2', '-Wl,--rpath=$ORIGIN/../lib', '-fPIC', '-o', dll, '-shared'] + objects + \ ['-L%s/lib' % PREFIX, '-lpython' + py_ver] run(*cmd) src = j(base, 'main.c') modules, basenames, functions = calibre_constants['modules'].copy(), calibre_constants['basenames'].copy(), calibre_constants['functions'].copy() modules['console'].append('calibre.linux') basenames['console'].append('calibre_postinstall') functions['console'].append('main') c_launcher = '/tmp/calibre-c-launcher' lsrc = os.path.join(base, 'launcher.c') cmd = ['gcc', '-O2', '-o', c_launcher, lsrc, ] run(*cmd) jobs = [] 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 = j(env.bin_dir, bname) cmd = ['gcc'] + xflags + [src, '-o', exe, '-L' + env.lib_dir, '-lcalibre-launcher'] jobs.append(create_job(cmd)) sh = j(env.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, verbose=False): raise SystemExit(1)
def py_compile(basedir): run(PYTHON, '-OO', '-m', 'compileall', '-f', '-q', '-b', basedir, library_path=True) for f in walk(basedir): if f.endswith('.py'): os.remove(f)
def create_installer(env): if os.path.exists(env.installer_dir): shutil.rmtree(env.installer_dir) os.makedirs(env.installer_dir) template = open(j(d(__file__), 'wix-template.xml'), 'rb').read() components, smap = get_components_from_files(env) wxs = template.format( app=calibre_constants['appname'], appfolder='Calibre2' if is64bit else 'Calibre', version=calibre_constants['version'], upgrade_code=UPGRADE_CODE, ProgramFilesFolder='ProgramFiles64Folder' if is64bit else 'ProgramFilesFolder', x64=' 64bit' if is64bit else '', minverhuman=MINVERHUMAN, minver='600', fix_wix= '<Custom Action="OverwriteWixSetDefaultPerMachineFolder" After="WixSetDefaultPerMachineFolder" />' if is64bit else '', compression='high', app_components=components, exe_map=smap, main_icon=j(env.src_root, 'icons', 'library.ico'), viewer_icon=j(env.src_root, 'icons', 'viewer.ico'), 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() 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) with open(enusf, 'wb') as f: f.write(enus) 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 ] run(*cmd) installer = j( env.dist, '%s%s-%s.msi' % (calibre_constants['appname'], ('-64bit' if is64bit else ''), calibre_constants['version'])) license = j(env.src_root, 'LICENSE.rtf') banner = j(env.src_root, 'icons', 'wix-banner.bmp') dialog = j(env.src_root, 'icons', 'wix-dialog.bmp') cmd = [ LIGHT, '-nologo', '-ext', 'WixUIExtension', '-cultures:en-us', '-loc', enusf, wixobj, '-ext', 'WixUtilExtension', '-o', installer, '-dWixUILicenseRtf=' + license, '-dWixUIBannerBmp=' + banner, '-dWixUIDialogBmp=' + dialog ] cmd.extend([ '-sice:ICE60', # No language in dlls warning '-sice:ICE61', # Allow upgrading with same version number '-sice:ICE40', # Re-install mode overriden '-sice:ICE69', # Shortcut components are part of a different feature than the files they point to ]) cmd.append( '-sval') # Disable all checks since they fail when running under ssh run(*cmd)