mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -04:00
Move runtime generation logic from yapdt to FreezeTool
This commit is contained in:
parent
aa6e722941
commit
b1a57643f9
@ -7,6 +7,7 @@ import os
|
|||||||
import marshal
|
import marshal
|
||||||
import imp
|
import imp
|
||||||
import platform
|
import platform
|
||||||
|
import struct
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
import distutils.sysconfig as sysconf
|
import distutils.sysconfig as sysconf
|
||||||
|
|
||||||
@ -1549,6 +1550,93 @@ class Freezer:
|
|||||||
|
|
||||||
return target
|
return target
|
||||||
|
|
||||||
|
def generateRuntimeFromStub(self, basename):
|
||||||
|
def make_module_list_entry(code, offset, modulename, module):
|
||||||
|
size = len(code)
|
||||||
|
if getattr(module, "__path__", None):
|
||||||
|
# Indicate package by negative size
|
||||||
|
size = -size
|
||||||
|
return struct.pack('<256sIi', bytes(modulename, 'ascii'), offset, size)
|
||||||
|
|
||||||
|
def make_forbidden_module_list_entry(modulename):
|
||||||
|
return struct.pack('<256sIi', bytes(modulename, 'ascii'), 0, 0)
|
||||||
|
|
||||||
|
# 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."
|
||||||
|
raise Exception(message)
|
||||||
|
|
||||||
|
if self.platform.startswith('win'):
|
||||||
|
target = basename + '.exe'
|
||||||
|
else:
|
||||||
|
target = basename
|
||||||
|
|
||||||
|
|
||||||
|
# Generate export table.
|
||||||
|
moduleBlob = bytes()
|
||||||
|
codeOffset = 0
|
||||||
|
moduleList = []
|
||||||
|
|
||||||
|
for moduleName, mdef in self.getModuleDefs():
|
||||||
|
origName = mdef.moduleName
|
||||||
|
if mdef.forbid:
|
||||||
|
# Explicitly disallow importing this module.
|
||||||
|
moduleList.append(make_forbidden_module_list_entry(moduleName))
|
||||||
|
continue
|
||||||
|
|
||||||
|
assert not mdef.exclude
|
||||||
|
# Allow importing this module.
|
||||||
|
module = self.mf.modules.get(origName, None)
|
||||||
|
code = getattr(module, "__code__", None)
|
||||||
|
if code:
|
||||||
|
code = marshal.dumps(code)
|
||||||
|
moduleList.append(make_module_list_entry(code, codeOffset, moduleName, module))
|
||||||
|
moduleBlob += code
|
||||||
|
codeOffset += len(code)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# This is a module with no associated Python code. It is either
|
||||||
|
# an extension module or a builtin module. Get the filename, if
|
||||||
|
# it is the former.
|
||||||
|
extensionFilename = getattr(module, '__file__', None)
|
||||||
|
|
||||||
|
if extensionFilename or self.linkExtensionModules:
|
||||||
|
self.extras.append((moduleName, extensionFilename))
|
||||||
|
|
||||||
|
# If it is a submodule of a frozen module, Python will have
|
||||||
|
# trouble importing it as a builtin module. Synthesize a frozen
|
||||||
|
# module that loads it as builtin.
|
||||||
|
if '.' in moduleName and self.linkExtensionModules:
|
||||||
|
code = compile('import sys;del sys.modules["%s"];import imp;imp.init_builtin("%s")' % (moduleName, moduleName), moduleName, 'exec')
|
||||||
|
code = marshal.dumps(code)
|
||||||
|
moduleList.append(make_module_list_entry(code, codeOffset, moduleName, module))
|
||||||
|
moduleBlob += code
|
||||||
|
codeOffset += len(code)
|
||||||
|
elif '.' in moduleName:
|
||||||
|
# Nothing we can do about this case except warn the user they
|
||||||
|
# are in for some trouble.
|
||||||
|
print('WARNING: Python cannot import extension modules under '
|
||||||
|
'frozen Python packages; %s will be inaccessible. '
|
||||||
|
'passing either -l to link in extension modules or use '
|
||||||
|
'-x %s to exclude the entire package.' % (moduleName, moduleName.split('.')[0]))
|
||||||
|
|
||||||
|
# Build from pre-built binary stub
|
||||||
|
stub_path = os.path.join(os.path.dirname(ExecutionEnvironment.get_dtool_name()), '..', 'bin', 'deploy-stub')
|
||||||
|
with open(stub_path, 'rb') as f:
|
||||||
|
stubbin = f.read()
|
||||||
|
|
||||||
|
with open(target, 'wb') as f:
|
||||||
|
f.write(stubbin)
|
||||||
|
listoffset = f.tell()
|
||||||
|
for mod in moduleList:
|
||||||
|
f.write(mod)
|
||||||
|
modsoffset = f.tell()
|
||||||
|
f.write(moduleBlob)
|
||||||
|
f.write(struct.pack('<I', listoffset))
|
||||||
|
f.write(struct.pack('<I', modsoffset))
|
||||||
|
f.write(struct.pack('<I', len(moduleList)))
|
||||||
|
os.chmod(target, 0o755)
|
||||||
|
|
||||||
def makeModuleDef(self, mangledName, code):
|
def makeModuleDef(self, mangledName, code):
|
||||||
result = ''
|
result = ''
|
||||||
result += 'static unsigned char %s[] = {' % (mangledName)
|
result += 'static unsigned char %s[] = {' % (mangledName)
|
||||||
|
@ -1,96 +1,13 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import marshal
|
|
||||||
import os
|
|
||||||
import struct
|
|
||||||
|
|
||||||
from direct.showutil import FreezeTool
|
from direct.showutil import FreezeTool
|
||||||
import panda3d.core as p3d
|
|
||||||
|
|
||||||
def make_module_list_entry(code, offset, modulename, module):
|
|
||||||
size = len(code)
|
|
||||||
if getattr(module, "__path__", None):
|
|
||||||
# Indicate package by negative size
|
|
||||||
size = -size
|
|
||||||
return struct.pack('<256sIi', bytes(modulename, 'ascii'), offset, size)
|
|
||||||
|
|
||||||
def make_forbidden_module_list_entry(modulename):
|
|
||||||
return struct.pack('<256sIi', bytes(modulename, 'ascii'), 0, 0)
|
|
||||||
|
|
||||||
def get_modules(freezer):
|
|
||||||
# Now generate the actual export table.
|
|
||||||
moduleBlob = bytes()
|
|
||||||
codeOffset = 0
|
|
||||||
moduleList = []
|
|
||||||
|
|
||||||
for moduleName, mdef in freezer.getModuleDefs():
|
|
||||||
origName = mdef.moduleName
|
|
||||||
if mdef.forbid:
|
|
||||||
# Explicitly disallow importing this module.
|
|
||||||
moduleList.append(make_forbidden_module_list_entry(moduleName))
|
|
||||||
continue
|
|
||||||
|
|
||||||
assert not mdef.exclude
|
|
||||||
# Allow importing this module.
|
|
||||||
module = freezer.mf.modules.get(origName, None)
|
|
||||||
code = getattr(module, "__code__", None)
|
|
||||||
if code:
|
|
||||||
code = marshal.dumps(code)
|
|
||||||
moduleList.append(make_module_list_entry(code, codeOffset, moduleName, module))
|
|
||||||
moduleBlob += code
|
|
||||||
codeOffset += len(code)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# This is a module with no associated Python code. It is either
|
|
||||||
# an extension module or a builtin module. Get the filename, if
|
|
||||||
# it is the former.
|
|
||||||
extensionFilename = getattr(module, '__file__', None)
|
|
||||||
|
|
||||||
if extensionFilename or freezer.linkExtensionModules:
|
|
||||||
freezer.extras.append((moduleName, extensionFilename))
|
|
||||||
|
|
||||||
# If it is a submodule of a frozen module, Python will have
|
|
||||||
# trouble importing it as a builtin module. Synthesize a frozen
|
|
||||||
# module that loads it as builtin.
|
|
||||||
if '.' in moduleName and freezer.linkExtensionModules:
|
|
||||||
code = compile('import sys;del sys.modules["%s"];import imp;imp.init_builtin("%s")' % (moduleName, moduleName), moduleName, 'exec')
|
|
||||||
code = marshal.dumps(code)
|
|
||||||
moduleList.append(make_module_list_entry(code, codeOffset, moduleName, module))
|
|
||||||
moduleBlob += code
|
|
||||||
codeOffset += len(code)
|
|
||||||
elif '.' in moduleName:
|
|
||||||
# Nothing we can do about this case except warn the user they
|
|
||||||
# are in for some trouble.
|
|
||||||
print('WARNING: Python cannot import extension modules under '
|
|
||||||
'frozen Python packages; %s will be inaccessible. '
|
|
||||||
'passing either -l to link in extension modules or use '
|
|
||||||
'-x %s to exclude the entire package.' % (moduleName, moduleName.split('.')[0]))
|
|
||||||
|
|
||||||
return moduleBlob, moduleList
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
start_file = 'app.py'
|
||||||
|
basename = 'built_app_ng'
|
||||||
# Setup Freezer
|
# Setup Freezer
|
||||||
freezer = FreezeTool.Freezer()
|
freezer = FreezeTool.Freezer()
|
||||||
freezer.keepTemporaryFiles = True
|
freezer.keepTemporaryFiles = True
|
||||||
freezer.addModule('__main__', filename='app.py')
|
freezer.addModule('__main__', filename=start_file)
|
||||||
freezer.done(addStartupModules=True)
|
freezer.done(addStartupModules=True)
|
||||||
|
|
||||||
# Build from pre-built binary stub
|
freezer.generateRuntimeFromStub(basename)
|
||||||
stub_path = os.path.join(os.path.dirname(p3d.ExecutionEnvironment.get_dtool_name()), '..', 'bin', 'deploy-stub')
|
|
||||||
out_path = 'frozen_app'
|
|
||||||
with open(stub_path, 'rb') as f:
|
|
||||||
stubbin = f.read()
|
|
||||||
|
|
||||||
modblob, modlist = get_modules(freezer)
|
|
||||||
|
|
||||||
with open(out_path, 'wb') as f:
|
|
||||||
f.write(stubbin)
|
|
||||||
listoffset = f.tell()
|
|
||||||
for mod in modlist:
|
|
||||||
f.write(mod)
|
|
||||||
modsoffset = f.tell()
|
|
||||||
f.write(modblob)
|
|
||||||
f.write(struct.pack('<I', listoffset))
|
|
||||||
f.write(struct.pack('<I', modsoffset))
|
|
||||||
f.write(struct.pack('<I', len(modlist)))
|
|
||||||
os.chmod(out_path, 0o755)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user