mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
Work on getting windows running
This commit is contained in:
parent
994befe846
commit
be471a8cbe
@ -28,6 +28,7 @@ dlls = [
|
|||||||
# 'WebSockets',
|
# 'WebSockets',
|
||||||
# 'WebView',
|
# 'WebView',
|
||||||
'Positioning',
|
'Positioning',
|
||||||
|
'PositioningQuick',
|
||||||
'Sensors',
|
'Sensors',
|
||||||
'Sql',
|
'Sql',
|
||||||
'Svg',
|
'Svg',
|
||||||
@ -178,10 +179,11 @@ def build_c_extensions(ext_dir):
|
|||||||
|
|
||||||
|
|
||||||
def run_tests(path_to_calibre_debug, cwd_on_failure):
|
def run_tests(path_to_calibre_debug, cwd_on_failure):
|
||||||
if run(path_to_calibre_debug, '--test-build') != 0:
|
ret = run(path_to_calibre_debug, '--test-build')
|
||||||
|
if ret != 0:
|
||||||
os.chdir(cwd_on_failure)
|
os.chdir(cwd_on_failure)
|
||||||
print(
|
print(
|
||||||
'running calibre build tests failed with:', path_to_calibre_debug, file=sys.stderr)
|
'running calibre build tests failed with return code:', ret, 'and exe:', path_to_calibre_debug, file=sys.stderr)
|
||||||
run_shell()
|
run_shell()
|
||||||
raise SystemExit('running calibre build tests failed')
|
raise SystemExit('running calibre build tests failed')
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ class Env(object):
|
|||||||
self.py_ver = '.'.join(map(str, python_major_minor_version()))
|
self.py_ver = '.'.join(map(str, python_major_minor_version()))
|
||||||
self.lib_dir = j(self.app_base, 'Lib')
|
self.lib_dir = j(self.app_base, 'Lib')
|
||||||
self.pylib = j(self.app_base, 'pylib.zip')
|
self.pylib = j(self.app_base, 'pylib.zip')
|
||||||
self.dll_dir = j(self.app_base, 'DLLs')
|
self.dll_dir = j(self.app_base, 'bin')
|
||||||
self.portable_base = j(d(self.base), 'Calibre Portable')
|
self.portable_base = j(d(self.base), 'Calibre Portable')
|
||||||
self.obj_dir = j(build_dir, 'launcher')
|
self.obj_dir = j(build_dir, 'launcher')
|
||||||
self.installer_dir = j(build_dir, 'wix')
|
self.installer_dir = j(build_dir, 'wix')
|
||||||
@ -165,10 +165,11 @@ def freeze(env, ext_dir):
|
|||||||
printf('Adding Qt...')
|
printf('Adding Qt...')
|
||||||
for x in QT_DLLS:
|
for x in QT_DLLS:
|
||||||
copybin(os.path.join(QT_PREFIX, 'bin', x + '.dll'))
|
copybin(os.path.join(QT_PREFIX, 'bin', x + '.dll'))
|
||||||
|
copybin(os.path.join(QT_PREFIX, 'bin', 'QtWebEngineProcess.exe'))
|
||||||
for x in 'libGLESv2 libEGL'.split():
|
for x in 'libGLESv2 libEGL'.split():
|
||||||
copybin(os.path.join(QT_PREFIX, 'bin', x + '.dll'))
|
copybin(os.path.join(QT_PREFIX, 'bin', x + '.dll'))
|
||||||
plugdir = j(QT_PREFIX, 'plugins')
|
plugdir = j(QT_PREFIX, 'plugins')
|
||||||
tdir = j(env.app_base, 'qt_plugins')
|
tdir = j(env.app_base, 'plugins')
|
||||||
for d in QT_PLUGINS:
|
for d in QT_PLUGINS:
|
||||||
imfd = os.path.join(plugdir, d)
|
imfd = os.path.join(plugdir, d)
|
||||||
tg = os.path.join(tdir, d)
|
tg = os.path.join(tdir, d)
|
||||||
@ -178,6 +179,9 @@ def freeze(env, ext_dir):
|
|||||||
for f in walk(tdir):
|
for f in walk(tdir):
|
||||||
if not f.lower().endswith('.dll'):
|
if not f.lower().endswith('.dll'):
|
||||||
os.remove(f)
|
os.remove(f)
|
||||||
|
for data_file in os.listdir(j(QT_PREFIX, 'resources')):
|
||||||
|
shutil.copy2(j(QT_PREFIX, 'resources', data_file), j(env.app_base, 'resources'))
|
||||||
|
shutil.copytree(j(QT_PREFIX, 'translations'), j(env.app_base, 'translations'))
|
||||||
|
|
||||||
printf('Adding python...')
|
printf('Adding python...')
|
||||||
|
|
||||||
@ -205,6 +209,12 @@ def freeze(env, ext_dir):
|
|||||||
for x in {x for x in os.listdir(pyqt) if x.endswith('.pyd')}:
|
for x in {x for x in os.listdir(pyqt) if x.endswith('.pyd')}:
|
||||||
if x.partition('.')[0] not in PYQT_MODULES and x != 'sip.pyd':
|
if x.partition('.')[0] not in PYQT_MODULES and x != 'sip.pyd':
|
||||||
os.remove(j(pyqt, x))
|
os.remove(j(pyqt, x))
|
||||||
|
with open(j(pyqt, '__init__.py') , 'r+b') as f:
|
||||||
|
raw = f.read()
|
||||||
|
nraw = raw.replace(b'def find_qt():', b'def find_qt():\n return # disabled for calibre')
|
||||||
|
if nraw == raw:
|
||||||
|
raise Exception('Failed to patch PyQt to disable dll directory manipulation')
|
||||||
|
f.seek(0), f.truncate(), f.write(nraw)
|
||||||
|
|
||||||
printf('Adding calibre sources...')
|
printf('Adding calibre sources...')
|
||||||
for x in glob.glob(j(CALIBRE_DIR, 'src', '*')):
|
for x in glob.glob(j(CALIBRE_DIR, 'src', '*')):
|
||||||
@ -636,8 +646,8 @@ def archive_lib_dir(env):
|
|||||||
shutil.rmtree(env.lib_dir)
|
shutil.rmtree(env.lib_dir)
|
||||||
|
|
||||||
|
|
||||||
def copy_crt(env):
|
def copy_crt_and_d3d(env):
|
||||||
printf('Copying CRT...')
|
printf('Copying CRT and D3D...')
|
||||||
plat = ('x64' if is64bit else 'x86')
|
plat = ('x64' if is64bit else 'x86')
|
||||||
for key, val in worker_env.items():
|
for key, val in worker_env.items():
|
||||||
if 'COMNTOOLS' in key.upper():
|
if 'COMNTOOLS' in key.upper():
|
||||||
@ -653,17 +663,27 @@ def copy_crt(env):
|
|||||||
'ucrt', 'DLLs', plat)
|
'ucrt', 'DLLs', plat)
|
||||||
if not os.path.exists(sdk_path):
|
if not os.path.exists(sdk_path):
|
||||||
raise SystemExit('Windows 10 Universal CRT redistributable not found at: %r' % sdk_path)
|
raise SystemExit('Windows 10 Universal CRT redistributable not found at: %r' % sdk_path)
|
||||||
for dll in glob.glob(os.path.join(sdk_path, '*.dll')):
|
d3d_path = os.path.join(
|
||||||
|
worker_env['WINDOWSSDKDIR'], 'Redist', 'D3D', plat)
|
||||||
|
if not os.path.exists(d3d_path):
|
||||||
|
raise SystemExit('Windows 10 D3D redistributable not found at: %r' % d3d_path)
|
||||||
|
|
||||||
|
def copy_dll(dll):
|
||||||
shutil.copy2(dll, env.dll_dir)
|
shutil.copy2(dll, env.dll_dir)
|
||||||
os.chmod(os.path.join(env.dll_dir, b(dll)), stat.S_IRWXU)
|
os.chmod(os.path.join(env.dll_dir, b(dll)), stat.S_IRWXU)
|
||||||
|
|
||||||
|
for dll in glob.glob(os.path.join(d3d_path, '*.dll')):
|
||||||
|
if os.path.basename(dll).lower().startswith('d3dcompiler_'):
|
||||||
|
copy_dll(dll)
|
||||||
|
for dll in glob.glob(os.path.join(sdk_path, '*.dll')):
|
||||||
|
copy_dll(dll)
|
||||||
for dll in glob.glob(os.path.join(vc_path, '*.dll')):
|
for dll in glob.glob(os.path.join(vc_path, '*.dll')):
|
||||||
bname = os.path.basename(dll)
|
bname = os.path.basename(dll)
|
||||||
if not bname.startswith('vccorlib') and not bname.startswith('concrt'):
|
if not bname.startswith('vccorlib') and not bname.startswith('concrt'):
|
||||||
# Those two DLLs are not required vccorlib is for the CORE CLR
|
# Those two DLLs are not required vccorlib is for the CORE CLR
|
||||||
# I think concrt is the concurrency runtime for C++ which I believe
|
# I think concrt is the concurrency runtime for C++ which I believe
|
||||||
# nothing in calibre currently uses
|
# nothing in calibre currently uses
|
||||||
shutil.copy(dll, env.dll_dir)
|
copy_dll(dll)
|
||||||
os.chmod(os.path.join(env.dll_dir, bname), stat.S_IRWXU)
|
|
||||||
|
|
||||||
|
|
||||||
def sign_executables(env):
|
def sign_executables(env):
|
||||||
@ -685,7 +705,7 @@ def main():
|
|||||||
build_utils(env)
|
build_utils(env)
|
||||||
freeze(env, ext_dir)
|
freeze(env, ext_dir)
|
||||||
embed_manifests(env)
|
embed_manifests(env)
|
||||||
copy_crt(env)
|
copy_crt_and_d3d(env)
|
||||||
archive_lib_dir(env)
|
archive_lib_dir(env)
|
||||||
if not args.skip_tests:
|
if not args.skip_tests:
|
||||||
run_tests(os.path.join(env.base, 'calibre-debug.exe'), env.base)
|
run_tests(os.path.join(env.base, 'calibre-debug.exe'), env.base)
|
||||||
|
@ -53,18 +53,22 @@ static int show_last_error(wchar_t *preamble) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef int (__cdecl *ENTRYPROC)(const char*, const char*, const char*, int);
|
typedef int (__cdecl *ENTRYPROC)(const char*, const char*, const char*, int);
|
||||||
|
typedef void (__cdecl *SIMPLEPRINT)(const wchar_t*);
|
||||||
|
typedef BOOL (*SETDEFAULTDIRS)(DWORD);
|
||||||
|
static ENTRYPROC entrypoint = NULL;
|
||||||
|
static SIMPLEPRINT simple_print = NULL;
|
||||||
|
static HMODULE dll = 0;
|
||||||
|
|
||||||
static ENTRYPROC load_launcher_dll() {
|
static void
|
||||||
wchar_t buf[MAX_PATH]; // Cannot use a zero initializer for the array as it generates an implicit call to memset()
|
load_launcher_dll() {
|
||||||
|
static wchar_t buf[MAX_PATH]; // Cannot use a zero initializer for the array as it generates an implicit call to memset()
|
||||||
wchar_t *dll_point = NULL;
|
wchar_t *dll_point = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
DWORD sz = 0;
|
DWORD sz = 0;
|
||||||
HMODULE dll = 0;
|
|
||||||
ENTRYPROC entrypoint = NULL;
|
|
||||||
|
|
||||||
if ((sz = GetModuleFileNameW(NULL, buf, MAX_PATH)) >= MAX_PATH - 30) {
|
if ((sz = GetModuleFileNameW(NULL, buf, MAX_PATH)) >= MAX_PATH - 30) {
|
||||||
show_error(L"Installation directory path too long", L"", 1);
|
show_error(L"Installation directory path too long", L"", 1);
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sz > 0) {
|
while (sz > 0) {
|
||||||
@ -73,33 +77,36 @@ static ENTRYPROC load_launcher_dll() {
|
|||||||
}
|
}
|
||||||
if (dll_point == NULL) {
|
if (dll_point == NULL) {
|
||||||
show_error(L"Executable path has no path separators", L"", 1);
|
show_error(L"Executable path has no path separators", L"", 1);
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
wsprintf(dll_point, L"%s\0\0", L"app\\DLLs");
|
wsprintf(dll_point, L"%s\0\0", L"app\\bin");
|
||||||
|
// Restrict the directories from which DLLs can be loaded
|
||||||
|
SETDEFAULTDIRS SetDefaultDllDirectories = (SETDEFAULTDIRS)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDefaultDllDirectories");
|
||||||
|
if (SetDefaultDllDirectories) SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
|
||||||
if (SetDllDirectoryW(buf) == 0) {
|
if (SetDllDirectoryW(buf) == 0) {
|
||||||
show_last_error(L"Failed to set DLL directory");
|
show_last_error(L"Failed to set DLL directory");
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
// Have to load ucrtbase manually first, otherwise loading fails on systems where the
|
// Have to load ucrtbase manually first, otherwise loading fails on systems where the
|
||||||
// Universal CRT is not installed.
|
// Universal CRT is not installed.
|
||||||
if (!LoadLibraryW(L"ucrtbase.dll")) {
|
if (!LoadLibraryW(L"ucrtbase.dll")) {
|
||||||
show_last_error(L"Unable to find ucrtbase.dll. You should install all Windows updates on your computer to get this file.");
|
show_last_error(L"Unable to find ucrtbase.dll. You should install all Windows updates on your computer to get this file.");
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
if (!(dll = LoadLibraryW(L"calibre-launcher.dll"))) {
|
if (!(dll = LoadLibraryW(L"calibre-launcher.dll"))) {
|
||||||
show_last_error(L"Failed to load: calibre-launcher.dll");
|
show_last_error(L"Failed to load: calibre-launcher.dll");
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
if (!(entrypoint = (ENTRYPROC) GetProcAddress(dll, "execute_python_entrypoint"))) {
|
if (!(entrypoint = (ENTRYPROC) GetProcAddress(dll, "execute_python_entrypoint"))) {
|
||||||
show_last_error(L"Failed to get the calibre-launcher dll entry point");
|
show_last_error(L"Failed to get the calibre-launcher dll entry point");
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
return entrypoint;
|
simple_print = (SIMPLEPRINT) GetProcAddress(dll, "simple_print");
|
||||||
}
|
}
|
||||||
|
|
||||||
int __stdcall start_here() {
|
int __stdcall start_here() {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
ENTRYPROC entrypoint = load_launcher_dll();
|
load_launcher_dll();
|
||||||
if (entrypoint) {
|
if (entrypoint) {
|
||||||
#ifdef GUI_APP
|
#ifdef GUI_APP
|
||||||
// This should really be returning the value set in the WM_QUIT message, but I cannot be bothered figuring out how to get that.
|
// This should really be returning the value set in the WM_QUIT message, but I cannot be bothered figuring out how to get that.
|
||||||
@ -108,6 +115,10 @@ int __stdcall start_here() {
|
|||||||
ret = entrypoint(BASENAME, MODULE, FUNCTION, 0);
|
ret = entrypoint(BASENAME, MODULE, FUNCTION, 0);
|
||||||
#endif
|
#endif
|
||||||
} else ret = 1;
|
} else ret = 1;
|
||||||
|
if (dll != 0) {
|
||||||
|
FreeLibrary(dll);
|
||||||
|
dll = 0;
|
||||||
|
}
|
||||||
ExitProcess(ret);
|
ExitProcess(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import imp
|
import imp
|
||||||
|
|
||||||
|
|
||||||
class PydImporter(object):
|
class PydImporter(object):
|
||||||
|
|
||||||
__slots__ = ('items', 'description')
|
__slots__ = ('items', 'description')
|
||||||
@ -19,7 +20,7 @@ class PydImporter(object):
|
|||||||
|
|
||||||
def find_module(self, fullname, path=None):
|
def find_module(self, fullname, path=None):
|
||||||
if self.items is None:
|
if self.items is None:
|
||||||
dlls_dir = os.path.join(sys.app_dir, 'app', 'DLLs')
|
dlls_dir = os.path.join(sys.app_dir, 'app', 'bin')
|
||||||
items = self.items = {}
|
items = self.items = {}
|
||||||
for x in os.listdir(dlls_dir):
|
for x in os.listdir(dlls_dir):
|
||||||
lx = x.lower()
|
lx = x.lower()
|
||||||
@ -34,13 +35,19 @@ class PydImporter(object):
|
|||||||
try:
|
try:
|
||||||
path = self.items[fullname.lower()]
|
path = self.items[fullname.lower()]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ImportError('The native code module %s seems to have disappeared from self.items' % fullname)
|
raise ImportError(
|
||||||
|
'The native code module %s seems to have disappeared from self.items'
|
||||||
|
% fullname
|
||||||
|
)
|
||||||
package, name = fullname.rpartition(b'.')[::2]
|
package, name = fullname.rpartition(b'.')[::2]
|
||||||
m = imp.load_module(fullname, None, path, self.description) # This inserts the module into sys.modules itself
|
m = imp.load_module(
|
||||||
|
fullname, None, path, self.description
|
||||||
|
) # This inserts the module into sys.modules itself
|
||||||
m.__loader__ = self
|
m.__loader__ = self
|
||||||
m.__package__ = package or None
|
m.__package__ = package or None
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
|
||||||
def abs__file__():
|
def abs__file__():
|
||||||
"""Set all module __file__ attribute to an absolute path"""
|
"""Set all module __file__ attribute to an absolute path"""
|
||||||
for m in sys.modules.values():
|
for m in sys.modules.values():
|
||||||
@ -51,6 +58,7 @@ def abs__file__():
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
def aliasmbcs():
|
def aliasmbcs():
|
||||||
import locale, codecs
|
import locale, codecs
|
||||||
enc = locale.getdefaultlocale()[1]
|
enc = locale.getdefaultlocale()[1]
|
||||||
@ -62,21 +70,24 @@ def aliasmbcs():
|
|||||||
encodings._cache[enc] = encodings._unknown
|
encodings._cache[enc] = encodings._unknown
|
||||||
encodings.aliases.aliases[enc] = 'mbcs'
|
encodings.aliases.aliases[enc] = 'mbcs'
|
||||||
|
|
||||||
|
|
||||||
def add_calibre_vars():
|
def add_calibre_vars():
|
||||||
sys.new_app_layout = 1
|
sys.new_app_layout = 1
|
||||||
sys.resources_location = os.path.join(sys.app_dir, 'app', 'resources')
|
sys.resources_location = os.path.join(sys.app_dir, 'app', 'resources')
|
||||||
sys.extensions_location = os.path.join(sys.app_dir, 'app', 'DLLs')
|
sys.extensions_location = os.path.join(sys.app_dir, 'app', 'bin')
|
||||||
|
|
||||||
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
|
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
|
||||||
if dv and os.path.exists(dv):
|
if dv and os.path.exists(dv):
|
||||||
sys.path.insert(0, os.path.abspath(dv))
|
sys.path.insert(0, os.path.abspath(dv))
|
||||||
|
|
||||||
|
|
||||||
def run_entry_point():
|
def run_entry_point():
|
||||||
bname, mod, func = sys.calibre_basename, sys.calibre_module, sys.calibre_function
|
bname, mod, func = sys.calibre_basename, sys.calibre_module, sys.calibre_function
|
||||||
sys.argv[0] = bname + '.exe'
|
sys.argv[0] = bname + '.exe'
|
||||||
pmod = __import__(mod, fromlist=[1], level=0)
|
pmod = __import__(mod, fromlist=[1], level=0)
|
||||||
return getattr(pmod, func)()
|
return getattr(pmod, func)()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
sys.frozen = 'windows_exe'
|
sys.frozen = 'windows_exe'
|
||||||
sys.setdefaultencoding('utf-8')
|
sys.setdefaultencoding('utf-8')
|
||||||
@ -86,8 +97,10 @@ def main():
|
|||||||
sys.path_importer_cache.clear()
|
sys.path_importer_cache.clear()
|
||||||
|
|
||||||
import linecache
|
import linecache
|
||||||
|
|
||||||
def fake_getline(filename, lineno, module_globals=None):
|
def fake_getline(filename, lineno, module_globals=None):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
linecache.orig_getline = linecache.getline
|
linecache.orig_getline = linecache.getline
|
||||||
linecache.getline = fake_getline
|
linecache.getline = fake_getline
|
||||||
|
|
||||||
@ -95,7 +108,7 @@ def main():
|
|||||||
|
|
||||||
add_calibre_vars()
|
add_calibre_vars()
|
||||||
|
|
||||||
# Needed for pywintypes to be able to load its DLL
|
# Needed to bypass meaningless check in pywintypes.py
|
||||||
sys.path.append(os.path.join(sys.app_dir, 'app', 'DLLs'))
|
sys.path.append(os.path.join(sys.app_dir, 'app', 'bin'))
|
||||||
|
|
||||||
return run_entry_point()
|
return run_entry_point()
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define arraysz(x) (sizeof((x))/sizeof((x)[0]))
|
||||||
|
|
||||||
static int GUI_APP = 0;
|
static int GUI_APP = 0;
|
||||||
static char python_dll[] = PYDLL;
|
static char python_dll[] = PYDLL;
|
||||||
@ -25,29 +26,16 @@ void set_gui_app(int yes) { GUI_APP = yes; }
|
|||||||
int calibre_show_python_error(const wchar_t *preamble, int code);
|
int calibre_show_python_error(const wchar_t *preamble, int code);
|
||||||
|
|
||||||
static int _show_error(const wchar_t *preamble, const wchar_t *msg, const int code) {
|
static int _show_error(const wchar_t *preamble, const wchar_t *msg, const int code) {
|
||||||
wchar_t *buf;
|
static wchar_t buf[4096];
|
||||||
char *cbuf;
|
|
||||||
buf = (wchar_t*)LocalAlloc(LMEM_ZEROINIT, sizeof(wchar_t)*
|
|
||||||
(wcslen(msg) + wcslen(preamble) + 80));
|
|
||||||
|
|
||||||
_snwprintf_s(buf,
|
fwprintf(stderr, L"%s\r\n %s (Error Code: %d)\r\n", preamble, msg, code);
|
||||||
LocalSize(buf) / sizeof(wchar_t), _TRUNCATE,
|
fflush(stderr);
|
||||||
L"%s\r\n %s (Error Code: %d)\r\n",
|
|
||||||
preamble, msg, code);
|
|
||||||
|
|
||||||
if (GUI_APP) {
|
if (GUI_APP) {
|
||||||
|
_snwprintf_s(buf, arraysz(buf), _TRUNCATE, L"%s\r\n %s (Error Code: %d)\r\n", preamble, msg, code);
|
||||||
MessageBeep(MB_ICONERROR);
|
MessageBeep(MB_ICONERROR);
|
||||||
MessageBox(NULL, buf, NULL, MB_OK|MB_ICONERROR);
|
MessageBox(NULL, buf, NULL, MB_OK|MB_ICONERROR);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
cbuf = (char*) calloc(10+(wcslen(buf)*4), sizeof(char));
|
|
||||||
if (cbuf) {
|
|
||||||
if (WideCharToMultiByte(CP_UTF8, 0, buf, -1, cbuf, (int)(10+(wcslen(buf)*4)), NULL, NULL) != 0) printf_s(cbuf);
|
|
||||||
free(cbuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalFree(buf);
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,72 +71,72 @@ int show_last_error(wchar_t *preamble) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* get_app_dir() {
|
static char app_dir[MAX_PATH] = {0};
|
||||||
char *buf, *buf2, *buf3;
|
static wchar_t dll_dir[MAX_PATH] = {0};
|
||||||
|
static wchar_t qt_prefix_dir[MAX_PATH] = {0};
|
||||||
|
static char program_name[MAX_PATH] = {0};
|
||||||
|
static wchar_t w_program_name[MAX_PATH] = {0};
|
||||||
|
static wchar_t w_app_dir[MAX_PATH] = {0};
|
||||||
|
#if PY_VERSION_MAJOR >= 3
|
||||||
|
static wchar_t python_path[MAX_PATH] = {0};
|
||||||
|
#else
|
||||||
|
static char python_path[MAX_PATH] = {0};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_app_dir(void) {
|
||||||
char drive[4] = "\0\0\0";
|
char drive[4] = "\0\0\0";
|
||||||
DWORD sz; errno_t err;
|
DWORD sz; errno_t err;
|
||||||
|
char buf[MAX_PATH] = {0};
|
||||||
|
|
||||||
buf = (char*)calloc(MAX_PATH, sizeof(char));
|
sz = GetModuleFileNameA(NULL, program_name, MAX_PATH);
|
||||||
buf2 = (char*)calloc(MAX_PATH, sizeof(char));
|
|
||||||
buf3 = (char*)calloc(MAX_PATH, sizeof(char));
|
|
||||||
if (!buf || !buf2 || !buf3) ExitProcess(_show_error(L"Out of memory", L"", 1));
|
|
||||||
sz = GetModuleFileNameA(NULL, buf, MAX_PATH);
|
|
||||||
if (sz >= MAX_PATH-1) ExitProcess(_show_error(L"Installation directory path too long", L"", 1));
|
if (sz >= MAX_PATH-1) ExitProcess(_show_error(L"Installation directory path too long", L"", 1));
|
||||||
err = _splitpath_s(buf, drive, 4, buf2, MAX_PATH, NULL, 0, NULL, 0);
|
err = _splitpath_s(program_name, drive, 4, buf, MAX_PATH, NULL, 0, NULL, 0);
|
||||||
if (err != 0) ExitProcess(show_last_error_crt(L"Failed to find application directory"));
|
if (err != 0) ExitProcess(show_last_error_crt(L"Failed to find application directory"));
|
||||||
_snprintf_s(buf3, MAX_PATH, _TRUNCATE, "%s%s", drive, buf2);
|
_snprintf_s(app_dir, MAX_PATH, _TRUNCATE, "%s%s", drive, buf);
|
||||||
free(buf); free(buf2);
|
|
||||||
return buf3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t* get_app_dirw() {
|
static void
|
||||||
wchar_t *buf, *buf2, *buf3;
|
get_app_dirw(void) {
|
||||||
|
wchar_t buf[MAX_PATH] = {0};
|
||||||
wchar_t drive[4] = L"\0\0\0";
|
wchar_t drive[4] = L"\0\0\0";
|
||||||
DWORD sz; errno_t err;
|
DWORD sz; errno_t err;
|
||||||
|
|
||||||
buf = (wchar_t*)calloc(MAX_PATH, sizeof(wchar_t));
|
sz = GetModuleFileNameW(NULL, w_program_name, MAX_PATH);
|
||||||
buf2 = (wchar_t*)calloc(MAX_PATH, sizeof(wchar_t));
|
|
||||||
buf3 = (wchar_t*)calloc(MAX_PATH, sizeof(wchar_t));
|
|
||||||
if (!buf || !buf2 || !buf3) ExitProcess(_show_error(L"Out of memory", L"", 1));
|
|
||||||
sz = GetModuleFileNameW(NULL, buf, MAX_PATH);
|
|
||||||
if (sz >= MAX_PATH-1) ExitProcess(_show_error(L"Installation directory path too long", L"", 1));
|
if (sz >= MAX_PATH-1) ExitProcess(_show_error(L"Installation directory path too long", L"", 1));
|
||||||
err = _wsplitpath_s(buf, drive, 4, buf2, MAX_PATH, NULL, 0, NULL, 0);
|
err = _wsplitpath_s(w_program_name, drive, 4, buf, MAX_PATH, NULL, 0, NULL, 0);
|
||||||
if (err != 0) ExitProcess(show_last_error_crt(L"Failed to find application directory"));
|
if (err != 0) ExitProcess(show_last_error_crt(L"Failed to find application directory"));
|
||||||
_snwprintf_s(buf3, MAX_PATH, _TRUNCATE, L"%s%s", drive, buf2);
|
_snwprintf_s(w_app_dir, MAX_PATH, _TRUNCATE, L"%s%s", drive, buf);
|
||||||
free(buf); free(buf2);
|
|
||||||
return buf3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_install_locations(void) {
|
||||||
|
get_app_dir();
|
||||||
|
get_app_dirw();
|
||||||
|
_snwprintf_s(qt_prefix_dir, MAX_PATH-1, _TRUNCATE, L"%s\\app", w_app_dir);
|
||||||
|
_wputenv_s(L"CALIBRE_QT_PREFIX", qt_prefix_dir);
|
||||||
|
_snwprintf_s(dll_dir, MAX_PATH-1, _TRUNCATE, L"%s\\app\\bin", w_app_dir);
|
||||||
|
#if PY_VERSION_MAJOR >= 3
|
||||||
|
_snwprintf_s(python_path, MAX_PATH-1, _TRUNCATE, L"%s\\app\\pylib.zip", w_app_dir);
|
||||||
|
#else
|
||||||
|
_snprintf_s(python_path, MAX_PATH-1, _TRUNCATE, "%s\\app\\pylib.zip", app_dir);
|
||||||
|
#endif
|
||||||
|
|
||||||
void load_python_dll() {
|
}
|
||||||
char *app_dir, *dll_dir, *qt_plugin_dir;
|
|
||||||
size_t l;
|
|
||||||
|
|
||||||
app_dir = get_app_dir();
|
static void
|
||||||
l = strlen(app_dir)+25;
|
load_python_dll() {
|
||||||
dll_dir = (char*) calloc(l, sizeof(char));
|
get_install_locations();
|
||||||
qt_plugin_dir = (char*) calloc(l, sizeof(char));
|
|
||||||
if (!dll_dir || !qt_plugin_dir) ExitProcess(_show_error(L"Out of memory", L"", 1));
|
|
||||||
_snprintf_s(dll_dir, l, _TRUNCATE, "%s\\app\\DLLs", app_dir);
|
|
||||||
_snprintf_s(qt_plugin_dir, l, _TRUNCATE, "%s\\app\\qt_plugins", app_dir);
|
|
||||||
free(app_dir);
|
|
||||||
|
|
||||||
_putenv_s("QT_PLUGIN_PATH", qt_plugin_dir);
|
|
||||||
|
|
||||||
if (!SetDllDirectoryA(dll_dir)) ExitProcess(show_last_error(L"Failed to set DLL directory."));
|
|
||||||
if (FAILED(__HrLoadAllImportsForDll(python_dll)))
|
if (FAILED(__HrLoadAllImportsForDll(python_dll)))
|
||||||
ExitProcess(_show_error(L"Failed to delay load the python dll", L"", 1));
|
ExitProcess(_show_error(L"Failed to delay load the python dll", L"", 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char program_name[MAX_PATH];
|
const static wchar_t out_of_memory[] = L"Out of memory";
|
||||||
static char python_home[MAX_PATH];
|
|
||||||
|
|
||||||
static wchar_t out_of_memory[] = L"Out of memory";
|
static void
|
||||||
|
setup_stream(const char *name, const char *errors, UINT cp) {
|
||||||
void setup_stream(const char *name, const char *errors, UINT cp) {
|
|
||||||
PyObject *stream;
|
PyObject *stream;
|
||||||
char *buf = (char *)calloc(100, sizeof(char));
|
char buf[128] = {0};
|
||||||
if (!buf) ExitProcess(_show_error(out_of_memory, L"", 1));
|
|
||||||
|
|
||||||
if (cp == CP_UTF8) _snprintf_s(buf, 100, _TRUNCATE, "%s", "utf-8");
|
if (cp == CP_UTF8) _snprintf_s(buf, 100, _TRUNCATE, "%s", "utf-8");
|
||||||
else if (cp == CP_UTF7) _snprintf_s(buf, 100, _TRUNCATE, "%s", "utf-7");
|
else if (cp == CP_UTF7) _snprintf_s(buf, 100, _TRUNCATE, "%s", "utf-7");
|
||||||
@ -158,9 +146,6 @@ void setup_stream(const char *name, const char *errors, UINT cp) {
|
|||||||
|
|
||||||
if (!PyFile_SetEncodingAndErrors(stream, buf, (char*)errors))
|
if (!PyFile_SetEncodingAndErrors(stream, buf, (char*)errors))
|
||||||
ExitProcess(calibre_show_python_error(L"Failed to set stream encoding", 1));
|
ExitProcess(calibre_show_python_error(L"Failed to set stream encoding", 1));
|
||||||
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT
|
UINT
|
||||||
@ -187,30 +172,12 @@ setup_streams() {
|
|||||||
|
|
||||||
UINT
|
UINT
|
||||||
initialize_interpreter(const char *basename, const char *module, const char *function) {
|
initialize_interpreter(const char *basename, const char *module, const char *function) {
|
||||||
DWORD sz; char *buf, *path; HMODULE dll;
|
DWORD sz; HMODULE dll;
|
||||||
int *flag, i, argc;
|
int *flag, i, argc;
|
||||||
wchar_t *app_dir, **wargv;
|
wchar_t **wargv;
|
||||||
PyObject *argv, *v;
|
PyObject *argv, *v;
|
||||||
char *dummy_argv[1] = {""};
|
char *dummy_argv[1] = {""};
|
||||||
|
|
||||||
buf = (char*)calloc(MAX_PATH, sizeof(char));
|
|
||||||
path = (char*)calloc(MAX_PATH, sizeof(char));
|
|
||||||
if (!buf || !path) ExitProcess(_show_error(L"Out of memory", L"", 1));
|
|
||||||
|
|
||||||
sz = GetModuleFileNameA(NULL, buf, MAX_PATH);
|
|
||||||
if (sz >= MAX_PATH-1) ExitProcess(_show_error(L"Installation directory path too long", L"", 1));
|
|
||||||
|
|
||||||
_snprintf_s(program_name, MAX_PATH, _TRUNCATE, "%s", buf);
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
buf = get_app_dir();
|
|
||||||
buf[strlen(buf)-1] = '\0';
|
|
||||||
|
|
||||||
_snprintf_s(python_home, MAX_PATH, _TRUNCATE, "%s", buf);
|
|
||||||
_snprintf_s(path, MAX_PATH, _TRUNCATE, "%s\\app\\pylib.zip", buf);
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
|
|
||||||
dll = GetModuleHandleA(python_dll);
|
dll = GetModuleHandleA(python_dll);
|
||||||
if (!dll) ExitProcess(show_last_error(L"Failed to get python dll handle"));
|
if (!dll) ExitProcess(show_last_error(L"Failed to get python dll handle"));
|
||||||
flag = (int*)GetProcAddress(dll, "Py_OptimizeFlag");
|
flag = (int*)GetProcAddress(dll, "Py_OptimizeFlag");
|
||||||
@ -238,8 +205,13 @@ initialize_interpreter(const char *basename, const char *module, const char *fun
|
|||||||
if (!flag) ExitProcess(_show_error(L"Failed to get debug flag", L"", 1));
|
if (!flag) ExitProcess(_show_error(L"Failed to get debug flag", L"", 1));
|
||||||
//*flag = 1;
|
//*flag = 1;
|
||||||
|
|
||||||
|
#if PY_VERSION_MAJOR >= 3
|
||||||
|
Py_SetProgramName(w_program_name);
|
||||||
|
Py_SetPythonHome(w_app_dir);
|
||||||
|
#else
|
||||||
Py_SetProgramName(program_name);
|
Py_SetProgramName(program_name);
|
||||||
Py_SetPythonHome(python_home);
|
Py_SetPythonHome(app_dir);
|
||||||
|
#endif
|
||||||
|
|
||||||
//printf("Path before Py_Initialize(): %s\r\n\n", Py_GetPath());
|
//printf("Path before Py_Initialize(): %s\r\n\n", Py_GetPath());
|
||||||
Py_Initialize();
|
Py_Initialize();
|
||||||
@ -247,11 +219,10 @@ initialize_interpreter(const char *basename, const char *module, const char *fun
|
|||||||
|
|
||||||
PySys_SetArgv(1, dummy_argv);
|
PySys_SetArgv(1, dummy_argv);
|
||||||
//printf("Path after Py_Initialize(): %s\r\n\n", Py_GetPath());
|
//printf("Path after Py_Initialize(): %s\r\n\n", Py_GetPath());
|
||||||
PySys_SetPath(path);
|
PySys_SetPath(python_path);
|
||||||
//printf("Path set by me: %s\r\n\n", path);
|
//printf("Path set by me: %s\r\n\n", path);
|
||||||
PySys_SetObject("gui_app", PyBool_FromLong((long)GUI_APP));
|
PySys_SetObject("gui_app", PyBool_FromLong((long)GUI_APP));
|
||||||
app_dir = get_app_dirw();
|
PySys_SetObject("app_dir", PyUnicode_FromWideChar(w_app_dir, wcslen(w_app_dir)));
|
||||||
PySys_SetObject("app_dir", PyUnicode_FromWideChar(app_dir, wcslen(app_dir)));
|
|
||||||
|
|
||||||
PySys_SetObject("calibre_basename", PyBytes_FromString(basename));
|
PySys_SetObject("calibre_basename", PyBytes_FromString(basename));
|
||||||
PySys_SetObject("calibre_module", PyBytes_FromString(module));
|
PySys_SetObject("calibre_module", PyBytes_FromString(module));
|
||||||
@ -271,22 +242,21 @@ initialize_interpreter(const char *basename, const char *module, const char *fun
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wchar_t* pyobject_to_wchar(PyObject *o) {
|
static const wchar_t*
|
||||||
PyUnicodeObject *t;
|
pyobject_to_wchar(PyObject *o) {
|
||||||
|
PyObject *t = NULL;
|
||||||
size_t s;
|
size_t s;
|
||||||
wchar_t *ans;
|
static wchar_t ans[4096];
|
||||||
|
|
||||||
if (!PyUnicode_Check(o)) {
|
if (!PyUnicode_Check(o)) {
|
||||||
t = (PyUnicodeObject*)PyUnicode_FromEncodedObject(o, NULL, "replace");
|
t = PyUnicode_FromEncodedObject(o, NULL, "replace");
|
||||||
if (t == NULL) return NULL;
|
if (t == NULL) return NULL;
|
||||||
} else t = (PyUnicodeObject*)o;
|
}
|
||||||
|
|
||||||
|
s = PyUnicode_AsWideChar(t ? t : o, ans, arraysz(ans)-1);
|
||||||
s = 2*PyUnicode_GET_SIZE(t) +1;
|
Py_XDECREF(t);
|
||||||
ans = (wchar_t*)calloc(s, sizeof(wchar_t));
|
if (s >= 0) ans[s] = 0;
|
||||||
if (ans == NULL) return NULL;
|
else ans[s] = 0;
|
||||||
s = PyUnicode_AsWideChar(t, ans, s-1);
|
|
||||||
ans[s] = L'\0';
|
|
||||||
|
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
@ -315,7 +285,7 @@ int handle_sysexit(PyObject *e) {
|
|||||||
int calibre_show_python_error(const wchar_t *preamble, int code) {
|
int calibre_show_python_error(const wchar_t *preamble, int code) {
|
||||||
PyObject *exc, *val, *tb, *str, **system_exit;
|
PyObject *exc, *val, *tb, *str, **system_exit;
|
||||||
HMODULE dll;
|
HMODULE dll;
|
||||||
int ret, issysexit = 0; wchar_t *i;
|
int ret, issysexit = 0; const wchar_t *i;
|
||||||
|
|
||||||
if (!PyErr_Occurred()) return code;
|
if (!PyErr_Occurred()) return code;
|
||||||
dll = GetModuleHandleA(python_dll);
|
dll = GetModuleHandleA(python_dll);
|
||||||
@ -340,7 +310,6 @@ int calibre_show_python_error(const wchar_t *preamble, int code) {
|
|||||||
}
|
}
|
||||||
i = pyobject_to_wchar(str);
|
i = pyobject_to_wchar(str);
|
||||||
ret = _show_error(preamble, (i==NULL)?out_of_memory:i, code);
|
ret = _show_error(preamble, (i==NULL)?out_of_memory:i, code);
|
||||||
if (i) free(i);
|
|
||||||
if (tb != NULL) {
|
if (tb != NULL) {
|
||||||
PyErr_Restore(exc, val, tb);
|
PyErr_Restore(exc, val, tb);
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
@ -373,6 +342,10 @@ null_invalid_parameter_handler(
|
|||||||
// to return errors instead of aborting the program. So get the windows CRT
|
// to return errors instead of aborting the program. So get the windows CRT
|
||||||
// to do that.
|
// to do that.
|
||||||
}
|
}
|
||||||
|
__declspec(dllexport) int __cdecl
|
||||||
|
simple_print(const wchar_t *msg) {
|
||||||
|
wprintf(L"%s", msg); fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
__declspec(dllexport) int __cdecl
|
__declspec(dllexport) int __cdecl
|
||||||
execute_python_entrypoint(const char *basename, const char *module, const char *function, int is_gui_app) {
|
execute_python_entrypoint(const char *basename, const char *module, const char *function, int is_gui_app) {
|
||||||
@ -398,51 +371,35 @@ execute_python_entrypoint(const char *basename, const char *module, const char *
|
|||||||
if (site == NULL)
|
if (site == NULL)
|
||||||
ret = calibre_show_python_error(L"Failed to import site module", 1);
|
ret = calibre_show_python_error(L"Failed to import site module", 1);
|
||||||
else {
|
else {
|
||||||
Py_XINCREF(site);
|
Py_INCREF(site);
|
||||||
|
|
||||||
main = PyObject_GetAttrString(site, "main");
|
main = PyObject_GetAttrString(site, "main");
|
||||||
if (main == NULL || !PyCallable_Check(main))
|
if (main == NULL || !PyCallable_Check(main))
|
||||||
ret = calibre_show_python_error(L"site module has no main function", 1);
|
ret = calibre_show_python_error(L"site module has no main function", 1);
|
||||||
else {
|
else {
|
||||||
Py_XINCREF(main);
|
Py_INCREF(main);
|
||||||
res = PyObject_CallObject(main, NULL);
|
res = PyObject_CallObject(main, NULL);
|
||||||
|
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
ret = calibre_show_python_error(L"Python function terminated unexpectedly", 1);
|
ret = calibre_show_python_error(L"Python function terminated unexpectedly", 1);
|
||||||
else {
|
else {
|
||||||
|
#if PY_VERSION_MAJOR < 3
|
||||||
|
if (PyInt_Check(res)) {
|
||||||
|
ret = PyInt_AS_LONG(res);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (PyLong_Check(res)) {
|
||||||
|
ret = PyLong_AsLong(res);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Py_DECREF(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
Py_Finalize();
|
Py_Finalize();
|
||||||
if (code_page != CP_UTF8) SetConsoleOutputCP(code_page);
|
if (code_page != CP_UTF8) SetConsoleOutputCP(code_page);
|
||||||
|
/* printf("111111111111 returning: %d\r\n", ret); */
|
||||||
|
|
||||||
//printf("11111 Returning: %d\r\n", ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wchar_t* get_temp_filename(const wchar_t *prefix) {
|
|
||||||
DWORD dwRetVal;
|
|
||||||
UINT uRetVal;
|
|
||||||
|
|
||||||
wchar_t *szTempName;
|
|
||||||
wchar_t lpPathBuffer[MAX_PATH];
|
|
||||||
szTempName = (wchar_t *)LocalAlloc(LMEM_ZEROINIT, sizeof(wchar_t)*MAX_PATH);
|
|
||||||
|
|
||||||
dwRetVal = GetTempPath(MAX_PATH, lpPathBuffer);
|
|
||||||
|
|
||||||
if (dwRetVal > MAX_PATH || (dwRetVal == 0)) {
|
|
||||||
ExitProcess(show_last_error(L"Failed to get temp path."));
|
|
||||||
}
|
|
||||||
|
|
||||||
uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files
|
|
||||||
prefix, // temp file name prefix
|
|
||||||
0, // create unique name
|
|
||||||
szTempName); // buffer for name
|
|
||||||
|
|
||||||
if (uRetVal == 0) {
|
|
||||||
ExitProcess(show_last_error(L"Failed to get temp file name"));
|
|
||||||
}
|
|
||||||
return szTempName;
|
|
||||||
}
|
|
||||||
|
@ -194,7 +194,7 @@ def sanitize_path():
|
|||||||
needed_paths.append(p)
|
needed_paths.append(p)
|
||||||
executables.remove(x)
|
executables.remove(x)
|
||||||
sw = os.environ['SW']
|
sw = os.environ['SW']
|
||||||
paths = r'{0}\private\python\DLLs {0}\private\python\Lib\site-packages\pywin32_system32 {0}\bin {0}\qt\bin C:\Windows\System32'.format(
|
paths = r'{0}\private\python\bin {0}\private\python\Lib\site-packages\pywin32_system32 {0}\bin {0}\qt\bin C:\Windows\System32'.format(
|
||||||
sw
|
sw
|
||||||
).split() + needed_paths
|
).split() + needed_paths
|
||||||
os.environ['PATH'] = os.pathsep.join(paths)
|
os.environ['PATH'] = os.pathsep.join(paths)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user