| 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 |