mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -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 imp
|
||||
import platform
|
||||
import struct
|
||||
from io import StringIO
|
||||
import distutils.sysconfig as sysconf
|
||||
|
||||
@ -1549,6 +1550,93 @@ class Freezer:
|
||||
|
||||
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):
|
||||
result = ''
|
||||
result += 'static unsigned char %s[] = {' % (mangledName)
|
||||
|
@ -1,96 +1,13 @@
|
||||
#!/usr/bin/env python
|
||||
import marshal
|
||||
import os
|
||||
import struct
|
||||
|
||||
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__':
|
||||
start_file = 'app.py'
|
||||
basename = 'built_app_ng'
|
||||
# Setup Freezer
|
||||
freezer = FreezeTool.Freezer()
|
||||
freezer.keepTemporaryFiles = True
|
||||
freezer.addModule('__main__', filename='app.py')
|
||||
freezer.addModule('__main__', filename=start_file)
|
||||
freezer.done(addStartupModules=True)
|
||||
|
||||
# Build from pre-built binary stub
|
||||
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)
|
||||
freezer.generateRuntimeFromStub(basename)
|
||||
|
Loading…
x
Reference in New Issue
Block a user