OLD | NEW |
| (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 import os | |
13 import re | |
14 | |
15 from driver_env import env as Env | |
16 from driver_log import Log | |
17 import driver_tools | |
18 | |
19 EXTRA_ENV = { | |
20 'INPUTS' : '', | |
21 'OUTPUT' : '', | |
22 | |
23 # bitcode linking flags - will be passed through to the pexe linking phase | |
24 'RELEVANT_FLAGS' : '', | |
25 'GENERATE_PIC' : '0', | |
26 | |
27 'MODE' : '', | |
28 | |
29 'LIB_PATHS' : '', | |
30 'LIBS' : '', | |
31 | |
32 'SONAME_FLAG' : '', | |
33 'OPT_FLAG' : '', | |
34 } | |
35 | |
36 RawRelevantArgs = [] | |
37 | |
38 RE_PATH = r'((?:-Wl,-rpath-link,|-L|-B).+)' | |
39 RE_LIB = r'(-l.+)' | |
40 | |
41 def RecordRelevantArg(category, value): | |
42 Env.append(category, value) | |
43 RawRelevantArgs.append(value) | |
44 | |
45 def RecordInput(value): | |
46 RecordRelevantArg('INPUTS', value) | |
47 | |
48 def RecordLib(value): | |
49 RecordRelevantArg('LIBS', value) | |
50 | |
51 def RecordPath(value): | |
52 RecordRelevantArg('LIB_PATHS', value) | |
53 | |
54 | |
55 ARG_PATTERNS = [ | |
56 ( ('-o','(.*)'), "env.set('OUTPUT', $0)"), | |
57 | |
58 ( RE_PATH, RecordPath), | |
59 ( RE_LIB, RecordLib), | |
60 | |
61 ( '(-l.+)', "env.append('RELEVANT_FLAGS', $0)"), | |
62 | |
63 ( '(-Wl,-soname,.+)', "env.append('SONAME_FLAG', $0)"), | |
64 ( '(-O.+)', "env.set('OPT_FLAGS_LINK', '$0')"), | |
65 | |
66 ( '-(dynamic|shared|static)', "env.set('MODE', $0)"), | |
67 | |
68 ( '-fPIC', "env.set('GENERATE_PIC', '1')"), | |
69 | |
70 ( '(-.*)', driver_tools.UnrecognizedOption), | |
71 | |
72 ( '(.*)', RecordInput), | |
73 ] | |
74 | |
75 | |
76 def ProcessBuildCommand(template): | |
77 result = [] | |
78 for t in template: | |
79 if type(t) == str: | |
80 s = driver_tools.env.eval(t) | |
81 if s: | |
82 result += [s] | |
83 # This is the more or less standard to test for a function | |
84 elif hasattr(t, '__call__'): | |
85 result += t() | |
86 else: | |
87 Log.Fatal('do now know how to process template member %s of type %s', | |
88 repr(t), type(t)) | |
89 return result | |
90 | |
91 | |
92 def DumpCommand(prefix, args): | |
93 for a in args: | |
94 print prefix + ": " + a | |
95 | |
96 # ====================================================================== | |
97 # -shared mode | |
98 # ====================================================================== | |
99 | |
100 def GetPsoTarget(): | |
101 out = Env.getone('OUTPUT') | |
102 if not out.endswith('.so'): | |
103 Log.Fatal('Unexpected target name %s', out) | |
104 return [out[:-2] + "pso"] | |
105 | |
106 | |
107 def GetPsoInputs(): | |
108 return Env.get('INPUTS') | |
109 | |
110 | |
111 BUILD_COMMAND_PSO_FROM_BC = [ | |
112 '--pnacl-driver-verbose', | |
113 '${OPT_FLAG}', | |
114 '${SONAME_FLAG}', | |
115 '-shared', | |
116 # for now force not dt_needed in .pso/.so | |
117 '-nodefaultlibs', | |
118 '-o', GetPsoTarget, | |
119 GetPsoInputs, | |
120 ] | |
121 | |
122 | |
123 BUILD_COMMAND_SO_FROM_PSO = [ | |
124 '--pnacl-driver-verbose', | |
125 '--newlib-shared-experiment', | |
126 '-shared', | |
127 '-fPIC', | |
128 '-arch', '${ARCH}', | |
129 '-o', '${OUTPUT}', | |
130 GetPsoTarget, | |
131 ] | |
132 | |
133 | |
134 def BuildSharedLib(): | |
135 # Shared libs must be built PIC | |
136 Env.set('GENERATE_PIC', '1') | |
137 inputs = Env.get('INPUTS') | |
138 if len(inputs) == 0: | |
139 Log.Fatal('No input specified.') | |
140 if not Env.getbool('GENERATE_PIC'): | |
141 Log.Fatal('Shared libs must be build in pic mode. Use -fPIC') | |
142 if Env.getone('SONAME_FLAG') == '': | |
143 Log.Fatal('Shared libs must be given a soname.') | |
144 | |
145 pso_command = ProcessBuildCommand(BUILD_COMMAND_PSO_FROM_BC) | |
146 DumpCommand("@bc->pso", pso_command) | |
147 # suppress_arch is needed to prevent clang to inherit the | |
148 # -arch argument | |
149 driver_tools.RunDriver('clang', pso_command, suppress_arch=True) | |
150 | |
151 so_command = ProcessBuildCommand(BUILD_COMMAND_SO_FROM_PSO) | |
152 DumpCommand("@pso->so", so_command) | |
153 driver_tools.RunDriver('translate', so_command) | |
154 | |
155 # ====================================================================== | |
156 # -static mode | |
157 # ====================================================================== | |
158 | |
159 def BuildStaticExecutable(): | |
160 Log.Fatal('PNaCl scons wrapper does not support static executables') | |
161 | |
162 # ====================================================================== | |
163 # -dynamic mode | |
164 # ====================================================================== | |
165 | |
166 def GetPexeTarget(): | |
167 out = Env.getone('OUTPUT') | |
168 if not out.endswith('.nexe'): | |
169 Log.Fatal('Unexpected target name %s', out) | |
170 return [out[:-4] + "pexe"] | |
171 | |
172 | |
173 def GetPexeInputsDynamic(): | |
174 return RawRelevantArgs | |
175 | |
176 | |
177 BUILD_COMMAND_PEXE_FROM_BC = [ | |
178 '--pnacl-driver-verbose', | |
179 '${OPT_FLAG}', | |
180 '-o', GetPexeTarget, | |
181 GetPexeInputsDynamic, | |
182 ] | |
183 | |
184 | |
185 BUILD_COMMAND_NEXE_FROM_PEXE = [ | |
186 '--pnacl-driver-verbose', | |
187 '-arch', '${ARCH}', | |
188 '--newlib-shared-experiment', | |
189 '-o', '${OUTPUT}', | |
190 GetPexeTarget, | |
191 ] | |
192 | |
193 def BuildDynamicExecutable(): | |
194 inputs = Env.get('INPUTS') | |
195 if len(inputs) != 1: | |
196 Log.Fatal('You must specify exactly on input for a dynamic executable.') | |
197 | |
198 pexe_command = ProcessBuildCommand(BUILD_COMMAND_PEXE_FROM_BC) | |
199 DumpCommand("@bc->pexe", pexe_command) | |
200 driver_tools.RunDriver('clang', pexe_command, suppress_arch=True) | |
201 | |
202 nexe_command = ProcessBuildCommand(BUILD_COMMAND_NEXE_FROM_PEXE) | |
203 DumpCommand("@pexe->nexe", nexe_command) | |
204 driver_tools.RunDriver('translate', nexe_command) | |
205 | |
206 # ====================================================================== | |
207 # | |
208 # ====================================================================== | |
209 | |
210 def main(argv): | |
211 DumpCommand("@incoming", argv) | |
212 | |
213 Env.update(EXTRA_ENV) | |
214 driver_tools.ParseArgs(argv, ARG_PATTERNS) | |
215 | |
216 output = Env.getone('OUTPUT') | |
217 | |
218 if output == '': | |
219 Log.Fatal('No output specified. Use -o to specify output') | |
220 | |
221 if Env.getone('ARCH') == '': | |
222 Log.Fatal('No arch specified') | |
223 | |
224 mode = Env.getone('MODE') | |
225 if mode == 'shared': | |
226 BuildSharedLib() | |
227 elif mode == 'dynamic': | |
228 BuildDynamicExecutable() | |
229 elif mode == 'static': | |
230 BuildStaticExecutable() | |
231 else: | |
232 Log.Fatal('You must specify at least one of -static, -shared, -dynamic') | |
233 return 0 | |
OLD | NEW |