deploy-ng: changes to make macOS app bundles work correctly
This commit is contained in:
parent
c911ba8059
commit
2c35d7a8e9
|
|
@ -1619,7 +1619,7 @@ class Freezer:
|
|||
|
||||
return target
|
||||
|
||||
def generateRuntimeFromStub(self, target, stub_file, fields={}):
|
||||
def generateRuntimeFromStub(self, target, stub_file, use_console, fields={}):
|
||||
# We must have a __main__ module to make an exe file.
|
||||
if not self.__writingModule('__main__'):
|
||||
message = "Can't generate an executable without a __main__ module."
|
||||
|
|
@ -1700,7 +1700,11 @@ class Freezer:
|
|||
# trouble importing it as a builtin module. Synthesize a frozen
|
||||
# module that loads it dynamically.
|
||||
if '.' in moduleName:
|
||||
code = 'import sys;del sys.modules["%s"];import sys,os,imp;imp.load_dynamic("%s",os.path.join(os.path.dirname(sys.executable), "%s%s"))' % (moduleName, moduleName, moduleName, modext)
|
||||
if self.platform.startswith("macosx") and not use_console:
|
||||
# We write the Frameworks directory to sys.path[0].
|
||||
code = 'import sys;del sys.modules["%s"];import sys,os,imp;imp.load_dynamic("%s",os.path.join(sys.path[0], "%s%s"))' % (moduleName, moduleName, moduleName, modext)
|
||||
else:
|
||||
code = 'import sys;del sys.modules["%s"];import sys,os,imp;imp.load_dynamic("%s",os.path.join(os.path.dirname(sys.executable), "%s%s"))' % (moduleName, moduleName, moduleName, modext)
|
||||
code = compile(code, moduleName, 'exec')
|
||||
code = marshal.dumps(code)
|
||||
moduleList.append((moduleName, len(pool), len(code)))
|
||||
|
|
|
|||
|
|
@ -33,6 +33,12 @@ def egg2bam(_build_cmd, srcpath, dstpath):
|
|||
])
|
||||
return dstpath
|
||||
|
||||
macosx_binary_magics = (
|
||||
b'\xFE\xED\xFA\xCE', b'\xCE\xFA\xED\xFE',
|
||||
b'\xFE\xED\xFA\xCF', b'\xCF\xFA\xED\xFE',
|
||||
b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\xCA',
|
||||
b'\xCA\xFE\xBA\xBF', b'\xBF\xBA\xFE\xCA')
|
||||
|
||||
|
||||
class build_apps(distutils.core.Command):
|
||||
description = 'build Panda3D applications'
|
||||
|
|
@ -121,15 +127,11 @@ class build_apps(distutils.core.Command):
|
|||
num_gui_apps = len(self.gui_apps)
|
||||
num_console_apps = len(self.console_apps)
|
||||
|
||||
if self.macos_main_app is None:
|
||||
if not self.macos_main_app:
|
||||
if num_gui_apps > 1:
|
||||
assert True, 'macos_main_app must be defined if more than one gui_app is defined'
|
||||
assert False, 'macos_main_app must be defined if more than one gui_app is defined'
|
||||
elif num_gui_apps == 1:
|
||||
self.macos_main_app = list(self.gui_apps.keys())[0]
|
||||
elif num_console_apps > 1:
|
||||
assert True, 'macos_main_app must be defined if more than one console_app is defined with no gui_apps'
|
||||
elif num_console_apps == 1:
|
||||
self.macos_main_app = list(self.console_apps.keys())[0]
|
||||
|
||||
assert os.path.exists(self.requirements_path), 'Requirements.txt path does not exist: {}'.format(self.requirements_path)
|
||||
assert num_gui_apps + num_console_apps != 0, 'Must specify at least one app in either gui_apps or console_apps'
|
||||
|
|
@ -209,10 +211,9 @@ class build_apps(distutils.core.Command):
|
|||
|
||||
if fname in self.gui_apps or self.console_apps:
|
||||
dst = macosdir
|
||||
elif src.endswith('.so') or src.endswith('dylib'):
|
||||
elif os.path.isfile(src) and open(src, 'rb').read(4) in macosx_binary_magics:
|
||||
dst = fwdir
|
||||
else:
|
||||
# TODO Cg still shows up in Resources when it should be in Frameworks
|
||||
dst = resdir
|
||||
shutil.move(src, dst)
|
||||
|
||||
|
|
@ -283,7 +284,7 @@ class build_apps(distutils.core.Command):
|
|||
target_path = os.path.join(builddir, appname)
|
||||
|
||||
stub_name = 'deploy-stub'
|
||||
if platform.startswith('win'):
|
||||
if platform.startswith('win') or 'macosx' in platform:
|
||||
if not use_console:
|
||||
stub_name = 'deploy-stubw'
|
||||
|
||||
|
|
@ -298,7 +299,7 @@ class build_apps(distutils.core.Command):
|
|||
stub_path = os.path.join(os.path.dirname(dtool_path), '..', 'bin', stub_name)
|
||||
stub_file = open(stub_path, 'rb')
|
||||
|
||||
freezer.generateRuntimeFromStub(target_path, stub_file, {
|
||||
freezer.generateRuntimeFromStub(target_path, stub_file, use_console, {
|
||||
'prc_data': None,
|
||||
'default_prc_dir': None,
|
||||
'prc_dir_envvars': None,
|
||||
|
|
@ -481,8 +482,8 @@ class build_apps(distutils.core.Command):
|
|||
copy_file(src, dst)
|
||||
|
||||
# Bundle into an .app on macOS
|
||||
#if 'macosx' in platform:
|
||||
# self.bundle_macos_app(builddir)
|
||||
if self.macos_main_app and 'macosx' in platform:
|
||||
self.bundle_macos_app(builddir)
|
||||
|
||||
def add_dependency(self, name, target_dir, search_path, referenced_by):
|
||||
""" Searches for the given DLL on the search path. If it exists,
|
||||
|
|
@ -699,6 +700,10 @@ class build_apps(distutils.core.Command):
|
|||
|
||||
if cmd == 0x0c: # LC_LOAD_DYLIB
|
||||
dylib = cmd_data[16:].decode('ascii').split('\x00', 1)[0]
|
||||
if dylib.startswith('@loader_path/../Frameworks/'):
|
||||
dylib = dylib.replace('@loader_path/../Frameworks/', '')
|
||||
if dylib.startswith('@executable_path/../Frameworks/'):
|
||||
dylib = dylib.replace('@executable_path/../Frameworks/', '')
|
||||
if dylib.startswith('@loader_path/'):
|
||||
dylib = dylib.replace('@loader_path/', '')
|
||||
load_dylibs.append(dylib)
|
||||
|
|
|
|||
|
|
@ -6617,6 +6617,12 @@ if PkgSkip("PYTHON") == 0:
|
|||
TargetAdd('deploy-stubw.exe', input='deploy-stub.obj')
|
||||
TargetAdd('deploy-stubw.exe', input='frozen_dllmain.obj')
|
||||
TargetAdd('deploy-stubw.exe', opts=['SUBSYSTEM:WINDOWS', 'PYTHON', 'DEPLOYSTUB', 'NOICON'])
|
||||
elif GetTarget() == 'darwin':
|
||||
DefSymbol('MACOS_APP_BUNDLE', 'MACOS_APP_BUNDLE')
|
||||
OPTS = OPTS + ['MACOS_APP_BUNDLE']
|
||||
TargetAdd('deploy-stubw.obj', opts=OPTS, input='deploy-stub.c')
|
||||
TargetAdd('deploy-stubw.exe', input='deploy-stubw.obj')
|
||||
TargetAdd('deploy-stubw.exe', opts=['MACOS_APP_BUNDLE', 'PYTHON', 'DEPLOYSTUB', 'NOICON'])
|
||||
|
||||
#
|
||||
# Generate the models directory and samples directory
|
||||
|
|
|
|||
|
|
@ -349,7 +349,10 @@ class WheelFile(object):
|
|||
|
||||
# Fix things like @loader_path/../lib references
|
||||
if sys.platform == "darwin":
|
||||
deps_path = '@loader_path'
|
||||
if source_path.endswith('deploy-stubw'):
|
||||
deps_path = '@executable_path/../Frameworks'
|
||||
else:
|
||||
deps_path = '@loader_path'
|
||||
loader_path = [os.path.dirname(source_path)]
|
||||
for dep in deps:
|
||||
if dep.endswith('/Python'):
|
||||
|
|
|
|||
|
|
@ -237,6 +237,37 @@ int Py_FrozenMain(int argc, char **argv)
|
|||
PySys_SetArgv(argc, argv);
|
||||
#endif
|
||||
|
||||
#ifdef MACOS_APP_BUNDLE
|
||||
// Add the Frameworks directory to sys.path.
|
||||
char buffer[PATH_MAX];
|
||||
uint32_t bufsize = sizeof(buffer);
|
||||
if (_NSGetExecutablePath(buffer, &bufsize) != 0) {
|
||||
assert(false);
|
||||
return 1;
|
||||
}
|
||||
char resolved[PATH_MAX];
|
||||
if (!realpath(buffer, resolved)) {
|
||||
perror("realpath");
|
||||
return 1;
|
||||
}
|
||||
const char *dir = dirname(resolved);
|
||||
sprintf(buffer, "%s/../Frameworks", dir);
|
||||
|
||||
PyObject *sys_path = PyList_New(1);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyList_SET_ITEM(sys_path, 0, PyUnicode_FromString(buffer));
|
||||
#else
|
||||
PyList_SET_ITEM(sys_path, 0, PyString_FromString(buffer));
|
||||
#endif
|
||||
PySys_SetObject("path", sys_path);
|
||||
Py_DECREF(sys_path);
|
||||
|
||||
// Now, store a path to the Resources directory into the main_dir pointer,
|
||||
// for ConfigPageManager to read out and assign to MAIN_DIR.
|
||||
sprintf(buffer, "%s/../Resources", dir);
|
||||
set_main_dir(buffer);
|
||||
#endif
|
||||
|
||||
n = PyImport_ImportFrozenModule("__main__");
|
||||
if (n == 0)
|
||||
Py_FatalError("__main__ not frozen");
|
||||
|
|
|
|||
Loading…
Reference in New Issue