def main(argv): env.update(EXTRA_ENV) ParseArgs(argv, LDPatterns) GetArch(required=True) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if output == '': output = pathtools.normalize('a.out') # Expand all parameters # This resolves -lfoo into actual filenames, # and expands linker scripts into command-line arguments. inputs = ldtools.ExpandInputs(inputs, env.get('SEARCH_DIRS'), env.getbool('STATIC'), ldtools.LibraryTypes.NATIVE) env.push() env.set('inputs', *inputs) env.set('output', output) if env.getbool('SANDBOXED'): RunLDSandboxed() else: Run('${RUN_LD}') env.pop() # only reached in case of no errors return 0
def main(argv): env.update(EXTRA_ENV) ParseArgs(argv, PATTERNS) inputs = env.get('INPUTS') if len(inputs) == 0: Log.Fatal("No input files given") for infile in inputs: env.push() env.set('input', infile) if filetype.IsLLVMBitcode(infile): # Hack to support newlib build. # Newlib determines whether the toolchain supports .init_array, etc., by # compiling a small test and looking for a specific section tidbit using # "readelf -S". Since pnacl compiles to bitcode, readelf isn't available. # (there is a line: "if ${READELF} -S conftest | grep -e INIT_ARRAY" # in newlib's configure file). # TODO(sehr): we may want to implement a whole readelf on bitcode. flags = env.get('FLAGS') if len(flags) == 1 and flags[0] == '-S': print 'INIT_ARRAY' return 0 Log.Fatal('Cannot handle pnacl-readelf %s' % str(argv)) return 1 Run('"${READELF}" ${FLAGS} ${input}') env.pop() # only reached in case of no errors return 0
def main(argv): if len(argv) == 0: print get_help(argv) return 1 env.update(EXTRA_ENV) ParseArgs(argv, PATTERNS) Run('"${RANLIB}" --plugin=${GOLD_PLUGIN_SO} ${ARGS}') # only reached in case of no errors return 0
def main(argv): env.update(EXTRA_ENV) ParseArgs(argv, LDPatterns) GetArch(required=True) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if output == '': output = pathtools.normalize('a.out') # As we will modify the output file in-place for non-SFI, we output # the file to a temporary file first and then rename it. Otherwise, # build systems such as make assume the output file is ready even # if the last build failed during the in-place update. tmp_output = output + '.tmp' # Expand all parameters # This resolves -lfoo into actual filenames, # and expands linker scripts into command-line arguments. inputs = ldtools.ExpandInputs(inputs, env.get('SEARCH_DIRS'), True, ldtools.LibraryTypes.NATIVE) env.push() env.set('inputs', *inputs) env.set('output', tmp_output) if env.getbool('SANDBOXED'): RunLDSandboxed() else: Run('${RUN_LD}') if env.getbool('NONSFI_NACL'): # Remove PT_INTERP in non-SFI binaries as we never use host's # dynamic linker/loader. # # This is necessary otherwise we get a statically linked # executable that is not directly runnable by Linux, because Linux # tries to load the non-existent file that PT_INTERP points to. # # This is fairly hacky. It would be better if the linker provided # an option for omitting PT_INTERP (e.g. "--dynamic-linker ''"). RemoveInterpProgramHeader(tmp_output) if driver_tools.IsWindowsPython() and os.path.exists(output): # On Windows (but not on Unix), the os.rename() call would fail if the # output file already exists. os.remove(output) os.rename(tmp_output, output) env.pop() # only reached in case of no errors return 0
def get_help(argv): tool = env.getone('SCRIPT_NAME') if '--help-full' in argv: # To get ${CC}, etc. env.update(EXTRA_ENV) code, stdout, stderr = Run('"${CC}" -help', redirect_stdout=subprocess.PIPE, redirect_stderr=subprocess.STDOUT, errexit=False) return stdout else: return """ This is a "GCC-compatible" driver using clang under the hood. Usage: %s [options] <inputs> ... BASIC OPTIONS: -o <file> Output to <file>. -E Only run the preprocessor. -S Generate bitcode assembly. -c Generate bitcode object. -I <dir> Add header search path. -L <dir> Add library search path. -D<key>[=<val>] Add definition for the preprocessor. -W<id> Toggle warning <id>. -f<feature> Enable <feature>. -Wl,<arg> Pass <arg> to the linker. -Xlinker <arg> Pass <arg> to the linker. -Wt,<arg> Pass <arg> to the translator. -Xtranslator <arg> Pass <arg> to the translator. -Wp,<arg> Pass <arg> to the preprocessor. -Xpreprocessor,<arg> Pass <arg> to the preprocessor. -x <language> Treat subsequent input files as having type <language>. -static Produce a static executable (the default). -Bstatic Link subsequent libraries statically. -Bdynamic Link subsequent libraries dynamically. -fPIC Ignored (only used by translator backend) (accepted for compatibility). -pipe Ignored (for compatibility). -O<n> Optimation level <n>: 0, 1, 2, 3, 4 or s. -g Generate complete debug information. -gline-tables-only Generate debug line-information only (allowing for stack traces). -flimit-debug-info Generate limited debug information. -save-temps Keep intermediate compilation results. -v Verbose output / show commands. -h | --help Show this help. --help-full Show underlying clang driver's help message (warning: not all options supported). """ % (tool)
def main(argv): env.set('ARGS', *argv) if filetype.IsLLVMBitcode(argv[1]): # Hack to support newlib build. # Newlib determines whether the toolchain supports .init_array, etc., by # compiling a small test and looking for a specific section tidbit using # readelf. Since pnacl compiles to bitcode, readelf isn't available. # TODO(sehr): we may want to implement a whole readelf on bitcode. if len(argv) == 2 and argv[0] == '-S': print 'INIT_ARRAY' return 0 return 1 Run('${READELF} ${ARGS}') # only reached in case of no errors return 0
def RunLDSandboxed(): if not env.getbool('USE_STDLIB'): Log.Fatal('-nostdlib is not supported by the sandboxed translator') CheckTranslatorPrerequisites() # The "main" input file is the application's combined object file. all_inputs = env.get('inputs') main_input = env.getone('LLC_TRANSLATED_FILE') if not main_input: Log.Fatal("Sandboxed LD requires one shm input file") outfile = env.getone('output') modules = int(env.getone('SPLIT_MODULE')) assert modules >= 1 first_mainfile = all_inputs.index(main_input) first_extra = all_inputs.index(main_input) + modules # Have a list of just the split module files. llc_outputs = all_inputs[first_mainfile:first_extra] # Have a list of everything else. other_inputs = all_inputs[:first_mainfile] + all_inputs[first_extra:] native_libs_dirname = pathtools.tosys(GetNativeLibsDirname(other_inputs)) command = [driver_tools.SelLdrCommand(), '-a'] # Allow file access driver_tools.AddListToEnv(command, 'NACL_IRT_PNACL_TRANSLATOR_LINK_INPUT', llc_outputs) command.extend([ '-E', 'NACL_IRT_PNACL_TRANSLATOR_LINK_OUTPUT=%s ' % outfile, '-E', 'NACL_IRT_OPEN_RESOURCE_BASE=%s' % native_libs_dirname, '-E', 'NACL_IRT_OPEN_RESOURCE_REMAP=%s' % 'libpnacl_irt_shim.a:libpnacl_irt_shim_dummy.a', '--', '${LD_SB}' ]) Run( ' '.join(command), # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def RunLDSandboxed(): if not env.getbool('USE_STDLIB'): Log.Fatal('-nostdlib is not supported by the sandboxed translator') CheckTranslatorPrerequisites() # The "main" input file is the application's combined object file. all_inputs = env.get('inputs') main_input = env.getone('LLC_TRANSLATED_FILE') if not main_input: Log.Fatal("Sandboxed LD requires one shm input file") outfile = env.getone('output') modules = int(env.getone('SPLIT_MODULE')) if modules > 1: first_mainfile = all_inputs.index(main_input) first_extra = all_inputs.index(main_input) + modules # Just the split module files llc_outputs = all_inputs[first_mainfile:first_extra] # everything else all_inputs = all_inputs[:first_mainfile] + all_inputs[first_extra:] else: llc_outputs = [main_input] files = LinkerFiles(all_inputs) ld_flags = env.get('LD_FLAGS') script = MakeSelUniversalScriptForLD(ld_flags, llc_outputs, files, outfile) Run( '${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ' + '${SEL_UNIVERSAL_FLAGS} -- ${LD_SB}', stdin_contents=script, # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def main(argv): env.update(EXTRA_ENV) CheckSetup() ParseArgs(argv, CustomPatterns + GCCPatterns) # "configure", especially when run as part of a toolchain bootstrap # process, will invoke gcc with various diagnostic options and # parse the output. In these cases we do not alter the incoming # commandline. It is also important to not emit spurious messages. if env.getbool('DIAGNOSTIC'): if env.getbool('SHOW_VERSION'): code, stdout, stderr = Run(env.get('CC') + env.get('CC_FLAGS'), redirect_stdout=subprocess.PIPE) out = stdout.split('\n') nacl_version = ReadDriverRevision() out[0] += ' nacl-version=%s' % nacl_version stdout = '\n'.join(out) print stdout, else: Run(env.get('CC') + env.get('CC_FLAGS')) return 0 unmatched = env.get('UNMATCHED') if len(unmatched) > 0: UnrecognizedOption(*unmatched) # If -arch was given, we are compiling directly to native code compiling_to_native = GetArch() is not None if env.getbool('ALLOW_NATIVE') and not compiling_to_native: Log.Fatal("--pnacl-allow-native without -arch is not meaningful.") if not env.get('STDLIB'): # Default C++ Standard Library. SetStdLib('libc++') inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) == 0: if env.getbool('VERBOSE'): # -v can be invoked without any inputs. Runs the original # command without modifying the commandline for this case. Run(env.get('CC') + env.get('CC_FLAGS')) return 0 else: Log.Fatal('No input files') gcc_mode = env.getone('GCC_MODE') output_type = DriverOutputTypes(gcc_mode, compiling_to_native) needs_linking = (gcc_mode == '') if env.getbool('NEED_DASH_E') and gcc_mode != '-E': Log.Fatal("-E or -x required when input is from stdin") # There are multiple input files and no linking is being done. # There will be multiple outputs. Handle this case separately. if not needs_linking: # Filter out flags inputs = [f for f in inputs if not IsFlag(f)] if output != '' and len(inputs) > 1: Log.Fatal('Cannot have -o with -c, -S, or -E and multiple inputs: %s', repr(inputs)) for f in inputs: if IsFlag(f): continue intype = filetype.FileType(f) if not filetype.IsSourceType(intype): if ((output_type == 'pp' and intype != 'S') or (output_type == 'll') or (output_type == 'po' and intype != 'll') or (output_type == 's' and intype not in ('ll','po','S')) or (output_type == 'o' and intype not in ('ll','po','S','s'))): Log.Fatal("%s: Unexpected type of file for '%s'", pathtools.touser(f), gcc_mode) if output == '': f_output = DefaultOutputName(f, output_type) else: f_output = output namegen = TempNameGen([f], f_output) CompileOne(f, output_type, namegen, f_output) return 0 # Linking case assert(needs_linking) assert(output_type in ('pso','so','pexe','nexe')) if output == '': output = pathtools.normalize('a.out') namegen = TempNameGen(inputs, output) # Compile all source files (c/c++/ll) to .po for i in xrange(0, len(inputs)): if IsFlag(inputs[i]): continue intype = filetype.FileType(inputs[i]) if filetype.IsSourceType(intype) or intype == 'll': inputs[i] = CompileOne(inputs[i], 'po', namegen) # Compile all .s/.S to .o if env.getbool('ALLOW_NATIVE'): for i in xrange(0, len(inputs)): if IsFlag(inputs[i]): continue intype = filetype.FileType(inputs[i]) if intype in ('s','S'): inputs[i] = CompileOne(inputs[i], 'o', namegen) # We should only be left with .po and .o and libraries for f in inputs: if IsFlag(f): continue intype = filetype.FileType(f) if intype in ('o','s','S') or filetype.IsNativeArchive(f): if not env.getbool('ALLOW_NATIVE'): Log.Fatal('%s: Native object files not allowed in link. ' 'Use --pnacl-allow-native to override.', pathtools.touser(f)) assert(intype in ('po','o','so','ldscript') or filetype.IsArchive(f)) # Fix the user-specified linker arguments ld_inputs = [] for f in inputs: if f.startswith('-Xlinker='): ld_inputs.append(f[len('-Xlinker='):]) elif f.startswith('-Wl,'): ld_inputs += f[len('-Wl,'):].split(',') else: ld_inputs.append(f) if env.getbool('ALLOW_NATIVE'): ld_inputs.append('--pnacl-allow-native') # Invoke the linker env.set('ld_inputs', *ld_inputs) ld_args = env.get('LD_ARGS') ld_flags = env.get('LD_FLAGS') RunDriver('ld', ld_flags + ld_args + ['-o', output]) return 0
def main(argv): env.update(EXTRA_ENV) CheckSetup() ParseArgs(argv, CustomPatterns + GCCPatterns) # "configure", especially when run as part of a toolchain bootstrap # process, will invoke gcc with various diagnostic options and # parse the output. In these cases we do not alter the incoming # commandline. It is also important to not emit spurious messages. if env.getbool('DIAGNOSTIC'): if env.getbool('SHOW_VERSION'): code, stdout, stderr = Run(env.get('CC') + env.get('CC_FLAGS'), redirect_stdout=subprocess.PIPE) out = stdout.split('\n') nacl_version = ReadDriverRevision() out[0] += ' nacl-version=%s' % nacl_version stdout = '\n'.join(out) print stdout, else: Run(env.get('CC') + env.get('CC_FLAGS')) return 0 unmatched = env.get('UNMATCHED') if len(unmatched) > 0: UnrecognizedOption(*unmatched) # If -arch was given, we are compiling directly to native code compiling_to_native = GetArch() is not None if env.getbool('ALLOW_NATIVE'): if not compiling_to_native: Log.Fatal("--pnacl-allow-native without -arch is not meaningful.") # For native/mixed links, also bring in the native libgcc and # libcrt_platform to avoid link failure if pre-translated native # code needs functions from it. env.append('LD_FLAGS', env.eval('-L${LIBS_NATIVE_ARCH}')) env.append('STDLIBS', '-lgcc') env.append('STDLIBS', '-lcrt_platform') flags_and_inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(flags_and_inputs) == 0: if env.getbool('VERBOSE'): # -v can be invoked without any inputs. Runs the original # command without modifying the commandline for this case. Run(env.get('CC') + env.get('CC_FLAGS')) return 0 else: Log.Fatal('No input files') gcc_mode = env.getone('GCC_MODE') output_type = DriverOutputTypes(gcc_mode, compiling_to_native) # '-shared' modifies the output from the linker and should be considered when # determining the final output type. if env.getbool('SHARED'): if compiling_to_native: Log.Fatal('Building native shared libraries not supported') if gcc_mode != '': Log.Fatal('-c, -S, and -E are disallowed with -shared') output_type = 'pll' # INPUTS consists of actual input files and a subset of flags like -Wl,<foo>. # Create a version with just the files. inputs = [f for f in flags_and_inputs if not IsFlag(f)] header_inputs = [ f for f in inputs if filetype.IsHeaderType(filetype.FileType(f)) ] # Handle PCH case specially (but only for a limited sense...) if header_inputs and gcc_mode != '-E': # We only handle doing pre-compiled headers for all inputs or not at # all at the moment. This is because DriverOutputTypes only assumes # one type of output, depending on the "gcc_mode" flag. When mixing # header inputs w/ non-header inputs, some of the outputs will be # pch while others will be output_type. We would also need to modify # the input->output chaining for the needs_linking case. if len(header_inputs) != len(inputs): Log.Fatal('mixed compiling of headers and source not supported') CompileHeaders(header_inputs, output) return 0 needs_linking = (gcc_mode == '') if env.getbool('NEED_DASH_E') and gcc_mode != '-E': Log.Fatal("-E or -x required when input is from stdin") # There are multiple input files and no linking is being done. # There will be multiple outputs. Handle this case separately. if not needs_linking: if output != '' and len(inputs) > 1: Log.Fatal( 'Cannot have -o with -c, -S, or -E and multiple inputs: %s', repr(inputs)) for f in inputs: intype = filetype.FileType(f) if not (filetype.IsSourceType(intype) or filetype.IsHeaderType(intype)): if ((output_type == 'pp' and intype != 'S') or (output_type == 'll') or (output_type == 'po' and intype != 'll') or (output_type == 's' and intype not in ('ll', 'po', 'S')) or (output_type == 'o' and intype not in ('ll', 'po', 'S', 's'))): Log.Fatal("%s: Unexpected type of file for '%s'", pathtools.touser(f), gcc_mode) if output == '': f_output = DefaultOutputName(f, output_type) else: f_output = output namegen = TempNameGen([f], f_output) CompileOne(f, output_type, namegen, f_output) return 0 # Linking case assert (needs_linking) assert (output_type in ('pll', 'pexe', 'nexe')) if output == '': output = pathtools.normalize('a.out') namegen = TempNameGen(flags_and_inputs, output) # Compile all source files (c/c++/ll) to .po for i in xrange(0, len(flags_and_inputs)): if IsFlag(flags_and_inputs[i]): continue intype = filetype.FileType(flags_and_inputs[i]) if filetype.IsSourceType(intype) or intype == 'll': flags_and_inputs[i] = CompileOne(flags_and_inputs[i], 'po', namegen) # Compile all .s/.S to .o if env.getbool('ALLOW_NATIVE'): for i in xrange(0, len(flags_and_inputs)): if IsFlag(flags_and_inputs[i]): continue intype = filetype.FileType(flags_and_inputs[i]) if intype in ('s', 'S'): flags_and_inputs[i] = CompileOne(flags_and_inputs[i], 'o', namegen) # We should only be left with .po and .o and libraries for f in flags_and_inputs: if IsFlag(f): continue intype = filetype.FileType(f) if intype in ('o', 's', 'S') or filetype.IsNativeArchive(f): if not env.getbool('ALLOW_NATIVE'): Log.Fatal( '%s: Native object files not allowed in link. ' 'Use --pnacl-allow-native to override.', pathtools.touser(f)) assert (intype in ('po', 'o', 'so', 'ldscript') or filetype.IsArchive(f)) # Fix the user-specified linker arguments ld_inputs = [] for f in flags_and_inputs: if f.startswith('-Xlinker='): ld_inputs.append(f[len('-Xlinker='):]) elif f.startswith('-Wl,'): ld_inputs += f[len('-Wl,'):].split(',') else: ld_inputs.append(f) if env.getbool('ALLOW_NATIVE'): ld_inputs.append('--pnacl-allow-native') # Invoke the linker env.set('ld_inputs', *ld_inputs) ld_args = env.get('LD_ARGS') ld_flags = env.get('LD_FLAGS') RunDriver('pnacl-ld', ld_flags + ld_args + ['-o', output]) return 0
def main(argv): env.update(EXTRA_ENV) ParseArgs(argv, PATTERNS) Run('"${NM}" --plugin=${GOLD_PLUGIN_SO} ${ARGS}') # only reached in case of no errors return 0