mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 17:35:34 -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.
|
||||
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
|
||||
# be directly manipulated by callers.
|
||||
self.previousModules = {}
|
||||
@ -837,6 +844,19 @@ class Freezer:
|
||||
if module:
|
||||
# Get the compiled code directly from the module object.
|
||||
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:
|
||||
# Read the code from the source file and compile it on-the-fly.
|
||||
if sourceFilename and sourceFilename.exists():
|
||||
@ -849,7 +869,8 @@ class Freezer:
|
||||
|
||||
def addToMultifile(self, multifile, compressionLevel = 0):
|
||||
""" 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 = {}
|
||||
for moduleName, mdef in self.getModuleDefs():
|
||||
@ -860,7 +881,8 @@ class Freezer:
|
||||
def writeMultifile(self, mfname):
|
||||
""" After a call to done(), this stores all of the accumulated
|
||||
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()
|
||||
|
||||
@ -881,10 +903,9 @@ class Freezer:
|
||||
false). The basename is the name of the file to write,
|
||||
without the extension.
|
||||
|
||||
The return value is the tuple (filename, extras) where
|
||||
filename is the newly-generated filename, including the
|
||||
filename extension, and extras is a list of (moduleName,
|
||||
filename), for extension modules. """
|
||||
The return value is the newly-generated filename, including
|
||||
the filename extension. Additional extension modules are
|
||||
listed in self.extras. """
|
||||
|
||||
if compileToExe:
|
||||
# We must have a __main__ module to make an exe file.
|
||||
@ -897,7 +918,6 @@ class Freezer:
|
||||
# Now generate the actual export table.
|
||||
moduleDefs = []
|
||||
moduleList = []
|
||||
extras = []
|
||||
|
||||
for moduleName, mdef in self.getModuleDefs():
|
||||
token = mdef.token
|
||||
@ -932,11 +952,11 @@ class Freezer:
|
||||
else:
|
||||
|
||||
# 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 = getattr(module, '__file__', None)
|
||||
if filename:
|
||||
extras.append((moduleName, 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
|
||||
@ -994,7 +1014,7 @@ class Freezer:
|
||||
if (os.path.exists(basename + self.objectExtension)):
|
||||
os.unlink(basename + self.objectExtension)
|
||||
|
||||
return (target, extras)
|
||||
return target
|
||||
|
||||
def compileExe(self, filename, basename):
|
||||
compile = self.compileObj % {
|
||||
|
@ -83,6 +83,44 @@ class Packager:
|
||||
for moduleName in self.skipModules.keys():
|
||||
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
|
||||
# discovered.
|
||||
self.sourceFilenames = {}
|
||||
@ -104,10 +142,13 @@ class Packager:
|
||||
self.targetFilenames[file.newName] = 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:
|
||||
ext = file.filename.getExtension()
|
||||
if ext == 'py':
|
||||
self.addPyFile(file)
|
||||
# Already handled, above.
|
||||
pass
|
||||
elif not self.dryRun:
|
||||
if ext == 'pz':
|
||||
# Strip off an implicit .pz extension.
|
||||
@ -131,36 +172,18 @@ class Packager:
|
||||
# Any other 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,
|
||||
# (and set our platform if necessary), we can generate the
|
||||
# output filename and write the output files.
|
||||
|
||||
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'
|
||||
for p2 in self.requires:
|
||||
if p2.version:
|
||||
self.version = p2.version
|
||||
break
|
||||
|
||||
self.packageBasename = self.packageName
|
||||
packageDir = self.packageName
|
||||
@ -189,7 +212,6 @@ class Packager:
|
||||
self.packageFullpath.unlink()
|
||||
|
||||
if not self.dryRun:
|
||||
self.freezer.addToMultifile(self.multifile, self.compressionLevel)
|
||||
if self.p3dApplication:
|
||||
self.makeP3dInfo()
|
||||
self.multifile.repack()
|
||||
@ -208,6 +230,27 @@ class Packager:
|
||||
if file.deleteTemp:
|
||||
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):
|
||||
""" Makes the p3d_info.xml file that defines the
|
||||
application startup parameters and such. """
|
||||
@ -278,7 +321,7 @@ class Packager:
|
||||
for package in self.requires:
|
||||
xrequires = TiXmlElement('requires')
|
||||
xrequires.SetAttribute('name', package.packageName)
|
||||
if package.platform:
|
||||
if self.platform and package.platform:
|
||||
xrequires.SetAttribute('platform', package.platform)
|
||||
if package.version:
|
||||
xrequires.SetAttribute('version', package.version)
|
||||
@ -315,7 +358,7 @@ class Packager:
|
||||
for package in self.requires:
|
||||
xrequires = TiXmlElement('requires')
|
||||
xrequires.SetAttribute('name', package.packageName)
|
||||
if package.platform:
|
||||
if self.platform and package.platform:
|
||||
xrequires.SetAttribute('platform', package.platform)
|
||||
if package.version:
|
||||
xrequires.SetAttribute('version', package.version)
|
||||
@ -635,10 +678,10 @@ class Packager:
|
||||
self.binaryExtensions = [ 'ttf', 'wav', 'mid' ]
|
||||
|
||||
# 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.
|
||||
self.platformSpecificExtensions = [ 'dll', 'so', 'dylib', 'exe' ]
|
||||
self.platformSpecificExtensions = [ 'dll', 'pyd', 'so', 'dylib', 'exe' ]
|
||||
|
||||
# Binary files that are considered uncompressible, and are
|
||||
# copied without compression.
|
||||
@ -978,6 +1021,24 @@ class Packager:
|
||||
|
||||
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):
|
||||
"""
|
||||
main_module moduleName
|
||||
@ -1353,6 +1414,14 @@ class Packager:
|
||||
|
||||
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):
|
||||
""" Names the indicated module as the "main" module of the
|
||||
application or exe. """
|
||||
@ -1400,17 +1469,10 @@ class Packager:
|
||||
dirname, basename = filename.rsplit('/', 1)
|
||||
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))
|
||||
for moduleName, filename in extras:
|
||||
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))
|
||||
|
||||
package.addExtensionModules()
|
||||
if not package.platform:
|
||||
package.platform = PandaSystem.getPlatform()
|
||||
|
||||
@ -1418,7 +1480,6 @@ class Packager:
|
||||
freezer.reset()
|
||||
package.mainModule = None
|
||||
|
||||
|
||||
def file(self, filename, newNameOrDir = None, extract = None):
|
||||
""" Adds the indicated arbitrary file to the current package.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user