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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pnacl/driver/pnacl-meta.py ('k') | site_scons/site_tools/naclsdk.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5 #
6 # IMPORTANT NOTE: If you make local mods to this file, you must run:
7 # % pnacl/build.sh driver
8 # in order for them to take effect in the scons build. This command
9 # updates the copy in the toolchain/ tree.
10 #
11
12 # Generate a draft manifest file given bitcode pexe.
13 # URLs and unknown runtime dependencies may be manually changed afterwards.
14
15 from driver_tools import *
16 from driver_env import env
17 from driver_log import Log, DriverOpen, TempFiles
18 from collections import deque
19
20 try:
21 import json
22 except Exception:
23 import simplejson as json
24
25 EXTRA_ENV = {
26 'INPUTS' : '',
27 'OUTPUT' : '',
28
29 # FLAT_URL_SCHEME is '1' if we are just trying to test via scons and
30 # do not want to put libraries under any kind of directory structure
31 # to simplify file staging. This means that really only one of the files
32 # is valid, since all arches will have the same URL. This is only for tests.
33 'FLAT_URL_SCHEME' : '0',
34
35 # Search path for finding pso's to grab transitive dependencies.
36 'SEARCH_DIRS' : '${SEARCH_DIRS_USER} ${SEARCH_DIRS_BUILTIN}',
37 'SEARCH_DIRS_USER' : '',
38 # This doesn't include native lib directories, so we aren't
39 # tracing transitive dependencies for those.
40 'SEARCH_DIRS_BUILTIN': ' ${BASE_USR}/lib/ ' +
41 ' ${BASE_SDK}/lib/ ' +
42 ' ${BASE_LIB}/ ',
43 }
44 env.update(EXTRA_ENV)
45
46 NMF_PATTERNS = [
47 ( ('-L', '(.+)'),
48 "env.append('SEARCH_DIRS_USER', pathtools.normalize($0))\n"),
49 ( '-L(.+)',
50 "env.append('SEARCH_DIRS_USER', pathtools.normalize($0))\n"),
51 ( '--library-path=(.+)',
52 "env.append('SEARCH_DIRS_USER', pathtools.normalize($0))\n"),
53
54 ( ('-o', '(.+)'), "env.set('OUTPUT', pathtools.normalize($0))\n"),
55 ( '--flat-url-scheme', "env.set('FLAT_URL_SCHEME', '1')"),
56
57 ( '(.*)', "env.append('INPUTS', pathtools.normalize($0))"),
58 ]
59
60 def Usage():
61 print "Usage: pnacl-nmf <pexe_file> [-L=...]"
62 print "Generate a draft NMF file based on the given pexe file."
63
64 def AddUrlForAllArches(json_dict, shortname):
65 # TODO(jvoung): We may want to calculate a hash to go with the URL.
66 KNOWN_NMF_ARCHES = ['x86-32', 'x86-64', 'arm']
67 for arch in KNOWN_NMF_ARCHES:
68 json_dict[arch] = {}
69 if env.getbool('FLAT_URL_SCHEME'):
70 json_dict[arch]['url'] = '%s' % shortname
71 else:
72 json_dict[arch]['url'] = 'lib-%s/%s' % (arch, shortname)
73
74 def SetPortableUrl(json_dict, shortname):
75 # TODO(jvoung): We may want to calculate a hash to go with the URL.
76 json_dict['portable'] = {}
77 json_dict['portable']['url'] = shortname
78
79 def GetActualFilePathAndType(shortname):
80 actual_lib_path = ldtools.FindFile([shortname], env.get('SEARCH_DIRS'))
81 if actual_lib_path == None:
82 Log.Warning('Could not find path of lib: %s, assuming it is native',
83 shortname)
84 file_type = 'so'
85 else:
86 file_type = FileType(actual_lib_path)
87 return actual_lib_path, file_type
88
89 def GetTransitiveClosureOfNeeded(base_needed):
90 # TODO(jvoung): We may need to get the topological sort of depedencies.
91 visited_portable = set()
92 visited_native = set()
93 all_needed = set(base_needed)
94 worklist = deque(base_needed)
95 while len(worklist) != 0:
96 lib = worklist.popleft()
97 if lib in visited_portable or lib in visited_native:
98 continue
99 actual_lib_path, file_type = GetActualFilePathAndType(lib)
100 if file_type == 'so':
101 # We could trace if we used objdump / readelf...
102 Log.Warning('Not tracing dependencies of native lib %s', lib)
103 visited_native.add(lib)
104 continue
105 elif file_type == 'pso':
106 visited_portable.add(lib)
107 more_needed = GetBitcodeMetadata(actual_lib_path).get('NeedsLibrary', [])
108 all_needed |= set(more_needed)
109 worklist.extend(more_needed)
110 else:
111 Log.Fatal('Lib: %s is neither bitcode nor native', lib)
112 return all_needed
113
114
115 def GenerateStaticNMF(pexe_file, output_file):
116 nmf_json = {}
117 nmf_json['program'] = {}
118 SetPortableUrl(nmf_json['program'], pathtools.basename(pexe_file))
119 json.dump(nmf_json, output_file, sort_keys=True, indent=2)
120
121
122 def GenerateDynamicNMF(pexe_file, needed, output_file):
123 nmf_json = {}
124 # Set runnable-ld.so as the program interpreter.
125 nmf_json['program'] = {}
126 AddUrlForAllArches(nmf_json['program'], 'runnable-ld.so')
127 # Set the pexe as the main program.
128 nmf_json['files'] = {}
129 nmf_json['files']['main.nexe'] = {}
130 SetPortableUrl(nmf_json['files']['main.nexe'], pathtools.basename(pexe_file))
131
132 # Get transitive closure of needed libraries.
133 transitive_needed = GetTransitiveClosureOfNeeded(needed)
134
135 # Make urls for libraries.
136 for lib in transitive_needed:
137 nmf_json['files'][lib] = {}
138 actual_lib_path, file_type = GetActualFilePathAndType(lib)
139 if file_type == 'so':
140 # Assume a native version exists for every known arch.
141 AddUrlForAllArches(nmf_json['files'][lib], lib)
142 elif file_type == 'pso':
143 SetPortableUrl(nmf_json['files'][lib], lib)
144 else:
145 Log.Fatal('Needed library is not a .so nor a .pso')
146 json.dump(nmf_json, output_file, sort_keys=True, indent=2)
147
148
149 def main(argv):
150 ParseArgs(argv, NMF_PATTERNS)
151 inputs = env.get('INPUTS')
152
153 if not inputs or len(inputs) != 1:
154 Usage()
155 DriverExit(0)
156 pexe_file = inputs[0]
157 output = env.getone('OUTPUT')
158 if output == '':
159 output_file = sys.stdout
160 else:
161 output_file = DriverOpen(output, 'w')
162
163 if not FileType(pexe_file) == 'pexe':
164 Log.Fatal("File %s is not an executable bitcode file",
165 pathtools.touser(pexe_file))
166 needed = GetBitcodeMetadata(pexe_file).get('NeedsLibrary', [])
167 if len(needed) == 0:
168 GenerateStaticNMF(pexe_file, output_file)
169 else:
170 GenerateDynamicNMF(pexe_file, needed, output_file)
171 DriverClose(output_file)
172 return 0
173
174 if __name__ == "__main__":
175 DriverMain(main)
OLDNEW
« 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