diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-05-02 22:13:56 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-05-02 22:13:56 +0000 |
commit | b83074dfa3885da91543e54e7dcc0ac68e4e4a27 (patch) | |
tree | 0db9fafa795e50ba070af61ea0b7c80dba2b11c5 /tools/ccc/ccclib/Driver.py | |
parent | 08617b1b475e5ae9c61c9b3536cf712283647284 (diff) |
ccc is dead.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70649 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/ccc/ccclib/Driver.py')
-rw-r--r-- | tools/ccc/ccclib/Driver.py | 873 |
1 files changed, 0 insertions, 873 deletions
diff --git a/tools/ccc/ccclib/Driver.py b/tools/ccc/ccclib/Driver.py deleted file mode 100644 index 92f7c87ca0..0000000000 --- a/tools/ccc/ccclib/Driver.py +++ /dev/null @@ -1,873 +0,0 @@ -import os -import platform -import subprocess -import sys -import tempfile -from pprint import pprint - -### - -import Arguments -import Jobs -import HostInfo -import Phases -import Tools -import Types -import Util - -# FIXME: Clean up naming of options and arguments. Decide whether to -# rename Option and be consistent about use of Option/Arg. - -#### - -class Driver(object): - def __init__(self, driverName, driverDir): - self.driverName = driverName - self.driverDir = driverDir - self.hostInfo = None - self.parser = Arguments.OptionParser() - self.cccHostBits = self.cccHostMachine = None - self.cccHostSystem = self.cccHostRelease = None - self.cccCXX = False - self.cccEcho = False - self.cccNoClang = self.cccNoClangCXX = self.cccNoClangPreprocessor = False - self.cccClangArchs = None - - # Certain options suppress the 'no input files' warning. - self.suppressMissingInputWarning = False - - # Temporary files used in compilation, removed on exit. - self.tempFiles = [] - # Result files produced by compilation, removed on error. - self.resultFiles = [] - - # Host queries which can be forcibly over-riden by the user for - # testing purposes. - # - # FIXME: We should make sure these are drawn from a fixed set so - # that nothing downstream ever plays a guessing game. - - def getHostBits(self): - if self.cccHostBits: - return self.cccHostBits - - return platform.architecture()[0].replace('bit','') - - def getHostMachine(self): - if self.cccHostMachine: - return self.cccHostMachine - - machine = platform.machine() - # Normalize names. - if machine == 'Power Macintosh': - return 'ppc' - if machine == 'x86_64': - return 'i386' - return machine - - def getHostSystemName(self): - if self.cccHostSystem: - return self.cccHostSystem - - return platform.system().lower() - - def getHostReleaseName(self): - if self.cccHostRelease: - return self.cccHostRelease - - return platform.release() - - def getenvBool(self, name): - var = os.getenv(name) - if not var: - return False - - try: - return bool(int(var)) - except: - return False - - ### - - def getFilePath(self, name, toolChain=None): - tc = toolChain or self.toolChain - for p in tc.filePathPrefixes: - path = os.path.join(p, name) - if os.path.exists(path): - return path - return name - - def getProgramPath(self, name, toolChain=None): - tc = toolChain or self.toolChain - for p in tc.programPathPrefixes: - path = os.path.join(p, name) - if os.path.exists(path): - return path - return name - - ### - - def run(self, argv): - # FIXME: Things to support from environment: GCC_EXEC_PREFIX, - # COMPILER_PATH, LIBRARY_PATH, LPATH, CC_PRINT_OPTIONS, - # QA_OVERRIDE_GCC3_OPTIONS, ...? - - # FIXME: -V and -b processing - - # Handle some special -ccc- options used for testing which are - # only allowed at the beginning of the command line. - cccPrintOptions = False - cccPrintPhases = False - - # FIXME: How to handle override of host? ccc specific options? - # Abuse -b? - arg = os.getenv('CCC_ADD_ARGS') - if arg: - args = filter(None, map(str.strip, arg.split(','))) - argv = args + argv - - while argv and argv[0].startswith('-ccc-'): - fullOpt,argv = argv[0],argv[1:] - opt = fullOpt[5:] - - if opt == 'print-options': - cccPrintOptions = True - elif opt == 'print-phases': - cccPrintPhases = True - elif opt == 'cxx': - self.cccCXX = True - elif opt == 'echo': - self.cccEcho = True - - elif opt == 'no-clang': - self.cccNoClang = True - elif opt == 'no-clang-cxx': - self.cccNoClangCXX = True - elif opt == 'no-clang-cpp': - self.cccNoClangPreprocessor = True - elif opt == 'clang-archs': - self.cccClangArchs,argv = argv[0].split(','),argv[1:] - - elif opt == 'host-bits': - self.cccHostBits,argv = argv[0],argv[1:] - elif opt == 'host-machine': - self.cccHostMachine,argv = argv[0],argv[1:] - elif opt == 'host-system': - self.cccHostSystem,argv = argv[0],argv[1:] - elif opt == 'host-release': - self.cccHostRelease,argv = argv[0],argv[1:] - elif opt == 'host-triple': - # This is a complete hack, but only exists for testing - # compatibility with the new driver. We will be six - # feet under soon enough. - triple,argv = argv[0],argv[1:] - self.cccHostMachine,_,self.cccHostSystem = triple.split('-', 2) - if self.cccHostSystem.startswith('darwin'): - self.cccHostSystem = 'darwin' - self.cccHostRelease = '10.5.0' - if self.cccHostMachine == 'x86_64': - self.cccHostMachine = 'i386' - self.cccHostBits = '64' - elif self.cccHostMachine == 'i386': - self.cccHostBits = '32' - else: - raise Arguments.InvalidArgumentsError("invalid option: %r" % fullOpt) - - self.hostInfo = HostInfo.getHostInfo(self) - self.toolChain = self.hostInfo.getToolChain() - - args = self.parser.parseArgs(argv) - - # FIXME: Ho hum I have just realized -Xarch_ is broken. We really - # need to reparse the Arguments after they have been expanded by - # -Xarch. How is this going to work? - # - # Scratch that, we aren't going to do that; it really disrupts the - # organization, doesn't consistently work with gcc-dd, and is - # confusing. Instead we are going to enforce that -Xarch_ is only - # used with options which do not alter the driver behavior. Let's - # hope this is ok, because the current architecture is a little - # tied to it. - - if cccPrintOptions: - self.printOptions(args) - sys.exit(0) - - self.handleImmediateOptions(args) - - if self.hostInfo.useDriverDriver(): - phases = self.buildPipeline(args) - else: - phases = self.buildNormalPipeline(args) - - if cccPrintPhases: - self.printPhases(phases, args) - sys.exit(0) - - if 0: - print Util.pprint(phases) - - jobs = self.bindPhases(phases, args) - - # FIXME: We should provide some basic sanity checking of the - # pipeline as a "verification" sort of stage. For example, the - # pipeline should never end up writing to an output file in two - # places (I think). The pipeline should also never end up writing - # to an output file that is an input. - # - # This is intended to just be a "verify" step, not a functionality - # step. It should catch things like the driver driver not - # preventing -save-temps, but it shouldn't change behavior (so we - # can turn it off in Release-Asserts builds). - - # Print in -### syntax. - hasHashHashHash = args.getLastArg(self.parser.hashHashHashOption) - if hasHashHashHash: - self.claim(hasHashHashHash) - for j in jobs.iterjobs(): - if isinstance(j, Jobs.Command): - print >>sys.stderr, ' "%s"' % '" "'.join(j.getArgv()) - elif isinstance(j, Jobs.PipedJob): - for c in j.commands: - print >>sys.stderr, ' "%s" %c' % ('" "'.join(c.getArgv()), - "| "[c is j.commands[-1]]) - elif not isinstance(j, JobList): - raise ValueError,'Encountered unknown job.' - sys.exit(0) - - try: - try: - self.executeJobs(args, jobs) - except: - if not args.getLastArg(self.parser.saveTempsOption): - # Fail if removing a result fails. - self.removeFiles(self.resultFiles, failOnError=True) - raise - finally: - # Ignore failures in removing temporary files - self.removeFiles(self.tempFiles, failOnError=False) - - def removeFiles(self, fileList, failOnError=False): - for f in fileList: - try: - os.remove(f) - except OSError,e: - if failOnError: - import errno - if e.errno != errno.ENOENT: - raise - except: - if failOnError: - raise - - def executeJobs(self, args, jobs): - vArg = args.getLastArg(self.parser.vOption) - for j in jobs.iterjobs(): - if isinstance(j, Jobs.Command): - if vArg or self.cccEcho: - print >>sys.stderr, ' '.join(map(str,j.getArgv())) - sys.stderr.flush() - p = self.startSubprocess(j.getArgv(), j.executable) - res = p.wait() - if res: - sys.exit(res) - - elif isinstance(j, Jobs.PipedJob): - procs = [] - for sj in j.commands: - if vArg or self.cccEcho: - print >> sys.stderr, ' '.join(map(str,sj.getArgv())) - sys.stdout.flush() - - if not procs: - stdin = None - else: - stdin = procs[-1].stdout - if sj is j.commands[-1]: - stdout = None - else: - stdout = subprocess.PIPE - - procs.append(self.startSubprocess(sj.getArgv(), sj.executable, - stdin=stdin, - stdout=stdout)) - - for proc in procs: - res = proc.wait() - if res: - sys.exit(res) - else: - raise ValueError,'Encountered unknown job.' - - def startSubprocess(self, argv, executable, **kwargs): - try: - return subprocess.Popen(argv, executable=executable, **kwargs) - except OSError, e: - self.warning("error trying to exec '%s': %s" % - (executable, e.args[1])) - sys.exit(1) - - def claim(self, option): - # FIXME: Move to OptionList once introduced and implement. - pass - - def warning(self, message): - print >>sys.stderr,'%s: %s' % (self.driverName, message) - - def printOptions(self, args): - for i,arg in enumerate(args): - if isinstance(arg, Arguments.MultipleValuesArg): - values = list(args.getValues(arg)) - elif isinstance(arg, Arguments.ValueArg): - values = [args.getValue(arg)] - elif isinstance(arg, Arguments.JoinedAndSeparateValuesArg): - values = [args.getJoinedValue(arg), args.getSeparateValue(arg)] - else: - values = [] - print 'Option %d - Name: "%s", Values: {%s}' % (i, arg.opt.name, - ', '.join(['"%s"' % v - for v in values])) - - def printPhases(self, phases, args): - def printPhase(p, f, steps): - if p in steps: - return steps[p] - - if isinstance(p, Phases.InputAction): - phaseName = 'input' - inputStr = '"%s"' % args.getValue(p.filename) - elif isinstance(p, Phases.BindArchAction): - phaseName = 'bind-arch' - inputs = [printPhase(i, f, steps) - for i in p.inputs] - inputStr = '"%s", {%s}' % (args.getValue(p.arch), - ', '.join(map(str, inputs))) - else: - phaseName = p.phase.name - inputs = [printPhase(i, f, steps) - for i in p.inputs] - inputStr = '{%s}' % ', '.join(map(str, inputs)) - steps[p] = index = len(steps) - print "%d: %s, %s, %s" % (index,phaseName,inputStr,p.type.name) - return index - steps = {} - for phase in phases: - printPhase(phase, sys.stdout, steps) - - def printVersion(self): - # FIXME: Print default target triple. - vers = '$HeadURL$' - vers = vers.split('/tools/ccc')[0] - vers = vers.split('/clang/tools/clang')[0] - vers = ' (' + vers[10:] + ')' - print >>sys.stderr,'ccc version 1.0' + vers - - def handleImmediateOptions(self, args): - # FIXME: Some driver Arguments are consumed right off the bat, - # like -dumpversion. Currently the gcc-dd handles these - # poorly, so we should be ok handling them upfront instead of - # after driver-driver level dispatching. - # - # FIXME: The actual order of these options in gcc is all over the - # place. The -dump ones seem to be first and in specification - # order, but there are other levels of precedence. For example, - # -print-search-dirs is evaluated before -print-prog-name=, - # regardless of order (and the last instance of -print-prog-name= - # wins verse itself). - # - # FIXME: Do we want to report "argument unused" type errors in the - # presence of things like -dumpmachine and -print-search-dirs? - # Probably not. - if (args.getLastArg(self.parser.vOption) or - args.getLastArg(self.parser.hashHashHashOption)): - self.printVersion() - self.suppressMissingInputWarning = True - - arg = args.getLastArg(self.parser.printFileNameOption) - if arg: - print self.getFilePath(args.getValue(arg)) - sys.exit(0) - - arg = args.getLastArg(self.parser.printProgNameOption) - if arg: - print self.getProgramPath(args.getValue(arg)) - sys.exit(0) - - arg = args.getLastArg(self.parser.printLibgccFileNameOption) - if arg: - print self.getFilePath('libgcc.a') - sys.exit(0) - - def buildNormalPipeline(self, args): - hasAnalyze = args.getLastArg(self.parser.analyzeOption) - hasCombine = args.getLastArg(self.parser.combineOption) - hasEmitLLVM = args.getLastArg(self.parser.emitLLVMOption) - hasSyntaxOnly = args.getLastArg(self.parser.syntaxOnlyOption) - hasDashC = args.getLastArg(self.parser.cOption) - hasDashE = args.getLastArg(self.parser.EOption) - hasDashS = args.getLastArg(self.parser.SOption) - hasDashM = args.getLastArg(self.parser.MOption) - hasDashMM = args.getLastArg(self.parser.MMOption) - - inputType = None - inputTypeOpt = None - inputs = [] - for a in args: - if a.opt is self.parser.inputOption: - inputValue = args.getValue(a) - if inputType is None: - base,ext = os.path.splitext(inputValue) - # stdin is handled specially. - if inputValue == '-': - if args.getLastArg(self.parser.EOption): - # Treat as a C input needing preprocessing - # (or Obj-C if over-ridden below). - klass = Types.CType - else: - raise Arguments.InvalidArgumentsError("-E or -x required when input is from standard input") - elif ext and ext in Types.kTypeSuffixMap: - klass = self.hostInfo.lookupTypeForExtension(ext) - else: - # FIXME: Its not clear why we shouldn't just - # revert to unknown. I think this is more likely a - # bug / unintended behavior in gcc. Not very - # important though. - klass = Types.ObjectType - - # -ObjC and -ObjC++ over-ride the default - # language, but only for "source files". We - # just treat everything that isn't a linker - # input as a source file. - # - # FIXME: Clean this up if we move the phase - # sequence into the type. - if klass is not Types.ObjectType: - if args.getLastArg(self.parser.ObjCOption): - klass = Types.ObjCType - elif args.getLastArg(self.parser.ObjCXXOption): - klass = Types.ObjCType - else: - assert inputTypeOpt is not None - self.claim(inputTypeOpt) - klass = inputType - - # Check that the file exists. It isn't clear this is - # worth doing, since the tool presumably does this - # anyway, and this just adds an extra stat to the - # equation, but this is gcc compatible. - if inputValue != '-' and not os.path.exists(inputValue): - self.warning("%s: No such file or directory" % inputValue) - else: - inputs.append((klass, a)) - elif a.opt.isLinkerInput: - # Treat as a linker input. - # - # FIXME: This might not be good enough. We may - # need to introduce another type for this case, so - # that other code which needs to know the inputs - # handles this properly. Best not to try and lipo - # this, for example. - inputs.append((Types.ObjectType, a)) - elif a.opt is self.parser.xOption: - inputTypeOpt = a - value = args.getValue(a) - if value in Types.kTypeSpecifierMap: - inputType = Types.kTypeSpecifierMap[value] - else: - # FIXME: How are we going to handle diagnostics. - self.warning("language %s not recognized" % value) - - # FIXME: Its not clear why we shouldn't just - # revert to unknown. I think this is more likely a - # bug / unintended behavior in gcc. Not very - # important though. - inputType = Types.ObjectType - - # We claim things here so that options for which we silently allow - # override only ever claim the used option. - if hasCombine: - self.claim(hasCombine) - - finalPhase = Phases.Phase.eOrderPostAssemble - finalPhaseOpt = None - - # Determine what compilation mode we are in. - if hasDashE or hasDashM or hasDashMM: - finalPhase = Phases.Phase.eOrderPreprocess - finalPhaseOpt = hasDashE - elif (hasAnalyze or hasSyntaxOnly or - hasEmitLLVM or hasDashS): - finalPhase = Phases.Phase.eOrderCompile - finalPhaseOpt = (hasAnalyze or hasSyntaxOnly or - hasEmitLLVM or hasDashS) - elif hasDashC: - finalPhase = Phases.Phase.eOrderAssemble - finalPhaseOpt = hasDashC - - if finalPhaseOpt: - self.claim(finalPhaseOpt) - - # Reject -Z* at the top level for now. - arg = args.getLastArg(self.parser.ZOption) - if arg: - raise Arguments.InvalidArgumentsError("%s: unsupported use of internal gcc option" % ' '.join(args.render(arg))) - - if not inputs and not self.suppressMissingInputWarning: - raise Arguments.InvalidArgumentsError("no input files") - - actions = [] - linkerInputs = [] - # FIXME: This is gross. - linkPhase = Phases.LinkPhase() - for klass,input in inputs: - # Figure out what step to start at. - - # FIXME: This should be part of the input class probably? - # Altough it doesn't quite fit there either, things like - # asm-with-preprocess don't easily fit into a linear scheme. - - # FIXME: I think we are going to end up wanting to just build - # a simple FSA which we run the inputs down. - sequence = [] - if klass.preprocess: - sequence.append(Phases.PreprocessPhase()) - if klass == Types.ObjectType: - sequence.append(linkPhase) - elif klass.onlyAssemble: - sequence.extend([Phases.AssemblePhase(), - linkPhase]) - elif klass.onlyPrecompile: - sequence.append(Phases.PrecompilePhase()) - elif hasAnalyze: - sequence.append(Phases.AnalyzePhase()) - elif hasSyntaxOnly: - sequence.append(Phases.SyntaxOnlyPhase()) - elif hasEmitLLVM: - sequence.append(Phases.EmitLLVMPhase()) - else: - sequence.extend([Phases.CompilePhase(), - Phases.AssemblePhase(), - linkPhase]) - - if sequence[0].order > finalPhase: - assert finalPhaseOpt and finalPhaseOpt.opt - # FIXME: Explain what type of input file is. Or just match - # gcc warning. - self.warning("%s: %s input file unused when %s is present" % (args.getValue(input), - sequence[0].name, - finalPhaseOpt.opt.name)) - else: - # Build the pipeline for this file. - - current = Phases.InputAction(input, klass) - for transition in sequence: - # If the current action produces no output, or we are - # past what the user requested, we are done. - if (current.type is Types.NothingType or - transition.order > finalPhase): - break - else: - if isinstance(transition, Phases.PreprocessPhase): - assert isinstance(klass.preprocess, Types.InputType) - current = Phases.JobAction(transition, - [current], - klass.preprocess) - elif isinstance(transition, Phases.PrecompilePhase): - current = Phases.JobAction(transition, - [current], - Types.PCHType) - elif isinstance(transition, Phases.AnalyzePhase): - output = Types.PlistType - current = Phases.JobAction(transition, - [current], - output) - elif isinstance(transition, Phases.SyntaxOnlyPhase): - output = Types.NothingType - current = Phases.JobAction(transition, - [current], - output) - elif isinstance(transition, Phases.EmitLLVMPhase): - if hasDashS: - output = Types.LLVMAsmType - else: - output = Types.LLVMBCType - current = Phases.JobAction(transition, - [current], - output) - elif isinstance(transition, Phases.CompilePhase): - output = Types.AsmTypeNoPP - current = Phases.JobAction(transition, - [current], - output) - elif isinstance(transition, Phases.AssemblePhase): - current = Phases.JobAction(transition, - [current], - Types.ObjectType) - elif transition is linkPhase: - linkerInputs.append(current) - current = None - break - else: - raise RuntimeError,'Unrecognized transition: %s.' % transition - pass - - if current is not None: - assert not isinstance(current, Phases.InputAction) - actions.append(current) - - if linkerInputs: - actions.append(Phases.JobAction(linkPhase, - linkerInputs, - Types.ImageType)) - - return actions - - def buildPipeline(self, args): - # FIXME: We need to handle canonicalization of the specified arch. - - archs = {} - hasDashM = args.getLastArg(self.parser.MGroup) - hasSaveTemps = args.getLastArg(self.parser.saveTempsOption) - for arg in args: - if arg.opt is self.parser.archOption: - # FIXME: Canonicalize this. - archName = args.getValue(arg) - archs[archName] = arg - - archs = archs.values() - if not archs: - archs.append(args.makeSeparateArg(self.hostInfo.getArchName(args), - self.parser.archOption)) - - actions = self.buildNormalPipeline(args) - - # FIXME: Use custom exception for this. - # - # FIXME: We killed off some others but these aren't yet detected in - # a functional manner. If we added information to jobs about which - # "auxiliary" files they wrote then we could detect the conflict - # these cause downstream. - if len(archs) > 1: - if hasDashM: - raise Arguments.InvalidArgumentsError("Cannot use -M options with multiple arch flags.") - elif hasSaveTemps: - raise Arguments.InvalidArgumentsError("Cannot use -save-temps with multiple arch flags.") - - # Execute once per arch. - finalActions = [] - for p in actions: - # Make sure we can lipo this kind of output. If not (and it - # is an actual output) then we disallow, since we can't - # create an output file with the right name without - # overwriting it. We could remove this oddity by just - # changing the output names to include the arch, which would - # also fix -save-temps. Compatibility wins for now. - # - # FIXME: Is this error substantially less useful than - # gcc-dd's? The main problem is that "Cannot use compiler - # output with multiple arch flags" won't make sense to most - # developers. - if (len(archs) > 1 and - p.type not in (Types.NothingType,Types.ObjectType,Types.ImageType)): - raise Arguments.InvalidArgumentsError('Cannot use %s output with multiple arch flags.' % p.type.name) - - inputs = [] - for arch in archs: - inputs.append(Phases.BindArchAction(p, arch)) - - # Lipo if necessary. We do it this way because we need to set - # the arch flag so that -Xarch_ gets rewritten. - if len(inputs) == 1 or p.type == Types.NothingType: - finalActions.extend(inputs) - else: - finalActions.append(Phases.JobAction(Phases.LipoPhase(), - inputs, - p.type)) - - return finalActions - - def bindPhases(self, phases, args): - jobs = Jobs.JobList() - - finalOutput = args.getLastArg(self.parser.oOption) - hasSaveTemps = args.getLastArg(self.parser.saveTempsOption) - hasNoIntegratedCPP = args.getLastArg(self.parser.noIntegratedCPPOption) - hasTraditionalCPP = args.getLastArg(self.parser.traditionalCPPOption) - hasPipe = args.getLastArg(self.parser.pipeOption) - - # We claim things here so that options for which we silently allow - # override only ever claim the used option. - if hasPipe: - self.claim(hasPipe) - # FIXME: Hack, override -pipe till we support it. - if hasSaveTemps: - self.warning('-pipe ignored because -save-temps specified') - hasPipe = None - # Claim these here. Its not completely accurate but any warnings - # about these being unused are likely to be noise anyway. - if hasSaveTemps: - self.claim(hasSaveTemps) - - if hasTraditionalCPP: - self.claim(hasTraditionalCPP) - elif hasNoIntegratedCPP: - self.claim(hasNoIntegratedCPP) - - # FIXME: Move to... somewhere else. - class InputInfo: - def __init__(self, source, type, baseInput): - self.source = source - self.type = type - self.baseInput = baseInput - - def __repr__(self): - return '%s(%r, %r, %r)' % (self.__class__.__name__, - self.source, self.type, self.baseInput) - - def isOriginalInput(self): - return self.source is self.baseInput - - def createJobs(tc, phase, - canAcceptPipe=False, atTopLevel=False, arch=None, - tcArgs=None, linkingOutput=None): - if isinstance(phase, Phases.InputAction): - return InputInfo(phase.filename, phase.type, phase.filename) - elif isinstance(phase, Phases.BindArchAction): - archName = args.getValue(phase.arch) - tc = self.hostInfo.getToolChainForArch(archName) - return createJobs(tc, phase.inputs[0], - canAcceptPipe, atTopLevel, phase.arch, - None, linkingOutput) - - if tcArgs is None: - tcArgs = tc.translateArgs(args, arch) - - assert isinstance(phase, Phases.JobAction) - tool = tc.selectTool(phase) - - # See if we should use an integrated CPP. We only use an - # integrated cpp when we have exactly one input, since this is - # the only use case we care about. - useIntegratedCPP = False - inputList = phase.inputs - if (not hasNoIntegratedCPP and - not hasTraditionalCPP and - not hasSaveTemps and - tool.hasIntegratedCPP()): - if (len(phase.inputs) == 1 and - isinstance(phase.inputs[0], Phases.JobAction) and - isinstance(phase.inputs[0].phase, Phases.PreprocessPhase)): - useIntegratedCPP = True - inputList = phase.inputs[0].inputs - - # Only try to use pipes when exactly one input. - attemptToPipeInput = len(inputList) == 1 and tool.acceptsPipedInput() - inputs = [createJobs(tc, p, attemptToPipeInput, False, - arch, tcArgs, linkingOutput) - for p in inputList] - - # Determine if we should output to a pipe. - canOutputToPipe = canAcceptPipe and tool.canPipeOutput() - outputToPipe = False - if canOutputToPipe: - # Some things default to writing to a pipe if the final - # phase and there was no user override. - # - # FIXME: What is the best way to handle this? - if atTopLevel: - if (isinstance(phase.phase, Phases.PreprocessPhase) and - not finalOutput): - outputToPipe = True - elif hasPipe: - outputToPipe = True - - # Figure out where to put the job (pipes). - jobList = jobs - if isinstance(inputs[0].source, Jobs.PipedJob): - jobList = inputs[0].source - - baseInput = inputs[0].baseInput - output,jobList = self.getOutputName(phase, outputToPipe, jobs, jobList, baseInput, - args, atTopLevel, hasSaveTemps, finalOutput) - tool.constructJob(phase, arch, jobList, inputs, output, phase.type, - tcArgs, linkingOutput) - - return InputInfo(output, phase.type, baseInput) - - # It is an error to provide a -o option if we are making multiple - # output files. - if finalOutput and len([a for a in phases if a.type is not Types.NothingType]) > 1: - raise Arguments.InvalidArgumentsError("cannot specify -o when generating multiple files") - - for phase in phases: - # If we are linking an image for multiple archs then the - # linker wants -arch_multiple and -final_output <final image - # name>. Unfortunately this requires some gross contortions. - # - # FIXME: This is a hack; find a cleaner way to integrate this - # into the process. - linkingOutput = None - if (isinstance(phase, Phases.JobAction) and - isinstance(phase.phase, Phases.LipoPhase)): - finalOutput = args.getLastArg(self.parser.oOption) - if finalOutput: - linkingOutput = finalOutput - else: - linkingOutput = args.makeSeparateArg('a.out', - self.parser.oOption) - - createJobs(self.toolChain, phase, - canAcceptPipe=True, atTopLevel=True, - linkingOutput=linkingOutput) - - return jobs - - def getOutputName(self, phase, outputToPipe, jobs, jobList, baseInput, - args, atTopLevel, hasSaveTemps, finalOutput): - # Figure out where to put the output. - if phase.type == Types.NothingType: - output = None - elif outputToPipe: - if isinstance(jobList, Jobs.PipedJob): - output = jobList - else: - jobList = output = Jobs.PipedJob([]) - jobs.addJob(output) - else: - # Figure out what the derived output location would be. - if phase.type is Types.ImageType: - namedOutput = "a.out" - else: - assert phase.type.tempSuffix is not None - inputName = args.getValue(baseInput) - if phase.type.appendSuffix: - namedOutput = inputName + '.' + phase.type.tempSuffix - else: - base,_ = os.path.splitext(inputName) - namedOutput = base + '.' + phase.type.tempSuffix - - isTemp = False - # Output to user requested destination? - if atTopLevel and finalOutput: - output = finalOutput - self.resultFiles.append(args.getValue(finalOutput)) - - # Contruct a named destination? - elif atTopLevel or hasSaveTemps: - # As an annoying special case, pch generation - # doesn't strip the pathname. - if phase.type is Types.PCHType: - outputName = namedOutput - else: - outputName = os.path.basename(namedOutput) - output = args.makeSeparateArg(outputName, - self.parser.oOption) - self.resultFiles.append(outputName) - - else: - # Output to temp file... - fd,filename = tempfile.mkstemp(suffix='.'+phase.type.tempSuffix) - output = args.makeSeparateArg(filename, - self.parser.oOption) - self.tempFiles.append(filename) - return output,jobList |