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):
|
def buildPipeline(self, args):
|
||||||
# FIXME: We need to handle canonicalization of the specified arch.
|
# FIXME: We need to handle canonicalization of the specified arch.
|
||||||
|
|
||||||
archs = []
|
archs = {}
|
||||||
hasDashM = args.getLastArg(self.parser.MGroup)
|
hasDashM = args.getLastArg(self.parser.MGroup)
|
||||||
hasSaveTemps = (args.getLastArg(self.parser.saveTempsOption) or
|
hasSaveTemps = (args.getLastArg(self.parser.saveTempsOption) or
|
||||||
args.getLastArg(self.parser.saveTempsOption2))
|
args.getLastArg(self.parser.saveTempsOption2))
|
||||||
for arg in args:
|
for arg in args:
|
||||||
if arg.opt is self.parser.archOption:
|
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:
|
if not archs:
|
||||||
archs.append(args.makeSeparateArg(self.hostInfo.getArchName(args),
|
archs.append(args.makeSeparateArg(self.hostInfo.getArchName(args),
|
||||||
self.parser.archOption))
|
self.parser.archOption))
|
||||||
|
@ -578,18 +581,6 @@ class Driver(object):
|
||||||
inputs,
|
inputs,
|
||||||
p.type))
|
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
|
return finalActions
|
||||||
|
|
||||||
def bindPhases(self, phases, args):
|
def bindPhases(self, phases, args):
|
||||||
|
@ -636,7 +627,7 @@ class Driver(object):
|
||||||
|
|
||||||
def createJobs(tc, phase,
|
def createJobs(tc, phase,
|
||||||
canAcceptPipe=False, atTopLevel=False, arch=None,
|
canAcceptPipe=False, atTopLevel=False, arch=None,
|
||||||
tcArgs=None):
|
tcArgs=None, linkingOutput=None):
|
||||||
if isinstance(phase, Phases.InputAction):
|
if isinstance(phase, Phases.InputAction):
|
||||||
return InputInfo(phase.filename, phase.type, phase.filename)
|
return InputInfo(phase.filename, phase.type, phase.filename)
|
||||||
elif isinstance(phase, Phases.BindArchAction):
|
elif isinstance(phase, Phases.BindArchAction):
|
||||||
|
@ -644,7 +635,7 @@ class Driver(object):
|
||||||
tc = self.hostInfo.getToolChainForArch(archName)
|
tc = self.hostInfo.getToolChainForArch(archName)
|
||||||
return createJobs(tc, phase.inputs[0],
|
return createJobs(tc, phase.inputs[0],
|
||||||
canAcceptPipe, atTopLevel, phase.arch,
|
canAcceptPipe, atTopLevel, phase.arch,
|
||||||
tcArgs=None)
|
None, linkingOutput)
|
||||||
|
|
||||||
if tcArgs is None:
|
if tcArgs is None:
|
||||||
tcArgs = tc.translateArgs(args, arch)
|
tcArgs = tc.translateArgs(args, arch)
|
||||||
|
@ -669,7 +660,8 @@ class Driver(object):
|
||||||
|
|
||||||
# Only try to use pipes when exactly one input.
|
# Only try to use pipes when exactly one input.
|
||||||
canAcceptPipe = len(inputList) == 1 and tool.acceptsPipedInput()
|
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]
|
for p in inputList]
|
||||||
|
|
||||||
# Determine if we should output to a pipe.
|
# Determine if we should output to a pipe.
|
||||||
|
@ -692,8 +684,45 @@ class Driver(object):
|
||||||
if canAcceptPipe and isinstance(inputs[0].source, Jobs.PipedJob):
|
if canAcceptPipe and isinstance(inputs[0].source, Jobs.PipedJob):
|
||||||
jobList = inputs[0].source
|
jobList = inputs[0].source
|
||||||
|
|
||||||
# Figure out where to put the output.
|
|
||||||
baseInput = inputs[0].baseInput
|
baseInput = inputs[0].baseInput
|
||||||
|
output = 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:
|
if phase.type == Types.NothingType:
|
||||||
output = None
|
output = None
|
||||||
elif outputToPipe:
|
elif outputToPipe:
|
||||||
|
@ -733,19 +762,4 @@ class Driver(object):
|
||||||
fd,filename = tempfile.mkstemp(suffix='.'+phase.type.tempSuffix)
|
fd,filename = tempfile.mkstemp(suffix='.'+phase.type.tempSuffix)
|
||||||
output = args.makeSeparateArg(filename,
|
output = args.makeSeparateArg(filename,
|
||||||
self.parser.oOption)
|
self.parser.oOption)
|
||||||
|
return output
|
||||||
tool.constructJob(phase, arch, jobList, inputs, output, phase.type,
|
|
||||||
tcArgs)
|
|
||||||
|
|
||||||
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:
|
|
||||||
createJobs(self.toolChain, phase,
|
|
||||||
canAcceptPipe=True, atTopLevel=True)
|
|
||||||
|
|
||||||
return jobs
|
|
||||||
|
|
|
@ -24,15 +24,17 @@ class Tool(object):
|
||||||
return not not (self.flags & Tool.eFlagsIntegratedCPP)
|
return not not (self.flags & Tool.eFlagsIntegratedCPP)
|
||||||
|
|
||||||
class GCC_Common_Tool(Tool):
|
class GCC_Common_Tool(Tool):
|
||||||
|
def getGCCExtraArgs(self):
|
||||||
|
return []
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def constructJob(self, phase, arch, jobs, inputs,
|
||||||
output, outputType, arglist,
|
output, outputType, arglist, linkingOutput):
|
||||||
extraArgs):
|
|
||||||
cmd_args = []
|
cmd_args = []
|
||||||
for arg in arglist.args:
|
for arg in arglist.args:
|
||||||
if arg.opt.forwardToGCC():
|
if arg.opt.forwardToGCC():
|
||||||
cmd_args.extend(arglist.render(arg))
|
cmd_args.extend(arglist.render(arg))
|
||||||
|
|
||||||
cmd_args.extend(extraArgs)
|
cmd_args.extend(self.getGCCExtraArgs())
|
||||||
if arch:
|
if arch:
|
||||||
cmd_args.extend(arglist.render(arch))
|
cmd_args.extend(arglist.render(arch))
|
||||||
if isinstance(output, Jobs.PipedJob):
|
if isinstance(output, Jobs.PipedJob):
|
||||||
|
@ -42,6 +44,12 @@ class GCC_Common_Tool(Tool):
|
||||||
else:
|
else:
|
||||||
cmd_args.extend(arglist.render(output))
|
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
|
# Only pass -x if gcc will understand it; otherwise hope gcc
|
||||||
# understands the suffix correctly. The main use case this
|
# understands the suffix correctly. The main use case this
|
||||||
# would go wrong in is for linker inputs if they happened to
|
# 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.eFlagsPipedInput |
|
||||||
Tool.eFlagsPipedOutput))
|
Tool.eFlagsPipedOutput))
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def getGCCExtraArgs(self):
|
||||||
output, outputType, arglist):
|
return ['-E']
|
||||||
return super(GCC_PreprocessTool, self).constructJob(phase, arch, jobs, inputs,
|
|
||||||
output, outputType, arglist,
|
|
||||||
['-E'])
|
|
||||||
|
|
||||||
class GCC_CompileTool(GCC_Common_Tool):
|
class GCC_CompileTool(GCC_Common_Tool):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -87,11 +92,8 @@ class GCC_CompileTool(GCC_Common_Tool):
|
||||||
Tool.eFlagsPipedOutput |
|
Tool.eFlagsPipedOutput |
|
||||||
Tool.eFlagsIntegratedCPP))
|
Tool.eFlagsIntegratedCPP))
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def getGCCExtraArgs(self):
|
||||||
output, outputType, arglist):
|
return ['-S']
|
||||||
return super(GCC_CompileTool, self).constructJob(phase, arch, jobs, inputs,
|
|
||||||
output, outputType, arglist,
|
|
||||||
['-S'])
|
|
||||||
|
|
||||||
class GCC_PrecompileTool(GCC_Common_Tool):
|
class GCC_PrecompileTool(GCC_Common_Tool):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -99,11 +101,21 @@ class GCC_PrecompileTool(GCC_Common_Tool):
|
||||||
(Tool.eFlagsPipedInput |
|
(Tool.eFlagsPipedInput |
|
||||||
Tool.eFlagsIntegratedCPP))
|
Tool.eFlagsIntegratedCPP))
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def getGCCExtraArgs(self):
|
||||||
output, outputType, arglist):
|
return []
|
||||||
return super(GCC_PrecompileTool, self).constructJob(phase, arch, jobs, inputs,
|
|
||||||
output, outputType, arglist,
|
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):
|
class Darwin_AssembleTool(Tool):
|
||||||
def __init__(self, toolChain):
|
def __init__(self, toolChain):
|
||||||
|
@ -112,7 +124,7 @@ class Darwin_AssembleTool(Tool):
|
||||||
self.toolChain = toolChain
|
self.toolChain = toolChain
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def constructJob(self, phase, arch, jobs, inputs,
|
||||||
output, outputType, arglist):
|
output, outputType, arglist, linkingOutput):
|
||||||
assert len(inputs) == 1
|
assert len(inputs) == 1
|
||||||
assert outputType is Types.ObjectType
|
assert outputType is Types.ObjectType
|
||||||
|
|
||||||
|
@ -150,28 +162,6 @@ class Darwin_AssembleTool(Tool):
|
||||||
jobs.addJob(Jobs.Command(self.toolChain.getProgramPath('as'),
|
jobs.addJob(Jobs.Command(self.toolChain.getProgramPath('as'),
|
||||||
cmd_args))
|
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):
|
class Clang_CompileTool(Tool):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Clang_CompileTool, self).__init__('clang',
|
super(Clang_CompileTool, self).__init__('clang',
|
||||||
|
@ -180,7 +170,7 @@ class Clang_CompileTool(Tool):
|
||||||
Tool.eFlagsIntegratedCPP))
|
Tool.eFlagsIntegratedCPP))
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def constructJob(self, phase, arch, jobs, inputs,
|
||||||
output, outputType, arglist):
|
output, outputType, arglist, linkingOutput):
|
||||||
cmd_args = []
|
cmd_args = []
|
||||||
|
|
||||||
patchOutputNameForPTH = False
|
patchOutputNameForPTH = False
|
||||||
|
@ -580,7 +570,7 @@ class Darwin_X86_PreprocessTool(Darwin_X86_CC1Tool):
|
||||||
self.toolChain = toolChain
|
self.toolChain = toolChain
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def constructJob(self, phase, arch, jobs, inputs,
|
||||||
output, outputType, arglist):
|
output, outputType, arglist, linkingOutput):
|
||||||
inputType = inputs[0].type
|
inputType = inputs[0].type
|
||||||
assert not [i for i in inputs if i.type != inputType]
|
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
|
self.toolChain = toolChain
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def constructJob(self, phase, arch, jobs, inputs,
|
||||||
output, outputType, arglist):
|
output, outputType, arglist, linkingOutput):
|
||||||
inputType = inputs[0].type
|
inputType = inputs[0].type
|
||||||
assert not [i for i in inputs if i.type != inputType]
|
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)
|
arglist.addLastArg(cmd_args, arglist.parser.MachOption)
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def constructJob(self, phase, arch, jobs, inputs,
|
||||||
output, outputType, arglist):
|
output, outputType, arglist, linkingOutput):
|
||||||
assert outputType is Types.ImageType
|
assert outputType is Types.ImageType
|
||||||
|
|
||||||
# The logic here is derived from gcc's behavior; most of which
|
# 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:
|
for input in inputs:
|
||||||
cmd_args.extend(arglist.renderAsInput(input.source))
|
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
|
if (arglist.getLastArg(arglist.parser.f_profileArcsOption) or
|
||||||
arglist.getLastArg(arglist.parser.f_profileGenerateOption) or
|
arglist.getLastArg(arglist.parser.f_profileGenerateOption) or
|
||||||
arglist.getLastArg(arglist.parser.f_createProfileOption) or
|
arglist.getLastArg(arglist.parser.f_createProfileOption) or
|
||||||
|
@ -1088,7 +1083,7 @@ class LipoTool(Tool):
|
||||||
super(LipoTool, self).__init__('lipo')
|
super(LipoTool, self).__init__('lipo')
|
||||||
|
|
||||||
def constructJob(self, phase, arch, jobs, inputs,
|
def constructJob(self, phase, arch, jobs, inputs,
|
||||||
output, outputType, arglist):
|
output, outputType, arglist, linkingOutput):
|
||||||
assert outputType is Types.ImageType
|
assert outputType is Types.ImageType
|
||||||
|
|
||||||
cmd_args = ['-create']
|
cmd_args = ['-create']
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
// RUN: xcc -arch ppc -arch i386 -arch x86_64 %s -o %t &&
|
// 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() {
|
int main() {
|
||||||
printf("Hello, World!\n");
|
printf("Hello, World!\n");
|
||||||
|
|
Loading…
Reference in New Issue