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.
9 from driver_tools import AddHostBinarySearchPath, DefaultOutputName, \
10 DriverChain, GetArch, ParseArgs, ParseTriple, Run, RunDriver, RunWithEnv, \
11 TempNameGen, UnrecognizedOption
12 from driver_env import env
13 from driver_log import DriverOpen, Log
18 'ALLOW_TRANSLATE': '0', # Allow bitcode translation before linking.
19 # It doesn't normally make sense to do this.
21 'ALLOW_NATIVE' : '0', # Allow native objects (.S,.s,.o) to be in the
22 # linker line for .pexe generation.
23 # It doesn't normally make sense to do this.
25 # CXX_EH_MODE specifies how to deal with C++ exception handling:
26 # * 'none': Strips out use of C++ exception handling.
27 # * 'sjlj': Enables the setjmp()+longjmp()-based implementation of
28 # C++ exception handling. This is supported in PNaCl's stable
30 # * 'zerocost': Enables the zero-cost implementation of C++
31 # exception handling. This is not supported in PNaCl's stable
33 'CXX_EH_MODE': 'none',
35 'FORCE_INTERMEDIATE_LL': '0',
36 # Produce an intermediate .ll file
37 # Useful for debugging.
38 # NOTE: potentially different code paths and bugs
39 # might be triggered by this
40 'LANGUAGE' : '', # C or CXX (set by SetTool)
41 'INCLUDE_CXX_HEADERS': '0', # This is set by RunCC.
43 # Command-line options
44 'GCC_MODE' : '', # '' (default), '-E', '-c', or '-S'
45 'STDINC' : '1', # Include standard headers (-nostdinc sets to 0)
46 'STDINCCXX' : '1', # Include standard cxx headers (-nostdinc++ sets to 0)
47 'USE_STDLIB' : '1', # Include standard libraries (-nostdlib sets to 0)
48 'STDLIB' : '', # C++ Standard Library.
49 'STDLIB_TRUNC': '', # C++ Standard Library, truncated to pass as -lXXX.
50 'STDLIB_IDIR' : '', # C++ Standard Library include directory.
51 # Note: the above C++ Standard Library
52 # settings use a default if their value
54 'DEFAULTLIBS' : '1', # Link with default libraries
55 'DIAGNOSTIC' : '0', # Diagnostic flag detected
56 'PIC' : '0', # Generate PIC
57 # TODO(robertm): Switch the default to 1
58 'NO_ASM' : '0', # Disallow use of inline assembler
59 'NEED_DASH_E' : '0', # Used for stdin inputs, which must have an explicit
60 # type set (using -x) unless -E is specified.
61 'VERBOSE' : '0', # Verbose (-v)
62 'SHOW_VERSION': '0', # Version (--version)
64 'PTHREAD' : '0', # use pthreads?
65 'INPUTS' : '', # Input files
66 'OUTPUT' : '', # Output file
67 'UNMATCHED' : '', # Unrecognized parameters
70 'BIAS_ARM' : '-D__arm__ -D__ARM_ARCH_7A__ -D__ARMEL__',
71 'BIAS_MIPS32' : '-D__MIPS__ -D__mips__ -D__MIPSEL__',
72 'BIAS_X8632' : '-D__i386__ -D__i386 -D__i686 -D__i686__ -D__pentium4__',
73 'BIAS_X8664' : '-D__amd64__ -D__amd64 -D__x86_64__ -D__x86_64 -D__core2__',
74 'BIAS_ARM_NONSFI': '${BIAS_ARM} -D__native_client_nonsfi__',
75 'BIAS_X8632_NONSFI': '${BIAS_X8632} -D__native_client_nonsfi__',
76 'FRONTEND_TRIPLE' : 'le32-unknown-nacl',
78 'OPT_LEVEL' : '', # Default for most tools is 0, but we need to know
79 # if it's explicitly set or not when the driver
80 # is only used for linking + translating.
81 'CC_FLAGS' : '-O${#OPT_LEVEL ? ${OPT_LEVEL} : 0} ' +
82 '-fno-vectorize -fno-slp-vectorize ' +
83 '-fno-common ${PTHREAD ? -pthread} ' +
84 '-nostdinc ${BIAS_%BIAS%} ' +
85 # BUG: http://code.google.com/p/nativeclient/issues/detail?id=2345
86 # it would be better to detect asm use inside clang
87 # as some uses of asm are borderline legit, e.g.
88 # <prototype> asm("<function-name>");
89 '${NO_ASM ? -Dasm=ASM_FORBIDDEN -D__asm__=ASM_FORBIDDEN} ' +
90 '-target ${FRONTEND_TRIPLE}',
93 'ISYSTEM' : '${ISYSTEM_USER} ${STDINC ? ${ISYSTEM_BUILTIN}}',
95 'ISYSTEM_USER' : '', # System include directories specified by
96 # using the -isystem flag.
99 '${BASE_USR}/local/include ' +
100 '${ISYSTEM_CLANG} ' +
102 '${BASE_USR}/include ' +
103 '${BASE_SDK}/include ',
105 'ISYSTEM_CLANG' : '${BASE_LLVM}/lib/clang/3.4/include',
108 '${INCLUDE_CXX_HEADERS && STDINCCXX ? ${ISYSTEM_CXX_include_paths}}',
110 'ISYSTEM_CXX_include_paths' :
111 '${BASE_USR}/include/c++/${STDLIB_IDIR} ' +
112 '${BASE_USR}/include/c++/${STDLIB_IDIR}/arm-none-linux-gnueabi ' +
113 '${BASE_USR}/include/c++/${STDLIB_IDIR}/backward',
116 # Only propagate opt level to linker if explicitly set, so that the
117 # linker will know if an opt level was explicitly set or not.
118 'LD_FLAGS' : '${#OPT_LEVEL ? -O${OPT_LEVEL}} -static ' +
119 '${PIC ? -fPIC} ${@AddPrefix:-L:SEARCH_DIRS} ' +
120 '--pnacl-exceptions=${CXX_EH_MODE}',
122 'SEARCH_DIRS' : '', # Directories specified using -L
125 'EMITMODE' : '${!USE_STDLIB ? nostdlib : static}',
127 # This is setup so that LD_ARGS_xxx is evaluated lazily.
128 'LD_ARGS' : '${LD_ARGS_%EMITMODE%}',
130 # ${ld_inputs} signifies where to place the objects and libraries
131 # provided on the command-line.
132 'LD_ARGS_nostdlib': '-nostdlib ${ld_inputs}',
135 '${CXX_EH_MODE==zerocost ? -l:crt1_for_eh.x : -l:crt1.x} ' +
136 '-l:crti.bc -l:crtbegin.bc '
137 '${CXX_EH_MODE==sjlj ? -l:sjlj_eh_redirect.bc : '
138 '${CXX_EH_MODE==none ? -l:unwind_stubs.bc}} ' +
140 '--start-group ${STDLIBS} --end-group',
142 'LLVM_PASSES_TO_DISABLE': '',
144 # Flags for translating to native .o files.
145 'TRANSLATE_FLAGS' : '-O${#OPT_LEVEL ? ${OPT_LEVEL} : 0}',
147 'STDLIBS' : '${DEFAULTLIBS ? '
148 '${LIBSTDCPP} ${LIBPTHREAD} ${LIBNACL} ${LIBC} ${LIBPNACLMM}}',
149 'LIBSTDCPP' : '${IS_CXX ? -l${STDLIB_TRUNC} -lm }',
151 'LIBNACL' : '-lnacl',
152 'LIBPNACLMM': '-lpnaclmm',
153 # Enabled/disabled by -pthreads
154 'LIBPTHREAD': '${PTHREAD ? -lpthread}',
156 # IS_CXX is set by pnacl-clang and pnacl-clang++ programmatically
157 'CC' : '${IS_CXX ? ${CLANGXX} : ${CLANG}}',
158 'RUN_CC': '${CC} -emit-llvm ${mode} ${CC_FLAGS} ' +
159 '${@AddPrefix:-isystem :ISYSTEM} ' +
160 '-x${typespec} "${infile}" -o ${output}',
163 def AddLLVMPassDisableFlag(*args):
164 env.append('LLVM_PASSES_TO_DISABLE', *args)
165 env.append('LD_FLAGS', *args)
167 def AddLDFlag(*args):
168 env.append('LD_FLAGS', *args)
170 def AddTranslatorFlag(*args):
171 # pass translator args to ld in case we go all the way to .nexe
172 env.append('LD_FLAGS', *['-Wt,' + a for a in args])
173 # pass translator args to translator in case we go to .o
174 env.append('TRANSLATE_FLAGS', *args)
176 def AddCCFlag(*args):
177 env.append('CC_FLAGS', *args)
179 def AddDiagnosticFlag(*args):
180 env.append('CC_FLAGS', *args)
181 env.set('DIAGNOSTIC', '1')
183 def SetTarget(*args):
184 arch = ParseTriple(args[0])
185 env.set('FRONTEND_TRIPLE', args[0])
186 AddLDFlag('--target=' + args[0])
188 def SetStdLib(*args):
189 """Set the C++ Standard Library."""
191 assert lib == 'libc++' or lib == 'libstdc++', (
192 'Invalid C++ standard library: -stdlib=%s' % lib)
193 env.set('STDLIB', lib)
194 env.set('STDLIB_TRUNC', lib[3:])
196 env.set('STDLIB_IDIR', 'v1')
197 if env.getbool('IS_CXX'):
198 # libc++ depends on pthread for C++11 features as well as some
199 # exception handling (which may get removed later by the PNaCl ABI
200 # simplification) and initialize-once.
201 env.set('PTHREAD', '1')
202 elif lib == 'libstdc++':
203 env.set('STDLIB_IDIR', '4.6.2')
206 return env.getone('FRONTEND_TRIPLE').startswith('le32-')
209 def AddInputFileStdin():
212 # When stdin is an input, -x or -E must be given.
213 forced_type = filetype.GetForcedFileType()
215 # Only allowed if -E is specified.
217 env.set('NEED_DASH_E', '1')
219 stdin_name = '__stdin%d__' % stdin_count
220 env.append('INPUTS', stdin_name)
221 filetype.ForceFileType(stdin_name, forced_type)
225 return f.startswith('__stdin') and f.endswith('__')
227 def HandleDashX(arg):
229 filetype.SetForcedFileType(None)
231 filetype.SetForcedFileType(filetype.GCCTypeToFileType(arg))
233 def AddVersionFlag(*args):
234 env.set('SHOW_VERSION', '1')
235 AddDiagnosticFlag(*args)
237 def AddBPrefix(prefix):
238 """ Add a path to the list searched for host binaries and include dirs. """
239 AddHostBinarySearchPath(prefix)
240 prefix = pathtools.normalize(prefix)
241 if pathtools.isdir(prefix) and not prefix.endswith('/'):
244 # Add prefix/ to the library search dir if it exists
245 if pathtools.isdir(prefix):
246 env.append('SEARCH_DIRS', prefix)
248 # Add prefix/include to isystem if it exists
249 include_dir = prefix + 'include'
250 if pathtools.isdir(include_dir):
251 env.append('ISYSTEM_USER', include_dir)
254 ( '--driver=(.+)', "env.set('CC', pathtools.normalize($0))\n"),
255 ( '--pnacl-allow-native', "env.set('ALLOW_NATIVE', '1')"),
256 ( '--pnacl-allow-translate', "env.set('ALLOW_TRANSLATE', '1')"),
257 ( '--pnacl-frontend-triple=(.+)', SetTarget),
258 ( ('-target','(.+)'), SetTarget),
259 ( ('--target=(.+)'), SetTarget),
260 ( '--pnacl-exceptions=(none|sjlj|zerocost)', "env.set('CXX_EH_MODE', $0)"),
261 # TODO(mseaborn): Remove "--pnacl-allow-exceptions", which is
262 # superseded by "--pnacl-exceptions".
263 ( '--pnacl-allow-exceptions', "env.set('CXX_EH_MODE', 'zerocost')"),
264 ( '(--pnacl-allow-nexe-build-id)', AddLDFlag),
265 ( '(--pnacl-disable-abi-check)', AddLDFlag),
266 ( '(--pnacl-disable-pass=.+)', AddLLVMPassDisableFlag),
270 ( '-o(.+)', "env.set('OUTPUT', pathtools.normalize($0))"),
271 ( ('-o', '(.+)'), "env.set('OUTPUT', pathtools.normalize($0))"),
273 ( '-E', "env.set('GCC_MODE', '-E')"),
274 ( '-S', "env.set('GCC_MODE', '-S')"),
275 ( '-c', "env.set('GCC_MODE', '-c')"),
277 ( '-allow-asm', "env.set('NO_ASM', '0')"),
279 ( '-nostdinc', "env.set('STDINC', '0')"),
280 ( '-nostdinc\+\+', "env.set('STDINCCXX', '0')"),
281 ( '-nostdlib', "env.set('USE_STDLIB', '0')"),
282 ( '-nodefaultlibs', "env.set('DEFAULTLIBS', '0')"),
284 ( '-?-stdlib=(.*)', SetStdLib),
285 ( ('-?-stdlib', '(.*)'), SetStdLib),
287 # Flags to pass to native linker
288 ( '(-Wn,.*)', AddLDFlag),
289 ( '-rdynamic', "env.append('LD_FLAGS', '-export-dynamic')"),
291 # Flags to pass to pnacl-translate
292 ( '-Wt,(.*)', AddTranslatorFlag),
293 ( ('-Xtranslator','(.*)'), AddTranslatorFlag),
295 # We don't care about -fPIC, but pnacl-ld and pnacl-translate do.
296 ( '-fPIC', "env.set('PIC', '1')"),
298 # We must include -l, -Xlinker, and -Wl options into the INPUTS
299 # in the order they appeared. This is the exactly behavior of gcc.
300 # For example: gcc foo.c -Wl,--start-group -lx -ly -Wl,--end-group
302 ( '(-l.+)', "env.append('INPUTS', $0)"),
303 ( ('(-l)','(.+)'), "env.append('INPUTS', $0+$1)"),
304 ( ('-Xlinker','(.*)'), "env.append('INPUTS', '-Xlinker=' + $0)"),
305 ( '(-Wl,.*)', "env.append('INPUTS', $0)"),
306 ( '(-Bstatic)', "env.append('INPUTS', $0)"),
307 ( '(-Bdynamic)', "env.append('INPUTS', $0)"),
309 ( '-O([sz])', "env.set('OPT_LEVEL', $0)\n"),
310 ( '-O([0-3])', "env.set('OPT_LEVEL', $0)\n"),
311 ( '-O([0-9]+)', "env.set('OPT_LEVEL', '3')\n"),
312 ( '-O', "env.set('OPT_LEVEL', '1')\n"),
314 ( ('-isystem', '(.*)'),
315 "env.append('ISYSTEM_USER', pathtools.normalize($0))"),
317 "env.append('ISYSTEM_USER', pathtools.normalize($0))"),
318 ( ('-I', '(.+)'), "env.append('CC_FLAGS', '-I'+pathtools.normalize($0))"),
319 ( '-I(.+)', "env.append('CC_FLAGS', '-I'+pathtools.normalize($0))"),
321 # NOTE: the -iquote =DIR syntax (substitute = with sysroot) doesn't work.
322 # Clang just says: ignoring nonexistent directory "=DIR"
323 ( ('-iquote', '(.+)'),
324 "env.append('CC_FLAGS', '-iquote', pathtools.normalize($0))"),
326 "env.append('CC_FLAGS', '-iquote', pathtools.normalize($0))"),
328 ( ('-idirafter', '(.+)'),
329 "env.append('CC_FLAGS', '-idirafter'+pathtools.normalize($0))"),
331 "env.append('CC_FLAGS', '-idirafter'+pathtools.normalize($0))"),
333 ( ('(-include)','(.+)'), AddCCFlag),
334 ( ('(-include.+)'), AddCCFlag),
335 ( '(-g)', AddCCFlag),
336 ( '(-W.*)', AddCCFlag),
337 ( '(-w)', AddCCFlag),
338 ( '(-std=.*)', AddCCFlag),
339 ( '(-ansi)', AddCCFlag),
340 ( ('(-D)','(.*)'), AddCCFlag),
341 ( '(-D.+)', AddCCFlag),
342 ( ('(-U)','(.*)'), AddCCFlag),
343 ( '(-U.+)', AddCCFlag),
344 ( '(-f.*)', AddCCFlag),
345 ( '(-pedantic)', AddCCFlag),
346 ( '(-pedantic-errors)', AddCCFlag),
347 ( '(-g.*)', AddCCFlag),
348 ( '(-v|--v)', "env.append('CC_FLAGS', $0)\n"
349 "env.set('VERBOSE', '1')"),
350 ( '(-pthreads?)', "env.set('PTHREAD', '1')"),
352 # No-op: accepted for compatibility in case build scripts pass it.
355 ( ('-B','(.*)'), AddBPrefix),
356 ( ('-B(.+)'), AddBPrefix),
358 ( ('-L','(.+)'), "env.append('SEARCH_DIRS', pathtools.normalize($0))"),
359 ( '-L(.+)', "env.append('SEARCH_DIRS', pathtools.normalize($0))"),
361 ( '(-Wp,.*)', AddCCFlag),
362 ( '(-Xpreprocessor .*)', AddCCFlag),
363 ( ('(-Xclang)', '(.*)'), AddCCFlag),
365 # Accept and ignore default flags
369 ( '(-MG)', AddCCFlag),
370 ( '(-MMD)', AddCCFlag),
371 ( '(-MM?)', "env.append('CC_FLAGS', $0)\n"
372 "env.set('GCC_MODE', '-E')"),
373 ( '(-MP)', AddCCFlag),
374 ( ('(-MQ)','(.*)'), AddCCFlag),
375 ( '(-MD)', AddCCFlag),
376 ( ('(-MT)','(.*)'), AddCCFlag),
377 ( ('(-MF)','(.*)'), "env.append('CC_FLAGS', $0, pathtools.normalize($1))"),
379 ( ('-x', '(.+)'), HandleDashX),
380 ( '-x(.+)', HandleDashX),
382 ( ('(-mllvm)', '(.+)'), AddCCFlag),
384 # Ignore these gcc flags
386 ( '(-march=armv7-a)', ""),
389 ( '(-s)', AddLDFlag),
390 ( '(--strip-all)', AddLDFlag),
391 ( '(--strip-debug)', AddLDFlag),
393 # Ignore these assembler flags
395 ( ('(--traditional-format)', '.*'), ""),
399 ( '(--gdwarf2)', ""),
400 ( '(--fatal-warnings)', ""),
401 ( '(-meabi=.*)', ""),
404 ( '(-mfloat-abi=.+)', AddCCFlag),
406 # GCC diagnostic mode triggers
407 ( '(-print-.*)', AddDiagnosticFlag),
408 ( '(--print.*)', AddDiagnosticFlag),
409 ( '(-dumpspecs)', AddDiagnosticFlag),
410 ( '(--version)', AddVersionFlag),
411 # These are preprocessor flags which should be passed to the frontend, but
412 # should not prevent the usual -i flags (which DIAGNOSTIC mode does)
413 ( '(-d[DIMNU])', AddCCFlag),
414 ( '(-d.*)', AddDiagnosticFlag),
416 # Catch all other command-line arguments
417 ( '(-.+)', "env.append('UNMATCHED', $0)"),
420 ( '-', AddInputFileStdin),
423 # Call ForceFileType for all input files at the time they are
424 # parsed on the command-line. This ensures that the gcc "-x"
425 # setting is correctly applied.
426 ( '(.*)', "env.append('INPUTS', pathtools.normalize($0))\n"
427 "filetype.ForceFileType(pathtools.normalize($0))"),
431 if not env.has('IS_CXX'):
432 Log.Fatal('"pnacl-driver" cannot be used directly. '
433 'Use pnacl-clang or pnacl-clang++.')
435 def DriverOutputTypes(driver_flag, compiling_to_native):
437 ('-E', False) : 'pp',
439 ('-c', False) : 'po',
441 ('-S', False) : 'll',
443 ('', False) : 'pexe',
446 return output_type_map[(driver_flag, compiling_to_native)]
449 def ReadDriverRevision():
450 rev_file = env.getone('DRIVER_REV_FILE')
451 # Might be an SVN version or a GIT hash (depending on the NaCl src client)
452 nacl_ver = DriverOpen(rev_file, 'rb').readlines()[0]
453 m = re.search(r'\[SVN\].*/native_client:\s*(\d+)', nacl_ver)
456 m = re.search(r'\[GIT\].*/native_client.git:\s*(\w+)', nacl_ver)
459 # fail-fast: if the REV file exists but regex search failed,
460 # we need to fix the regex to get nacl-version.
462 Log.Fatal('Failed to parse REV file to get nacl-version.')
466 env.update(EXTRA_ENV)
468 ParseArgs(argv, CustomPatterns + GCCPatterns)
470 # "configure", especially when run as part of a toolchain bootstrap
471 # process, will invoke gcc with various diagnostic options and
472 # parse the output. In these cases we do not alter the incoming
473 # commandline. It is also important to not emit spurious messages.
474 if env.getbool('DIAGNOSTIC'):
475 if env.getbool('SHOW_VERSION'):
476 code, stdout, stderr = Run(env.get('CC') + env.get('CC_FLAGS'),
477 redirect_stdout=subprocess.PIPE)
478 out = stdout.split('\n')
479 nacl_version = ReadDriverRevision()
480 out[0] += ' nacl-version=%s' % nacl_version
481 stdout = '\n'.join(out)
484 Run(env.get('CC') + env.get('CC_FLAGS'))
487 unmatched = env.get('UNMATCHED')
488 if len(unmatched) > 0:
489 UnrecognizedOption(*unmatched)
491 # If -arch was given, we are compiling directly to native code
492 compiling_to_native = GetArch() is not None
494 if env.getbool('ALLOW_NATIVE'):
495 if not compiling_to_native:
496 Log.Fatal("--pnacl-allow-native without -arch is not meaningful.")
497 # For native/mixed links, also bring in the native libgcc to avoid link
498 # failure if pre-translated native code needs functions from it.
499 env.append('LD_FLAGS', env.eval('-L${LIBS_NATIVE_ARCH}'))
500 env.append('STDLIBS', '-lgcc')
503 if not env.get('STDLIB'):
504 # Default C++ Standard Library.
507 inputs = env.get('INPUTS')
508 output = env.getone('OUTPUT')
511 if env.getbool('VERBOSE'):
512 # -v can be invoked without any inputs. Runs the original
513 # command without modifying the commandline for this case.
514 Run(env.get('CC') + env.get('CC_FLAGS'))
517 Log.Fatal('No input files')
519 gcc_mode = env.getone('GCC_MODE')
520 output_type = DriverOutputTypes(gcc_mode, compiling_to_native)
521 needs_linking = (gcc_mode == '')
523 if env.getbool('NEED_DASH_E') and gcc_mode != '-E':
524 Log.Fatal("-E or -x required when input is from stdin")
526 # There are multiple input files and no linking is being done.
527 # There will be multiple outputs. Handle this case separately.
528 if not needs_linking:
530 inputs = [f for f in inputs if not IsFlag(f)]
531 if output != '' and len(inputs) > 1:
532 Log.Fatal('Cannot have -o with -c, -S, or -E and multiple inputs: %s',
538 intype = filetype.FileType(f)
539 if not filetype.IsSourceType(intype):
540 if ((output_type == 'pp' and intype != 'S') or
541 (output_type == 'll') or
542 (output_type == 'po' and intype != 'll') or
543 (output_type == 's' and intype not in ('ll','po','S')) or
544 (output_type == 'o' and intype not in ('ll','po','S','s'))):
545 Log.Fatal("%s: Unexpected type of file for '%s'",
546 pathtools.touser(f), gcc_mode)
549 f_output = DefaultOutputName(f, output_type)
553 namegen = TempNameGen([f], f_output)
554 CompileOne(f, output_type, namegen, f_output)
558 assert(needs_linking)
559 assert(output_type in ('pso','so','pexe','nexe'))
562 output = pathtools.normalize('a.out')
563 namegen = TempNameGen(inputs, output)
565 # Compile all source files (c/c++/ll) to .po
566 for i in xrange(0, len(inputs)):
567 if IsFlag(inputs[i]):
569 intype = filetype.FileType(inputs[i])
570 if filetype.IsSourceType(intype) or intype == 'll':
571 inputs[i] = CompileOne(inputs[i], 'po', namegen)
573 # Compile all .s/.S to .o
574 if env.getbool('ALLOW_NATIVE'):
575 for i in xrange(0, len(inputs)):
576 if IsFlag(inputs[i]):
578 intype = filetype.FileType(inputs[i])
579 if intype in ('s','S'):
580 inputs[i] = CompileOne(inputs[i], 'o', namegen)
582 # We should only be left with .po and .o and libraries
586 intype = filetype.FileType(f)
587 if intype in ('o','s','S') or filetype.IsNativeArchive(f):
588 if not env.getbool('ALLOW_NATIVE'):
589 Log.Fatal('%s: Native object files not allowed in link. '
590 'Use --pnacl-allow-native to override.', pathtools.touser(f))
591 assert(intype in ('po','o','so','ldscript') or filetype.IsArchive(f))
593 # Fix the user-specified linker arguments
596 if f.startswith('-Xlinker='):
597 ld_inputs.append(f[len('-Xlinker='):])
598 elif f.startswith('-Wl,'):
599 ld_inputs += f[len('-Wl,'):].split(',')
603 if env.getbool('ALLOW_NATIVE'):
604 ld_inputs.append('--pnacl-allow-native')
607 env.set('ld_inputs', *ld_inputs)
609 ld_args = env.get('LD_ARGS')
610 ld_flags = env.get('LD_FLAGS')
612 RunDriver('pnacl-ld', ld_flags + ld_args + ['-o', output])
616 return f.startswith('-')
618 def CompileOne(infile, output_type, namegen, output = None):
620 output = namegen.TempNameForInput(infile, output_type)
622 chain = DriverChain(infile, output, namegen)
623 SetupChain(chain, filetype.FileType(infile), output_type)
627 def RunCC(infile, output, mode):
628 intype = filetype.FileType(infile)
629 typespec = filetype.FileTypeToGCCType(intype)
630 include_cxx_headers = (env.get('LANGUAGE') == 'CXX') or (intype == 'c++')
631 env.setbool('INCLUDE_CXX_HEADERS', include_cxx_headers)
632 if IsStdinInput(infile):
634 RunWithEnv("${RUN_CC}", infile=infile, output=output,
638 def RunLLVMAS(infile, output):
639 if IsStdinInput(infile):
641 # This is a bitcode only step - so get rid of "-arch xxx" which
642 # might be inherited from the current invocation
643 RunDriver('pnacl-as', [infile, '-o', output],
644 suppress_inherited_arch_args=True)
646 def RunNativeAS(infile, output):
647 if IsStdinInput(infile):
649 RunDriver('pnacl-as', [infile, '-o', output])
651 def RunTranslate(infile, output, mode):
652 if not env.getbool('ALLOW_TRANSLATE'):
653 Log.Fatal('%s: Trying to convert bitcode to an object file before '
654 'bitcode linking. This is supposed to wait until '
655 'translation. Use --pnacl-allow-translate to override.',
656 pathtools.touser(infile))
657 args = env.get('TRANSLATE_FLAGS') + [mode, '--allow-llvm-bitcode-input',
658 infile, '-o', output]
659 if env.getbool('PIC'):
661 RunDriver('pnacl-translate', args)
664 def RunOpt(infile, outfile, pass_list):
665 filtered_list = [pass_option for pass_option in pass_list
666 if pass_option not in env.get('LLVM_PASSES_TO_DISABLE')]
667 RunDriver('pnacl-opt', filtered_list + [infile, '-o', outfile])
670 def SetupChain(chain, input_type, output_type):
671 assert(output_type in ('pp','ll','po','s','o'))
672 cur_type = input_type
675 if filetype.IsSourceType(cur_type) and output_type == 'pp':
676 chain.add(RunCC, 'cpp', mode='-E')
678 if cur_type == output_type:
682 if (filetype.IsSourceType(cur_type) and
683 (env.getbool('FORCE_INTERMEDIATE_LL') or output_type == 'll')):
684 chain.add(RunCC, 'll', mode='-S')
686 if cur_type == output_type:
691 chain.add(RunLLVMAS, 'po')
693 if cur_type == output_type:
696 # source file -> po (we also force native output to go through this phase
697 if filetype.IsSourceType(cur_type) and output_type in ('po', 'o', 's'):
698 chain.add(RunCC, 'po', mode='-c')
700 if cur_type == output_type:
704 if (cur_type == 'po' and output_type == 'o'):
705 # If we aren't using biased bitcode, then at least -expand-byval
706 # must be run to work with the PPAPI shim calling convention.
708 chain.add(RunOpt, 'expand.po', pass_list=['-expand-byval'])
709 chain.add(RunTranslate, 'o', mode='-c')
711 if cur_type == output_type:
716 # If we aren't using biased bitcode, then at least -expand-byval
717 # must be run to work with the PPAPI shim calling convention.
719 chain.add(RunOpt, 'expand.po', pass_list=['-expand-byval'])
720 chain.add(RunTranslate, 's', mode='-S')
722 if cur_type == output_type:
727 chain.add(RunCC, 's', mode='-E')
729 if output_type == 'pp':
731 if cur_type == output_type:
735 if cur_type == 's' and output_type == 'o':
736 chain.add(RunNativeAS, 'o')
738 if cur_type == output_type:
741 Log.Fatal("Unable to compile .%s to .%s", input_type, output_type)
744 tool = env.getone('SCRIPT_NAME')
746 if '--help-full' in argv:
748 env.update(EXTRA_ENV)
749 code, stdout, stderr = Run('"${CC}" -help',
750 redirect_stdout=subprocess.PIPE,
751 redirect_stderr=subprocess.STDOUT,
756 This is a "GCC-compatible" driver using clang under the hood.
758 Usage: %s [options] <inputs> ...
761 -o <file> Output to <file>.
762 -E Only run the preprocessor.
763 -S Generate bitcode assembly.
764 -c Generate bitcode object.
765 -I <dir> Add header search path.
766 -L <dir> Add library search path.
767 -D<key>[=<val>] Add definition for the preprocessor.
768 -W<id> Toggle warning <id>.
769 -f<feature> Enable <feature>.
770 -Wl,<arg> Pass <arg> to the linker.
771 -Xlinker <arg> Pass <arg> to the linker.
772 -Wt,<arg> Pass <arg> to the translator.
773 -Xtranslator <arg> Pass <arg> to the translator.
774 -Wp,<arg> Pass <arg> to the preprocessor.
775 -Xpreprocessor,<arg> Pass <arg> to the preprocessor.
776 -x <language> Treat subsequent input files as having type <language>.
777 -static Produce a static executable (the default).
778 -Bstatic Link subsequent libraries statically.
779 -Bdynamic Link subsequent libraries dynamically.
780 -fPIC Ignored (only used by translator backend)
781 (accepted for compatibility).
782 -pipe Ignored (for compatibility).
783 -O<n> Optimation level <n>: 0, 1, 2, 3, 4 or s.
784 -g Generate complete debug information.
785 -gline-tables-only Generate debug line-information only
786 (allowing for stack traces).
787 -flimit-debug-info Generate limited debug information.
788 -save-temps Keep intermediate compilation results.
789 -v Verbose output / show commands.
790 -h | --help Show this help.
791 --help-full Show underlying clang driver's help message
792 (warning: not all options supported).