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

Unified Diff: pnacl/driver/pnacl-nmf.py

Issue 9264026: Add support for generating nmfs for pnacl pexes with glibc (vs pnacl nexes). (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: add search path args for psos Created 8 years, 11 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 | « pnacl/driver/pnacl-meta.py ('k') | site_scons/site_tools/naclsdk.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pnacl/driver/pnacl-nmf.py
diff --git a/pnacl/driver/pnacl-nmf.py b/pnacl/driver/pnacl-nmf.py
new file mode 100755
index 0000000000000000000000000000000000000000..2b8169606dbf83eae5b976f7c2e6eff6abbf3c84
--- /dev/null
+++ b/pnacl/driver/pnacl-nmf.py
@@ -0,0 +1,175 @@
+#!/usr/bin/python
+# Copyright (c) 2012 The Native Client Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# IMPORTANT NOTE: If you make local mods to this file, you must run:
+# % pnacl/build.sh driver
+# in order for them to take effect in the scons build. This command
+# updates the copy in the toolchain/ tree.
+#
+
+# Generate a draft manifest file given bitcode pexe.
+# URLs and unknown runtime dependencies may be manually changed afterwards.
+
+from driver_tools import *
+from driver_env import env
+from driver_log import Log, DriverOpen, TempFiles
+from collections import deque
+
+try:
+ import json
+except Exception:
+ import simplejson as json
+
+EXTRA_ENV = {
+ 'INPUTS' : '',
+ 'OUTPUT' : '',
+
+ # FLAT_URL_SCHEME is '1' if we are just trying to test via scons and
+ # do not want to put libraries under any kind of directory structure
+ # to simplify file staging. This means that really only one of the files
+ # is valid, since all arches will have the same URL. This is only for tests.
+ 'FLAT_URL_SCHEME' : '0',
+
+ # Search path for finding pso's to grab transitive dependencies.
+ 'SEARCH_DIRS' : '${SEARCH_DIRS_USER} ${SEARCH_DIRS_BUILTIN}',
+ 'SEARCH_DIRS_USER' : '',
+ # This doesn't include native lib directories, so we aren't
+ # tracing transitive dependencies for those.
+ 'SEARCH_DIRS_BUILTIN': ' ${BASE_USR}/lib/ ' +
+ ' ${BASE_SDK}/lib/ ' +
+ ' ${BASE_LIB}/ ',
+}
+env.update(EXTRA_ENV)
+
+NMF_PATTERNS = [
+ ( ('-L', '(.+)'),
+ "env.append('SEARCH_DIRS_USER', pathtools.normalize($0))\n"),
+ ( '-L(.+)',
+ "env.append('SEARCH_DIRS_USER', pathtools.normalize($0))\n"),
+ ( '--library-path=(.+)',
+ "env.append('SEARCH_DIRS_USER', pathtools.normalize($0))\n"),
+
+ ( ('-o', '(.+)'), "env.set('OUTPUT', pathtools.normalize($0))\n"),
+ ( '--flat-url-scheme', "env.set('FLAT_URL_SCHEME', '1')"),
+
+ ( '(.*)', "env.append('INPUTS', pathtools.normalize($0))"),
+]
+
+def Usage():
+ print "Usage: pnacl-nmf <pexe_file> [-L=...]"
+ print "Generate a draft NMF file based on the given pexe file."
+
+def AddUrlForAllArches(json_dict, shortname):
+ # TODO(jvoung): We may want to calculate a hash to go with the URL.
+ KNOWN_NMF_ARCHES = ['x86-32', 'x86-64', 'arm']
+ for arch in KNOWN_NMF_ARCHES:
+ json_dict[arch] = {}
+ if env.getbool('FLAT_URL_SCHEME'):
+ json_dict[arch]['url'] = '%s' % shortname
+ else:
+ json_dict[arch]['url'] = 'lib-%s/%s' % (arch, shortname)
+
+def SetPortableUrl(json_dict, shortname):
+ # TODO(jvoung): We may want to calculate a hash to go with the URL.
+ json_dict['portable'] = {}
+ json_dict['portable']['url'] = shortname
+
+def GetActualFilePathAndType(shortname):
+ actual_lib_path = ldtools.FindFile([shortname], env.get('SEARCH_DIRS'))
+ if actual_lib_path == None:
+ Log.Warning('Could not find path of lib: %s, assuming it is native',
+ shortname)
+ file_type = 'so'
+ else:
+ file_type = FileType(actual_lib_path)
+ return actual_lib_path, file_type
+
+def GetTransitiveClosureOfNeeded(base_needed):
+ # TODO(jvoung): We may need to get the topological sort of depedencies.
+ visited_portable = set()
+ visited_native = set()
+ all_needed = set(base_needed)
+ worklist = deque(base_needed)
+ while len(worklist) != 0:
+ lib = worklist.popleft()
+ if lib in visited_portable or lib in visited_native:
+ continue
+ actual_lib_path, file_type = GetActualFilePathAndType(lib)
+ if file_type == 'so':
+ # We could trace if we used objdump / readelf...
+ Log.Warning('Not tracing dependencies of native lib %s', lib)
+ visited_native.add(lib)
+ continue
+ elif file_type == 'pso':
+ visited_portable.add(lib)
+ more_needed = GetBitcodeMetadata(actual_lib_path).get('NeedsLibrary', [])
+ all_needed |= set(more_needed)
+ worklist.extend(more_needed)
+ else:
+ Log.Fatal('Lib: %s is neither bitcode nor native', lib)
+ return all_needed
+
+
+def GenerateStaticNMF(pexe_file, output_file):
+ nmf_json = {}
+ nmf_json['program'] = {}
+ SetPortableUrl(nmf_json['program'], pathtools.basename(pexe_file))
+ json.dump(nmf_json, output_file, sort_keys=True, indent=2)
+
+
+def GenerateDynamicNMF(pexe_file, needed, output_file):
+ nmf_json = {}
+ # Set runnable-ld.so as the program interpreter.
+ nmf_json['program'] = {}
+ AddUrlForAllArches(nmf_json['program'], 'runnable-ld.so')
+ # Set the pexe as the main program.
+ nmf_json['files'] = {}
+ nmf_json['files']['main.nexe'] = {}
+ SetPortableUrl(nmf_json['files']['main.nexe'], pathtools.basename(pexe_file))
+
+ # Get transitive closure of needed libraries.
+ transitive_needed = GetTransitiveClosureOfNeeded(needed)
+
+ # Make urls for libraries.
+ for lib in transitive_needed:
+ nmf_json['files'][lib] = {}
+ actual_lib_path, file_type = GetActualFilePathAndType(lib)
+ if file_type == 'so':
+ # Assume a native version exists for every known arch.
+ AddUrlForAllArches(nmf_json['files'][lib], lib)
+ elif file_type == 'pso':
+ SetPortableUrl(nmf_json['files'][lib], lib)
+ else:
+ Log.Fatal('Needed library is not a .so nor a .pso')
+ json.dump(nmf_json, output_file, sort_keys=True, indent=2)
+
+
+def main(argv):
+ ParseArgs(argv, NMF_PATTERNS)
+ inputs = env.get('INPUTS')
+
+ if not inputs or len(inputs) != 1:
+ Usage()
+ DriverExit(0)
+ pexe_file = inputs[0]
+ output = env.getone('OUTPUT')
+ if output == '':
+ output_file = sys.stdout
+ else:
+ output_file = DriverOpen(output, 'w')
+
+ if not FileType(pexe_file) == 'pexe':
+ Log.Fatal("File %s is not an executable bitcode file",
+ pathtools.touser(pexe_file))
+ needed = GetBitcodeMetadata(pexe_file).get('NeedsLibrary', [])
+ if len(needed) == 0:
+ GenerateStaticNMF(pexe_file, output_file)
+ else:
+ GenerateDynamicNMF(pexe_file, needed, output_file)
+ DriverClose(output_file)
+ return 0
+
+if __name__ == "__main__":
+ DriverMain(main)
« no previous file with comments | « pnacl/driver/pnacl-meta.py ('k') | site_scons/site_tools/naclsdk.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698