#!/usr/bin/env python # # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## # # This script attempts to be a drop-in replacement for gcc. # ##===----------------------------------------------------------------------===## import sys import subprocess def error(message): print >> sys.stderr, 'ccc: ' + message sys.exit(1) def quote(arg): if '"' in arg: return repr(arg) return arg def run(args): print ' '.join(map(quote, args)) code = subprocess.call(args) if code > 255: code = 1 if code: sys.exit(code) def preprocess(args): command = 'clang -E'.split() run(command + args) def compile(args): command = 'clang -emit-llvm-bc'.split() run(command + args) def link(args): command = 'llvm-ld -native -disable-internalize'.split() run(command + args) def extension(path): return path.split(".")[-1] def changeextension(path, newext): i = path.rfind('.') if i < 0: return path j = path.rfind('/', 0, i) print path if j < 0: return path[:i] + "." + newext return path[j+1:i] + "." + newext def inferlanguage(extension): if extension == "c": return "c" elif extension in ["cpp", "cc"]: return "c++" elif extension == "i": return "c-cpp-output" elif extension == "m": return "objective-c" elif extension == "mi": return "objective-c-cpp-output" else: return "unknown" def main(args): action = 'link' output = '' compile_opts = [] link_opts = [] files = [] save_temps = 0 language = '' i = 0 while i < len(args): arg = args[i] # Modes ccc supports if arg == '-E': action = 'preprocess' if arg == '-c': action = 'compile' if arg.startswith('-print-prog-name'): action = 'print-prog-name' if arg == '-save-temps': save_temps = 1 # Options with no arguments that should pass through if arg in ['-v']: compile_opts.append(arg) link_opts.append(arg) # Options with one argument that should be ignored if arg in ['--param', '-u']: i += 1 # Preprocessor options with one argument that should be ignored if arg in ['-MT', '-MF']: i += 1 # Prefix matches for the compile mode if arg[:2] in ['-D', '-I', '-U', '-F']: if not arg[2:]: arg += args[i+1] i += 1 compile_opts.append(arg) if arg[:5] in ['-std=']: compile_opts.append(arg) # Options with one argument that should pass through to compiler if arg in [ '-include', '-idirafter', '-iprefix', '-iquote', '-isystem', '-iwithprefix', '-iwithprefixbefore']: compile_opts.append(arg) compile_opts.append(args[i+1]) i += 1 # Options with one argument that should pass through if arg in ['-framework']: link_opts.append(arg) link_opts.append(args[i+1]) i += 1 # Options with one argument that should pass through to both if arg in ['-isysroot', '-arch']: compile_opts.append(arg) compile_opts.append(args[i+1]) link_opts.append(arg) link_opts.append(args[i+1]) i += 1 # Prefix matches for the link mode if arg[:2] in ['-l', '-L', '-F', '-R']: link_opts.append(arg) # Enable threads if arg == '-pthread': link_opts.append('-lpthread') # Input files if arg == '-filelist': f = open(args[i+1]) for line in f: files.append(line.strip()) f.close() i += 1 if arg == '-x': language = args[i+1] compile_opts.append(arg) compile_opts.append(args[i+1]) i += 1 if arg[0] != '-': files.append(arg) # Output file if arg == '-o': output = args[i+1] i += 1 i += 1 if action == 'print-prog-name': # assume we can handle everything print sys.argv[0] return if not files: error('no input files') if action == 'preprocess' or save_temps: for i, file in enumerate(files): if not language: language = inferlanguage(extension(file)) if save_temps and action != 'preprocess': # Need a temporary output file if language == 'c': poutput = changeextension(file, "i"); elif language == 'objective-c': poutput = changeextension(file, "mi"); else: poutput = changeextension(file, "tmp." + extension(file)) files[i] = poutput else: poutput = output if poutput: args = ['-x', language, '-o', poutput, file] + compile_opts else: args = ['-x', language, file] + compile_opts preprocess(args) # Discard the explicit language after used once language = '' if action == 'compile' or save_temps: for i, file in enumerate(files): if not language: language = inferlanguage(extension(file)) if save_temps and action != "compile": # Need a temporary output file coutput = changeextension(file, "o"); files[i] = coutput elif not output: coutput = changeextension(file, "o") else: coutput = output args = ['-x', language, '-o', coutput, file] + compile_opts compile(args) language = '' if action == 'link': for i, file in enumerate(files): ext = extension(file) if ext != "o" and ext != "a" and ext != "so": out = changeextension(file, "o") args = ['-o', out, file] + compile_opts compile(args) files[i] = out if not output: output = 'a.out' args = ['-o', output] + link_opts + files link(args) if __name__ == '__main__': main(sys.argv[1:])