Add code to automatically pick up dependent assemblies and their dependent files

This commit is contained in:
rdb 2009-12-25 17:39:47 +00:00
parent 79b6b53d32
commit 940265ffcb

View File

@ -770,8 +770,8 @@ class Packager:
def __addImplicitDependenciesWindows(self): def __addImplicitDependenciesWindows(self):
""" Walks through the list of files, looking for dll's and """ Walks through the list of files, looking for dll's and
exe's that might include implicit dependencies on other exe's that might include implicit dependencies on other
dll's. Tries to determine those dependencies, and adds dll's and assembly manifests. Tries to determine those
them back into the filelist. """ dependencies, and adds them back into the filelist. """
# We walk through the list as we modify it. That's OK, # We walk through the list as we modify it. That's OK,
# because we want to follow the transitive closure of # because we want to follow the transitive closure of
@ -784,22 +784,53 @@ class Packager:
# Skip this file. # Skip this file.
continue continue
tempFile = Filename.temporary('', 'p3d_', '.txt') if file.filename.getExtension().lower() == "manifest":
command = 'dumpbin /dependents "%s" >"%s"' % ( filenames = self.__parseManifest(file.filename)
file.filename.toOsSpecific(), print file.filename, filenames
tempFile.toOsSpecific()) if filenames is None:
try: self.notify.warning("Unable to determine dependent assemblies from %s" % (file.filename))
os.system(command) continue
except:
pass else:
filenames = None tempFile = Filename.temporary('', 'p3d_', '.txt')
command = 'dumpbin /dependents "%s" >"%s"' % (
file.filename.toOsSpecific(),
tempFile.toOsSpecific())
try:
os.system(command)
except:
pass
filenames = None
if tempFile.exists(): if tempFile.exists():
filenames = self.__parseDependenciesWindows(tempFile) filenames = self.__parseDependenciesWindows(tempFile)
tempFile.unlink() tempFile.unlink()
if filenames is None: if filenames is None:
self.notify.warning("Unable to determine dependencies from %s" % (file.filename)) self.notify.warning("Unable to determine dependencies from %s" % (file.filename))
continue continue
# Extract the manifest file so we can figure out the dependent assemblies.
tempFile = Filename.temporary('', 'p3d_', '.manifest')
resindex = 2
if file.filename.getExtension().lower() == "exe":
resindex = 1
command = 'mt -inputresource:"%s";#%d -out:"%s" > nul' % (
file.filename.toOsSpecific(),
resindex, tempFile.toOsSpecific())
try:
out = os.system(command)
except:
pass
afilenames = None
if tempFile.exists():
afilenames = self.__parseManifest(tempFile)
tempFile.unlink()
if afilenames is None and out != 31:
self.notify.warning("Unable to determine dependent assemblies from %s" % (file.filename))
continue
if afilenames is not None:
filenames += afilenames
# Attempt to resolve the dependent filename relative # Attempt to resolve the dependent filename relative
# to the original filename, before we resolve it along # to the original filename, before we resolve it along
@ -851,7 +882,41 @@ class Packager:
# At least we got some data. # At least we got some data.
return filenames return filenames
def __parseManifest(self, tempFile):
""" Reads the indicated application manifest file, to
determine the list of dependent assemblies this
executable file depends on. """
doc = TiXmlDocument(tempFile.toOsSpecific())
if not doc.LoadFile():
return None
assembly = doc.FirstChildElement("assembly")
if not assembly:
return None
# Pick up assemblies that it depends on
filenames = []
dependency = assembly.FirstChildElement("dependency")
while dependency:
ident = dependency.FirstChildElement("dependentAssembly").FirstChildElement("assemblyIdentity")
if ident:
name = ident.Attribute("name")
if name:
filenames.append(name + ".manifest")
dependency = dependency.NextSiblingElement("dependency")
# Pick up direct dll dependencies that it lists
dfile = assembly.FirstChildElement("file")
while dfile:
name = dfile.Attribute("name")
if name:
filenames.append(name)
dfile = dfile.NextSiblingElement("file")
return filenames
def __locateFrameworkLibrary(self, library): def __locateFrameworkLibrary(self, library):
""" Locates the given library inside its framework on the """ Locates the given library inside its framework on the
default framework paths, and returns its location as Filename. """ default framework paths, and returns its location as Filename. """