forked from OSchip/llvm-project
ccc: Allow downstream tools to be aware of final output name.
- This is a hack to allow the Darwin linker to get -final_output when doing universal builds; the mechanism should be generalized. - Handle multiple redundant -arch arguments correctly. - Forward -arch_multiple and -final_output to gcc when necessary. - Simplified implementation of derived gcc tools. llvm-svn: 62618
This commit is contained in:
parent
f1e873a221
commit
de46097847
|
@ -521,14 +521,17 @@ class Driver(object):
|
|||
def buildPipeline(self, args):
|
||||
# FIXME: We need to handle canonicalization of the specified arch.
|
||||
|
||||
archs = []
|
||||
archs = {}
|
||||
hasDashM = args.getLastArg(self.parser.MGroup)
|
||||
hasSaveTemps = (args.getLastArg(self.parser.saveTempsOption) or
|
||||
args.getLastArg(self.parser.saveTempsOption2))
|
||||
for arg in args:
|
||||
if arg.opt is self.parser.archOption:
|
||||
archs.append(arg)
|
||||
|
||||
# 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))
|
||||
|
@ -578,18 +581,6 @@ class Driver(object):
|
|||
inputs,
|
||||
p.type))
|
||||
|
||||
# FIXME: We need to add -Wl,arch_multiple and -Wl,final_output in
|
||||
# certain cases. This may be icky because we need to figure out the
|
||||
# mode first. Current plan is to hack on the pipeline once it is built
|
||||
# and we know what is being spit out. This avoids having to handling
|
||||
# things like -c and -combine in multiple places.
|
||||
#
|
||||
# The annoying one of these is -Wl,final_output because it involves
|
||||
# communication across different phases.
|
||||
#
|
||||
# Hopefully we can do this purely as part of the binding, but
|
||||
# leaving comment here for now until it is clear this works.
|
||||
|
||||
return finalActions
|
||||
|
||||
def bindPhases(self, phases, args):
|
||||
|
@ -636,7 +627,7 @@ class Driver(object):
|
|||
|
||||
def createJobs(tc, phase,
|
||||
canAcceptPipe=False, atTopLevel=False, arch=None,
|
||||
tcArgs=None):
|
||||
tcArgs=None, linkingOutput=None):
|
||||
if isinstance(phase, Phases.InputAction):
|
||||
return InputInfo(phase.filename, phase.type, phase.filename)
|
||||
elif isinstance(phase, Phases.BindArchAction):
|
||||
|
@ -644,7 +635,7 @@ class Driver(object):
|
|||
tc = self.hostInfo.getToolChainForArch(archName)
|
||||
return createJobs(tc, phase.inputs[0],
|
||||
canAcceptPipe, atTopLevel, phase.arch,
|
||||
tcArgs=None)
|
||||
None, linkingOutput)
|
||||
|
||||
if tcArgs is None:
|
||||
tcArgs = tc.translateArgs(args, arch)
|
||||
|
@ -669,7 +660,8 @@ class Driver(object):
|
|||
|
||||
# Only try to use pipes when exactly one input.
|
||||
canAcceptPipe = len(inputList) == 1 and tool.acceptsPipedInput()
|
||||
inputs = [createJobs(tc, p, canAcceptPipe, False, arch, tcArgs)
|
||||
inputs = [createJobs(tc, p, canAcceptPipe, False,
|
||||
arch, tcArgs, linkingOutput)
|
||||
for p in inputList]
|
||||
|
||||
# Determine if we should output to a pipe.
|
||||
|
@ -691,51 +683,12 @@ class Driver(object):
|
|||
jobList = jobs
|
||||
if canAcceptPipe and isinstance(inputs[0].source, Jobs.PipedJob):
|
||||
jobList = inputs[0].source
|
||||
|
||||
# Figure out where to put the output.
|
||||
|
||||
baseInput = inputs[0].baseInput
|
||||
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.
|
||||
#
|
||||
# FIXME: gcc has some special case in here so that it doesn't
|
||||
# create output files if they would conflict with an input.
|
||||
if phase.type is Types.ImageType:
|
||||
namedOutput = "a.out"
|
||||
else:
|
||||
inputName = args.getValue(baseInput)
|
||||
base,_ = os.path.splitext(inputName)
|
||||
assert phase.type.tempSuffix is not None
|
||||
namedOutput = base + '.' + phase.type.tempSuffix
|
||||
|
||||
# Output to user requested destination?
|
||||
if atTopLevel and finalOutput:
|
||||
output = 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)
|
||||
else:
|
||||
# Output to temp file...
|
||||
fd,filename = tempfile.mkstemp(suffix='.'+phase.type.tempSuffix)
|
||||
output = args.makeSeparateArg(filename,
|
||||
self.parser.oOption)
|
||||
|
||||
output = self.getOutputName(phase, outputToPipe, jobs, jobList, baseInput,
|
||||
args, atTopLevel, hasSaveTemps, finalOutput)
|
||||
tool.constructJob(phase, arch, jobList, inputs, output, phase.type,
|
||||
tcArgs)
|
||||
tcArgs, linkingOutput)
|
||||
|
||||
return InputInfo(output, phase.type, baseInput)
|
||||
|
||||
|
@ -745,7 +698,68 @@ class Driver(object):
|
|||
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)
|
||||
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.
|
||||
#
|
||||
# FIXME: gcc has some special case in here so that it doesn't
|
||||
# create output files if they would conflict with an input.
|
||||
if phase.type is Types.ImageType:
|
||||
namedOutput = "a.out"
|
||||
else:
|
||||
inputName = args.getValue(baseInput)
|
||||
base,_ = os.path.splitext(inputName)
|
||||
assert phase.type.tempSuffix is not None
|
||||
namedOutput = base + '.' + phase.type.tempSuffix
|
||||
|
||||
# Output to user requested destination?
|
||||
if atTopLevel and finalOutput:
|
||||
output = 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)
|
||||
else:
|
||||
# Output to temp file...
|
||||
fd,filename = tempfile.mkstemp(suffix='.'+phase.type.tempSuffix)
|
||||
output = args.makeSeparateArg(filename,
|
||||
self.parser.oOption)
|
||||
return output
|
||||
|
|
|
@ -24,15 +24,17 @@ class Tool(object):
|
|||
return not not (self.flags & Tool.eFlagsIntegratedCPP)
|
||||
|
||||
class GCC_Common_Tool(Tool):
|
||||
def getGCCExtraArgs(self):
|
||||
return []
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist,
|
||||
extraArgs):
|
||||
output, outputType, arglist, linkingOutput):
|
||||
cmd_args = []
|
||||
for arg in arglist.args:
|
||||
if arg.opt.forwardToGCC():
|
||||
cmd_args.extend(arglist.render(arg))
|
||||
|
||||
cmd_args.extend(extraArgs)
|
||||
cmd_args.extend(self.getGCCExtraArgs())
|
||||
if arch:
|
||||
cmd_args.extend(arglist.render(arch))
|
||||
if isinstance(output, Jobs.PipedJob):
|
||||
|
@ -42,6 +44,12 @@ class GCC_Common_Tool(Tool):
|
|||
else:
|
||||
cmd_args.extend(arglist.render(output))
|
||||
|
||||
if (isinstance(self, GCC_LinkTool) and
|
||||
linkingOutput):
|
||||
cmd_args.append('-Wl,-arch_multiple')
|
||||
cmd_args.append('-Wl,-final_output,' +
|
||||
arglist.getValue(linkingOutput))
|
||||
|
||||
# Only pass -x if gcc will understand it; otherwise hope gcc
|
||||
# understands the suffix correctly. The main use case this
|
||||
# would go wrong in is for linker inputs if they happened to
|
||||
|
@ -74,11 +82,8 @@ class GCC_PreprocessTool(GCC_Common_Tool):
|
|||
(Tool.eFlagsPipedInput |
|
||||
Tool.eFlagsPipedOutput))
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
return super(GCC_PreprocessTool, self).constructJob(phase, arch, jobs, inputs,
|
||||
output, outputType, arglist,
|
||||
['-E'])
|
||||
def getGCCExtraArgs(self):
|
||||
return ['-E']
|
||||
|
||||
class GCC_CompileTool(GCC_Common_Tool):
|
||||
def __init__(self):
|
||||
|
@ -87,11 +92,8 @@ class GCC_CompileTool(GCC_Common_Tool):
|
|||
Tool.eFlagsPipedOutput |
|
||||
Tool.eFlagsIntegratedCPP))
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
return super(GCC_CompileTool, self).constructJob(phase, arch, jobs, inputs,
|
||||
output, outputType, arglist,
|
||||
['-S'])
|
||||
def getGCCExtraArgs(self):
|
||||
return ['-S']
|
||||
|
||||
class GCC_PrecompileTool(GCC_Common_Tool):
|
||||
def __init__(self):
|
||||
|
@ -99,11 +101,21 @@ class GCC_PrecompileTool(GCC_Common_Tool):
|
|||
(Tool.eFlagsPipedInput |
|
||||
Tool.eFlagsIntegratedCPP))
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
return super(GCC_PrecompileTool, self).constructJob(phase, arch, jobs, inputs,
|
||||
output, outputType, arglist,
|
||||
[])
|
||||
def getGCCExtraArgs(self):
|
||||
return []
|
||||
|
||||
class GCC_AssembleTool(GCC_Common_Tool):
|
||||
def __init__(self):
|
||||
# We can't generally assume the assembler can take or output
|
||||
# on pipes.
|
||||
super(GCC_AssembleTool, self).__init__('gcc (as)')
|
||||
|
||||
def getGCCExtraArgs(self):
|
||||
return ['-c']
|
||||
|
||||
class GCC_LinkTool(GCC_Common_Tool):
|
||||
def __init__(self):
|
||||
super(GCC_LinkTool, self).__init__('gcc (ld)')
|
||||
|
||||
class Darwin_AssembleTool(Tool):
|
||||
def __init__(self, toolChain):
|
||||
|
@ -112,7 +124,7 @@ class Darwin_AssembleTool(Tool):
|
|||
self.toolChain = toolChain
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
output, outputType, arglist, linkingOutput):
|
||||
assert len(inputs) == 1
|
||||
assert outputType is Types.ObjectType
|
||||
|
||||
|
@ -150,28 +162,6 @@ class Darwin_AssembleTool(Tool):
|
|||
jobs.addJob(Jobs.Command(self.toolChain.getProgramPath('as'),
|
||||
cmd_args))
|
||||
|
||||
class GCC_AssembleTool(GCC_Common_Tool):
|
||||
def __init__(self):
|
||||
# We can't generally assume the assembler can take or output
|
||||
# on pipes.
|
||||
super(GCC_AssembleTool, self).__init__('gcc (as)')
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
return super(GCC_AssembleTool, self).constructJob(phase, arch, jobs, inputs,
|
||||
output, outputType, arglist,
|
||||
['-c'])
|
||||
|
||||
class GCC_LinkTool(GCC_Common_Tool):
|
||||
def __init__(self):
|
||||
super(GCC_LinkTool, self).__init__('gcc (ld)')
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
return super(GCC_LinkTool, self).constructJob(phase, arch, jobs, inputs,
|
||||
output, outputType, arglist,
|
||||
[])
|
||||
|
||||
class Clang_CompileTool(Tool):
|
||||
def __init__(self):
|
||||
super(Clang_CompileTool, self).__init__('clang',
|
||||
|
@ -180,7 +170,7 @@ class Clang_CompileTool(Tool):
|
|||
Tool.eFlagsIntegratedCPP))
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
output, outputType, arglist, linkingOutput):
|
||||
cmd_args = []
|
||||
|
||||
patchOutputNameForPTH = False
|
||||
|
@ -580,7 +570,7 @@ class Darwin_X86_PreprocessTool(Darwin_X86_CC1Tool):
|
|||
self.toolChain = toolChain
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
output, outputType, arglist, linkingOutput):
|
||||
inputType = inputs[0].type
|
||||
assert not [i for i in inputs if i.type != inputType]
|
||||
|
||||
|
@ -611,7 +601,7 @@ class Darwin_X86_CompileTool(Darwin_X86_CC1Tool):
|
|||
self.toolChain = toolChain
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
output, outputType, arglist, linkingOutput):
|
||||
inputType = inputs[0].type
|
||||
assert not [i for i in inputs if i.type != inputType]
|
||||
|
||||
|
@ -897,7 +887,7 @@ class Darwin_X86_LinkTool(Tool):
|
|||
arglist.addLastArg(cmd_args, arglist.parser.MachOption)
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
output, outputType, arglist, linkingOutput):
|
||||
assert outputType is Types.ImageType
|
||||
|
||||
# The logic here is derived from gcc's behavior; most of which
|
||||
|
@ -1017,6 +1007,11 @@ class Darwin_X86_LinkTool(Tool):
|
|||
for input in inputs:
|
||||
cmd_args.extend(arglist.renderAsInput(input.source))
|
||||
|
||||
if linkingOutput:
|
||||
cmd_args.append('-arch_multiple')
|
||||
cmd_args.append('-final_output')
|
||||
cmd_args.append(arglist.getValue(linkingOutput))
|
||||
|
||||
if (arglist.getLastArg(arglist.parser.f_profileArcsOption) or
|
||||
arglist.getLastArg(arglist.parser.f_profileGenerateOption) or
|
||||
arglist.getLastArg(arglist.parser.f_createProfileOption) or
|
||||
|
@ -1088,7 +1083,7 @@ class LipoTool(Tool):
|
|||
super(LipoTool, self).__init__('lipo')
|
||||
|
||||
def constructJob(self, phase, arch, jobs, inputs,
|
||||
output, outputType, arglist):
|
||||
output, outputType, arglist, linkingOutput):
|
||||
assert outputType is Types.ImageType
|
||||
|
||||
cmd_args = ['-create']
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// RUN: xcc -arch ppc -arch i386 -arch x86_64 %s -o %t &&
|
||||
// RUN: %t | grep "Hello, World"
|
||||
// RUN: %t | grep "Hello, World" &&
|
||||
|
||||
// Check that multiple archs are handled properly.
|
||||
// RUN: xcc -ccc-print-phases -### -arch ppc -arch ppc %s | grep linker- | count 1
|
||||
|
||||
int main() {
|
||||
printf("Hello, World!\n");
|
||||
|
|
Loading…
Reference in New Issue