Chromium Code Reviews| 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: |