Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1048)

Unified Diff: native_client_sdk/src/tools/create_nmf.py

Issue 15891011: [NaCl SDK] Fix create_nmf handling of missing libraries. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | native_client_sdk/src/tools/tests/create_nmf_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: native_client_sdk/src/tools/create_nmf.py
diff --git a/native_client_sdk/src/tools/create_nmf.py b/native_client_sdk/src/tools/create_nmf.py
index 6ca83abbf574c8e0d5e8014d695706965213b31b..48b124bff39785ad8bad35faf37242f6441fc2f3 100755
--- a/native_client_sdk/src/tools/create_nmf.py
+++ b/native_client_sdk/src/tools/create_nmf.py
@@ -190,7 +190,7 @@ class ArchFile(object):
self.path = path
self.url = url
self.arch = arch
- if arch is None:
+ if not arch:
self.arch = ParseElfHeader(path)[0]
def __repr__(self):
@@ -235,15 +235,23 @@ class NmfUtils(object):
self.remap = remap or {}
self.pnacl = main_files and main_files[0].endswith('pexe')
- def GleanFromObjdump(self, files):
+ for filename in self.main_files:
+ if not os.path.exists(filename):
+ raise Error('Input file not found: %s' % filename)
+ if not os.path.isfile(filename):
+ raise Error('Input is not a file: %s' % filename)
+
+ def GleanFromObjdump(self, files, arch):
'''Get architecture and dependency information for given files
Args:
- files: A dict with key=filename and value=list or set of archs. E.g.:
- { '/path/to/my.nexe': ['x86-32']
- '/path/to/lib64/libmy.so': ['x86-64'],
- '/path/to/mydata.so': ['x86-32', 'x86-64'],
- '/path/to/my.data': None } # Indicates all architectures
+ files: A list of files to examine.
+ [ '/path/to/my.nexe',
+ '/path/to/lib64/libmy.so',
+ '/path/to/mydata.so',
+ '/path/to/my.data' ]
+ arch: The architecure we are looking for, or None to accept any
+ architecture.
Returns: A tuple with the following members:
input_info: A dict with key=filename and value=ArchFile of input files.
@@ -257,11 +265,22 @@ class NmfUtils(object):
self.objdump = FindObjdumpExecutable()
if not self.objdump:
raise Error('No objdump executable found (see --help for more info)')
- DebugPrint('GleanFromObjdump(%s)' % ([self.objdump, '-p'] + files.keys()))
- proc = subprocess.Popen([self.objdump, '-p'] + files.keys(),
- stdout=subprocess.PIPE,
+
+ full_paths = set()
+ for filename in files:
+ if os.path.exists(filename):
+ full_paths.add(filename)
+ else:
+ for path in self.FindLibsInPath(filename):
+ full_paths.add(path)
+
+ cmd = [self.objdump, '-p'] + list(full_paths)
+ DebugPrint('GleanFromObjdump[%s](%s)' % (arch, cmd))
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, bufsize=-1)
+
input_info = {}
+ found_basenames = {}
binji 2013/05/28 22:52:41 = set(), you never use the value
Sam Clegg 2013/05/28 23:04:40 Its used below, unless I'm misunderstanding.
needed = set()
output, err_output = proc.communicate()
if proc.returncode:
@@ -274,18 +293,27 @@ class NmfUtils(object):
matched = FormatMatcher.match(line)
if matched:
filename = matched.group(1)
- arch = OBJDUMP_ARCH_MAP[matched.group(2)]
- if files[filename] is None or arch in files[filename]:
- name = os.path.basename(filename)
- input_info[filename] = ArchFile(
- arch=arch,
- name=name,
- path=filename,
- url='/'.join(self.lib_prefix + [ARCH_LOCATION[arch], name]))
+ file_arch = OBJDUMP_ARCH_MAP[matched.group(2)]
+ if arch and file_arch != arch:
+ continue
+ name = os.path.basename(filename)
+ found_basenames[name] = True
+ input_info[filename] = ArchFile(
+ arch=file_arch,
+ name=name,
+ path=filename,
+ url='/'.join(self.lib_prefix + [ARCH_LOCATION[file_arch], name]))
matched = NeededMatcher.match(line)
if matched:
- if files[filename] is None or arch in files[filename]:
- needed.add('/'.join([arch, matched.group(1)]))
+ if not arch or arch == file_arch:
binji 2013/05/28 22:52:41 might be nicer to use not(arch and arch != file_ar
binji 2013/05/28 22:52:41 now that I look at it closer, where is file_arch c
Sam Clegg 2013/05/28 23:04:40 Just removed this condition as the continue above
+ match = '/'.join([file_arch, matched.group(1)])
+ needed.add(match)
+ Trace("NEEDED: %s" % match)
+
+ for filename in files:
+ if os.path.basename(filename) not in found_basenames:
+ raise Error('Library not found [%s]: %s' % (arch, filename))
binji 2013/05/28 22:52:41 seems like it would be useful to know which object
Sam Clegg 2013/05/28 23:04:40 Maybe. That would require another re-factor sinc
+
return input_info, needed
def FindLibsInPath(self, name):
@@ -323,28 +351,36 @@ class NmfUtils(object):
if dynamic:
examined = set()
- all_files, unexamined = self.GleanFromObjdump(
- dict([(f, None) for f in self.main_files]))
- for name, arch_file in all_files.items():
- arch_file.url = name
+ all_files, unexamined = self.GleanFromObjdump(self.main_files, None)
+ for arch_file in all_files.itervalues():
+ arch_file.url = arch_file.path
if unexamined:
unexamined.add('/'.join([arch_file.arch, RUNNABLE_LD]))
+
while unexamined:
files_to_examine = {}
+
+ # Take all the currently unexamined files and group them
+ # by architecture.
for arch_name in unexamined:
arch, name = arch_name.split('/')
- for path in self.FindLibsInPath(name):
- files_to_examine.setdefault(path, set()).add(arch)
- new_files, needed = self.GleanFromObjdump(files_to_examine)
- all_files.update(new_files)
+ files_to_examine.setdefault(arch, []).append(name)
+
+ # Call GleanFromObjdump() for each architecture.
+ needed = set()
+ for arch, files in files_to_examine.iteritems():
+ new_files, new_needed = self.GleanFromObjdump(files, arch)
+ all_files.update(new_files)
+ needed |= new_needed
+
examined |= unexamined
unexamined = needed - examined
# With the runnable-ld.so scheme we have today, the proper name of
# the dynamic linker should be excluded from the list of files.
ldso = [LD_NACL_MAP[arch] for arch in set(OBJDUMP_ARCH_MAP.values())]
- for name, arch_map in all_files.items():
- if arch_map.name in ldso:
+ for name, arch_file in all_files.items():
+ if arch_file.name in ldso:
del all_files[name]
self.needed = all_files
@@ -369,8 +405,9 @@ class NmfUtils(object):
nexe_root = os.path.normcase(nexe_root)
needed = self.GetNeeded()
- for source, arch_file in needed.items():
+ for arch_file in needed.itervalues():
urldest = arch_file.url
+ source = arch_file.path
# for .nexe and .so files specified on the command line stage
# them in paths relative to the .nexe (with the .nexe always
@@ -596,7 +633,7 @@ def main(argv):
help='Override the default "objdump" tool used to find '
'shared object dependencies',
metavar='TOOL')
- parser.add_option('--no-default-libpath',
+ parser.add_option('--no-default-libpath', action='store_true',
help="Don't include the SDK default library paths")
parser.add_option('--debug-libs', action='store_true',
help='Use debug library paths when constructing default '
@@ -635,12 +672,6 @@ def main(argv):
if len(args) < 1:
raise Error('No nexe files specified. See --help for more info')
- for filename in args:
- if not os.path.exists(filename):
- raise Error('Input file not found: %s' % filename)
- if not os.path.isfile(filename):
- raise Error('Input is not a file: %s' % filename)
-
canonicalized = ParseExtraFiles(options.extra_files, sys.stderr)
if canonicalized is None:
parser.error('Bad --extra-files (-x) argument syntax')
@@ -657,6 +688,12 @@ def main(argv):
else:
path_prefix = []
+ for libpath in options.lib_path:
+ if not os.path.exists(libpath):
+ raise Error('Specified library path does not exist: %s' % libpath)
+ if not os.path.isdir(libpath):
+ raise Error('Specified library is not a directory: %s' % libpath)
+
if not options.no_default_libpath:
# Add default libraries paths to the end of the search path.
config = options.debug_libs and 'Debug' or 'Release'
@@ -670,7 +707,7 @@ def main(argv):
remap=remap)
nmf.GetManifest()
- if options.output is None:
+ if not options.output:
sys.stdout.write(nmf.GetJson())
else:
with open(options.output, 'w') as output:
« no previous file with comments | « no previous file | native_client_sdk/src/tools/tests/create_nmf_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698