mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
add extension modules
This commit is contained in:
parent
efa3af6e46
commit
8e651c8f8e
@ -402,6 +402,13 @@ class Freezer:
|
|||||||
# or dll's; those are always stored with compiled code.
|
# or dll's; those are always stored with compiled code.
|
||||||
self.storePythonSource = False
|
self.storePythonSource = False
|
||||||
|
|
||||||
|
# This list will be filled in by generateCode() or
|
||||||
|
# addToMultifile(). It contains a list of all the extension
|
||||||
|
# modules that were discovered, which have not been added to
|
||||||
|
# the output. The list is a list of tuples of the form
|
||||||
|
# (moduleName, filename).
|
||||||
|
self.extras = []
|
||||||
|
|
||||||
# End of public interface. These remaining members should not
|
# End of public interface. These remaining members should not
|
||||||
# be directly manipulated by callers.
|
# be directly manipulated by callers.
|
||||||
self.previousModules = {}
|
self.previousModules = {}
|
||||||
@ -837,6 +844,19 @@ class Freezer:
|
|||||||
if module:
|
if module:
|
||||||
# Get the compiled code directly from the module object.
|
# Get the compiled code directly from the module object.
|
||||||
code = getattr(module, "__code__", None)
|
code = getattr(module, "__code__", None)
|
||||||
|
if not code:
|
||||||
|
# This is a module with no associated Python
|
||||||
|
# code. It must be an extension module. Get the
|
||||||
|
# filename.
|
||||||
|
extensionFilename = getattr(module, '__file__', None)
|
||||||
|
if extensionFilename:
|
||||||
|
self.extras.append((moduleName, extensionFilename))
|
||||||
|
else:
|
||||||
|
# It doesn't even have a filename; it must
|
||||||
|
# be a built-in module. No worries about
|
||||||
|
# this one, then.
|
||||||
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Read the code from the source file and compile it on-the-fly.
|
# Read the code from the source file and compile it on-the-fly.
|
||||||
if sourceFilename and sourceFilename.exists():
|
if sourceFilename and sourceFilename.exists():
|
||||||
@ -849,7 +869,8 @@ class Freezer:
|
|||||||
|
|
||||||
def addToMultifile(self, multifile, compressionLevel = 0):
|
def addToMultifile(self, multifile, compressionLevel = 0):
|
||||||
""" After a call to done(), this stores all of the accumulated
|
""" After a call to done(), this stores all of the accumulated
|
||||||
python code into the indicated Multifile. """
|
python code into the indicated Multifile. Additional
|
||||||
|
extension modules are listed in self.extras. """
|
||||||
|
|
||||||
moduleDirs = {}
|
moduleDirs = {}
|
||||||
for moduleName, mdef in self.getModuleDefs():
|
for moduleName, mdef in self.getModuleDefs():
|
||||||
@ -860,7 +881,8 @@ class Freezer:
|
|||||||
def writeMultifile(self, mfname):
|
def writeMultifile(self, mfname):
|
||||||
""" After a call to done(), this stores all of the accumulated
|
""" After a call to done(), this stores all of the accumulated
|
||||||
python code into a Multifile with the indicated filename,
|
python code into a Multifile with the indicated filename,
|
||||||
including the extension. """
|
including the extension. Additional extension modules are
|
||||||
|
listed in self.extras."""
|
||||||
|
|
||||||
self.__replacePaths()
|
self.__replacePaths()
|
||||||
|
|
||||||
@ -881,10 +903,9 @@ class Freezer:
|
|||||||
false). The basename is the name of the file to write,
|
false). The basename is the name of the file to write,
|
||||||
without the extension.
|
without the extension.
|
||||||
|
|
||||||
The return value is the tuple (filename, extras) where
|
The return value is the newly-generated filename, including
|
||||||
filename is the newly-generated filename, including the
|
the filename extension. Additional extension modules are
|
||||||
filename extension, and extras is a list of (moduleName,
|
listed in self.extras. """
|
||||||
filename), for extension modules. """
|
|
||||||
|
|
||||||
if compileToExe:
|
if compileToExe:
|
||||||
# We must have a __main__ module to make an exe file.
|
# We must have a __main__ module to make an exe file.
|
||||||
@ -897,7 +918,6 @@ class Freezer:
|
|||||||
# Now generate the actual export table.
|
# Now generate the actual export table.
|
||||||
moduleDefs = []
|
moduleDefs = []
|
||||||
moduleList = []
|
moduleList = []
|
||||||
extras = []
|
|
||||||
|
|
||||||
for moduleName, mdef in self.getModuleDefs():
|
for moduleName, mdef in self.getModuleDefs():
|
||||||
token = mdef.token
|
token = mdef.token
|
||||||
@ -932,11 +952,11 @@ class Freezer:
|
|||||||
else:
|
else:
|
||||||
|
|
||||||
# This is a module with no associated Python
|
# This is a module with no associated Python
|
||||||
# code. It must be a compiled file. Get the
|
# code. It must be an extension module. Get the
|
||||||
# filename.
|
# filename.
|
||||||
filename = getattr(module, '__file__', None)
|
extensionFilename = getattr(module, '__file__', None)
|
||||||
if filename:
|
if extensionFilename:
|
||||||
extras.append((moduleName, filename))
|
self.extras.append((moduleName, extensionFilename))
|
||||||
else:
|
else:
|
||||||
# It doesn't even have a filename; it must
|
# It doesn't even have a filename; it must
|
||||||
# be a built-in module. No worries about
|
# be a built-in module. No worries about
|
||||||
@ -994,7 +1014,7 @@ class Freezer:
|
|||||||
if (os.path.exists(basename + self.objectExtension)):
|
if (os.path.exists(basename + self.objectExtension)):
|
||||||
os.unlink(basename + self.objectExtension)
|
os.unlink(basename + self.objectExtension)
|
||||||
|
|
||||||
return (target, extras)
|
return target
|
||||||
|
|
||||||
def compileExe(self, filename, basename):
|
def compileExe(self, filename, basename):
|
||||||
compile = self.compileObj % {
|
compile = self.compileObj % {
|
||||||
|
@ -83,6 +83,44 @@ class Packager:
|
|||||||
for moduleName in self.skipModules.keys():
|
for moduleName in self.skipModules.keys():
|
||||||
self.freezer.excludeModule(moduleName)
|
self.freezer.excludeModule(moduleName)
|
||||||
|
|
||||||
|
# First, add the explicit py files. These get turned into
|
||||||
|
# Python modules.
|
||||||
|
for file in self.files:
|
||||||
|
if not file.newName:
|
||||||
|
file.newName = file.filename
|
||||||
|
if file.newName in self.skipFilenames:
|
||||||
|
# Skip this file.
|
||||||
|
continue
|
||||||
|
|
||||||
|
ext = file.filename.getExtension()
|
||||||
|
if ext == 'py':
|
||||||
|
self.addPyFile(file)
|
||||||
|
|
||||||
|
if not self.mainModule and self.p3dApplication:
|
||||||
|
message = 'No main_module specified for application %s' % (self.packageName)
|
||||||
|
raise PackagerError, message
|
||||||
|
if self.mainModule:
|
||||||
|
if self.mainModule not in self.freezer.modules:
|
||||||
|
self.freezer.addModule(self.mainModule)
|
||||||
|
|
||||||
|
# Add known module names.
|
||||||
|
self.moduleNames = {}
|
||||||
|
for moduleName in self.freezer.getAllModuleNames():
|
||||||
|
if moduleName == '__main__':
|
||||||
|
# Ignore this special case.
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.moduleNames[moduleName] = True
|
||||||
|
|
||||||
|
xmodule = TiXmlElement('module')
|
||||||
|
xmodule.SetAttribute('name', moduleName)
|
||||||
|
self.components.append(xmodule)
|
||||||
|
|
||||||
|
# Pick up any unfrozen Python files.
|
||||||
|
self.freezer.done()
|
||||||
|
self.freezer.addToMultifile(self.multifile, self.compressionLevel)
|
||||||
|
self.addExtensionModules()
|
||||||
|
|
||||||
# Build up a cross-reference of files we've already
|
# Build up a cross-reference of files we've already
|
||||||
# discovered.
|
# discovered.
|
||||||
self.sourceFilenames = {}
|
self.sourceFilenames = {}
|
||||||
@ -104,10 +142,13 @@ class Packager:
|
|||||||
self.targetFilenames[file.newName] = file
|
self.targetFilenames[file.newName] = file
|
||||||
processFiles.append(file)
|
processFiles.append(file)
|
||||||
|
|
||||||
|
# Now add all the real, non-Python files. This will
|
||||||
|
# include the extension modules we just discovered above.
|
||||||
for file in processFiles:
|
for file in processFiles:
|
||||||
ext = file.filename.getExtension()
|
ext = file.filename.getExtension()
|
||||||
if ext == 'py':
|
if ext == 'py':
|
||||||
self.addPyFile(file)
|
# Already handled, above.
|
||||||
|
pass
|
||||||
elif not self.dryRun:
|
elif not self.dryRun:
|
||||||
if ext == 'pz':
|
if ext == 'pz':
|
||||||
# Strip off an implicit .pz extension.
|
# Strip off an implicit .pz extension.
|
||||||
@ -131,36 +172,18 @@ class Packager:
|
|||||||
# Any other file.
|
# Any other file.
|
||||||
self.addComponent(file)
|
self.addComponent(file)
|
||||||
|
|
||||||
if not self.mainModule and self.p3dApplication:
|
|
||||||
message = 'No main_module specified for application %s' % (self.packageName)
|
|
||||||
raise PackagerError, message
|
|
||||||
if self.mainModule:
|
|
||||||
if self.mainModule not in self.freezer.modules:
|
|
||||||
self.freezer.addModule(self.mainModule)
|
|
||||||
|
|
||||||
# Pick up any unfrozen Python files.
|
|
||||||
self.freezer.done()
|
|
||||||
|
|
||||||
# Add known module names.
|
|
||||||
self.moduleNames = {}
|
|
||||||
for moduleName in self.freezer.getAllModuleNames():
|
|
||||||
if moduleName == '__main__':
|
|
||||||
# Ignore this special case.
|
|
||||||
continue
|
|
||||||
|
|
||||||
self.moduleNames[moduleName] = True
|
|
||||||
|
|
||||||
xmodule = TiXmlElement('module')
|
|
||||||
xmodule.SetAttribute('name', moduleName)
|
|
||||||
self.components.append(xmodule)
|
|
||||||
|
|
||||||
# Now that we've processed all of the component files,
|
# Now that we've processed all of the component files,
|
||||||
# (and set our platform if necessary), we can generate the
|
# (and set our platform if necessary), we can generate the
|
||||||
# output filename and write the output files.
|
# output filename and write the output files.
|
||||||
|
|
||||||
if not self.p3dApplication and not self.version:
|
if not self.p3dApplication and not self.version:
|
||||||
# We must have a version string for packages.
|
# We must have a version string for packages. Use the
|
||||||
|
# first versioned string on our require list.
|
||||||
self.version = '0.0'
|
self.version = '0.0'
|
||||||
|
for p2 in self.requires:
|
||||||
|
if p2.version:
|
||||||
|
self.version = p2.version
|
||||||
|
break
|
||||||
|
|
||||||
self.packageBasename = self.packageName
|
self.packageBasename = self.packageName
|
||||||
packageDir = self.packageName
|
packageDir = self.packageName
|
||||||
@ -189,7 +212,6 @@ class Packager:
|
|||||||
self.packageFullpath.unlink()
|
self.packageFullpath.unlink()
|
||||||
|
|
||||||
if not self.dryRun:
|
if not self.dryRun:
|
||||||
self.freezer.addToMultifile(self.multifile, self.compressionLevel)
|
|
||||||
if self.p3dApplication:
|
if self.p3dApplication:
|
||||||
self.makeP3dInfo()
|
self.makeP3dInfo()
|
||||||
self.multifile.repack()
|
self.multifile.repack()
|
||||||
@ -208,6 +230,27 @@ class Packager:
|
|||||||
if file.deleteTemp:
|
if file.deleteTemp:
|
||||||
file.filename.unlink()
|
file.filename.unlink()
|
||||||
|
|
||||||
|
def addExtensionModules(self):
|
||||||
|
""" Adds the extension modules detected by the freezer to
|
||||||
|
the current list of files. """
|
||||||
|
|
||||||
|
freezer = self.freezer
|
||||||
|
if freezer.extras:
|
||||||
|
if not self.platform:
|
||||||
|
self.platform = PandaSystem.getPlatform()
|
||||||
|
|
||||||
|
for moduleName, filename in freezer.extras:
|
||||||
|
filename = Filename.fromOsSpecific(filename)
|
||||||
|
newName = filename.getBasename()
|
||||||
|
if '.' in moduleName:
|
||||||
|
newName = '/'.join(moduleName.split('.')[:-1])
|
||||||
|
newName += '/' + filename.getBasename()
|
||||||
|
# Sometimes the PYTHONPATH has the wrong case in it.
|
||||||
|
filename.makeTrueCase()
|
||||||
|
self.files.append(Packager.PackFile(filename, newName = newName, extract = True))
|
||||||
|
freezer.extras = []
|
||||||
|
|
||||||
|
|
||||||
def makeP3dInfo(self):
|
def makeP3dInfo(self):
|
||||||
""" Makes the p3d_info.xml file that defines the
|
""" Makes the p3d_info.xml file that defines the
|
||||||
application startup parameters and such. """
|
application startup parameters and such. """
|
||||||
@ -278,7 +321,7 @@ class Packager:
|
|||||||
for package in self.requires:
|
for package in self.requires:
|
||||||
xrequires = TiXmlElement('requires')
|
xrequires = TiXmlElement('requires')
|
||||||
xrequires.SetAttribute('name', package.packageName)
|
xrequires.SetAttribute('name', package.packageName)
|
||||||
if package.platform:
|
if self.platform and package.platform:
|
||||||
xrequires.SetAttribute('platform', package.platform)
|
xrequires.SetAttribute('platform', package.platform)
|
||||||
if package.version:
|
if package.version:
|
||||||
xrequires.SetAttribute('version', package.version)
|
xrequires.SetAttribute('version', package.version)
|
||||||
@ -315,7 +358,7 @@ class Packager:
|
|||||||
for package in self.requires:
|
for package in self.requires:
|
||||||
xrequires = TiXmlElement('requires')
|
xrequires = TiXmlElement('requires')
|
||||||
xrequires.SetAttribute('name', package.packageName)
|
xrequires.SetAttribute('name', package.packageName)
|
||||||
if package.platform:
|
if self.platform and package.platform:
|
||||||
xrequires.SetAttribute('platform', package.platform)
|
xrequires.SetAttribute('platform', package.platform)
|
||||||
if package.version:
|
if package.version:
|
||||||
xrequires.SetAttribute('version', package.version)
|
xrequires.SetAttribute('version', package.version)
|
||||||
@ -635,10 +678,10 @@ class Packager:
|
|||||||
self.binaryExtensions = [ 'ttf', 'wav', 'mid' ]
|
self.binaryExtensions = [ 'ttf', 'wav', 'mid' ]
|
||||||
|
|
||||||
# Files that should be extracted to disk.
|
# Files that should be extracted to disk.
|
||||||
self.extractExtensions = [ 'dll', 'so', 'dylib', 'exe' ]
|
self.extractExtensions = [ 'dll', 'pyd', 'so', 'dylib', 'exe' ]
|
||||||
|
|
||||||
# Files that indicate a platform dependency.
|
# Files that indicate a platform dependency.
|
||||||
self.platformSpecificExtensions = [ 'dll', 'so', 'dylib', 'exe' ]
|
self.platformSpecificExtensions = [ 'dll', 'pyd', 'so', 'dylib', 'exe' ]
|
||||||
|
|
||||||
# Binary files that are considered uncompressible, and are
|
# Binary files that are considered uncompressible, and are
|
||||||
# copied without compression.
|
# copied without compression.
|
||||||
@ -978,6 +1021,24 @@ class Packager:
|
|||||||
|
|
||||||
self.module(moduleName, newName = newName)
|
self.module(moduleName, newName = newName)
|
||||||
|
|
||||||
|
def parse_exclude_module(self, words):
|
||||||
|
"""
|
||||||
|
exclude_module moduleName [forbid=1]
|
||||||
|
"""
|
||||||
|
newName = None
|
||||||
|
|
||||||
|
args = self.__parseArgs(words, ['extract'])
|
||||||
|
|
||||||
|
try:
|
||||||
|
command, moduleName = words
|
||||||
|
except ValueError:
|
||||||
|
raise ArgumentError
|
||||||
|
|
||||||
|
forbid = args.get('forbid', None)
|
||||||
|
if forbid is not None:
|
||||||
|
forbid = int(forbid)
|
||||||
|
self.excludeModule(moduleName, forbid = forbid)
|
||||||
|
|
||||||
def parse_main_module(self, words):
|
def parse_main_module(self, words):
|
||||||
"""
|
"""
|
||||||
main_module moduleName
|
main_module moduleName
|
||||||
@ -1353,6 +1414,14 @@ class Packager:
|
|||||||
|
|
||||||
self.currentPackage.freezer.addModule(moduleName, newName = newName)
|
self.currentPackage.freezer.addModule(moduleName, newName = newName)
|
||||||
|
|
||||||
|
def excludeModule(self, moduleName, forbid = False):
|
||||||
|
""" Marks the indicated Python module as not to be included. """
|
||||||
|
|
||||||
|
if not self.currentPackage:
|
||||||
|
raise OutsideOfPackageError
|
||||||
|
|
||||||
|
self.currentPackage.freezer.excludeModule(moduleName, forbid = forbid)
|
||||||
|
|
||||||
def mainModule(self, moduleName, newName = None):
|
def mainModule(self, moduleName, newName = None):
|
||||||
""" Names the indicated module as the "main" module of the
|
""" Names the indicated module as the "main" module of the
|
||||||
application or exe. """
|
application or exe. """
|
||||||
@ -1400,17 +1469,10 @@ class Packager:
|
|||||||
dirname, basename = filename.rsplit('/', 1)
|
dirname, basename = filename.rsplit('/', 1)
|
||||||
dirname += '/'
|
dirname += '/'
|
||||||
|
|
||||||
basename, extras = freezer.generateCode(basename, compileToExe = compileToExe)
|
basename = freezer.generateCode(basename, compileToExe = compileToExe)
|
||||||
|
|
||||||
package.files.append(self.PackFile(Filename(basename), newName = dirname + basename, deleteTemp = True, extract = True))
|
package.files.append(self.PackFile(Filename(basename), newName = dirname + basename, deleteTemp = True, extract = True))
|
||||||
for moduleName, filename in extras:
|
package.addExtensionModules()
|
||||||
filename = Filename.fromOsSpecific(filename)
|
|
||||||
newName = filename.getBasename()
|
|
||||||
if '.' in moduleName:
|
|
||||||
newName = '/'.join(moduleName.split('.')[:-1])
|
|
||||||
newName += '/' + filename.getBasename()
|
|
||||||
package.files.append(self.PackFile(filename, newName = newName, extract = True))
|
|
||||||
|
|
||||||
if not package.platform:
|
if not package.platform:
|
||||||
package.platform = PandaSystem.getPlatform()
|
package.platform = PandaSystem.getPlatform()
|
||||||
|
|
||||||
@ -1418,7 +1480,6 @@ class Packager:
|
|||||||
freezer.reset()
|
freezer.reset()
|
||||||
package.mainModule = None
|
package.mainModule = None
|
||||||
|
|
||||||
|
|
||||||
def file(self, filename, newNameOrDir = None, extract = None):
|
def file(self, filename, newNameOrDir = None, extract = None):
|
||||||
""" Adds the indicated arbitrary file to the current package.
|
""" Adds the indicated arbitrary file to the current package.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user