blob: 73b0127e1448f7f77fece25019a70c1b12d81d4a [file] [log] [blame]
Daniel Dunbarf677a602009-01-21 02:03:52 +00001import os
2
Daniel Dunbarb3492762009-01-13 18:51:26 +00003import Arguments
Daniel Dunbar08dea462009-01-10 02:07:54 +00004import Phases
5import Tools
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +00006import Types
Daniel Dunbar08dea462009-01-10 02:07:54 +00007
8###
9
10class ToolChain(object):
11 """ToolChain - Provide mappings of Actions to Tools."""
12
Daniel Dunbarf677a602009-01-21 02:03:52 +000013 def __init__(self, driver,
14 filePathPrefixes=[],
15 programPathPrefixes=[]):
Daniel Dunbar08dea462009-01-10 02:07:54 +000016 self.driver = driver
Daniel Dunbarf677a602009-01-21 02:03:52 +000017 self.filePathPrefixes = list(filePathPrefixes)
18 self.programPathPrefixes = list(programPathPrefixes)
19
20 def getFilePath(self, name):
21 return self.driver.getFilePath(name, self)
22
23 def getProgramPath(self, name):
24 return self.driver.getProgramPath(name, self)
Daniel Dunbar08dea462009-01-10 02:07:54 +000025
26 def selectTool(self, action):
27 """selectTool - Return a Tool instance to use for handling
28 some particular action."""
29 abstract
30
Daniel Dunbarb3492762009-01-13 18:51:26 +000031 def translateArgs(self, args, arch):
32 """translateArgs - Callback to allow argument translation for
33 an entire toolchain."""
34
35 # FIXME: Would be nice to move arch handling out of generic
36 # code.
37 if arch:
38 archName = args.getValue(arch)
39 al = Arguments.DerivedArgList(args)
40 for arg in args.args:
41 if arg.opt is args.parser.archOption:
42 if arg is arch:
43 al.append(arg)
44 elif arg.opt is args.parser.XarchOption:
45 if args.getJoinedValue(arg) == archName:
46 # FIXME: Fix this.
47 arg = args.parser.lookupOptForArg(Arguments.InputIndex(0, arg.index.pos + 1),
48 args.getSeparateValue(arg),
49 iter([]))
50 al.append(arg)
51 else:
52 al.append(arg)
53 return al
54 else:
55 return args
56
Daniel Dunbarc2148562009-01-12 04:21:12 +000057class Darwin_X86_ToolChain(ToolChain):
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +000058 def __init__(self, driver, darwinVersion, gccVersion, archName):
Daniel Dunbarc2148562009-01-12 04:21:12 +000059 super(Darwin_X86_ToolChain, self).__init__(driver)
Daniel Dunbar2dda5412009-01-12 07:45:49 +000060 assert isinstance(darwinVersion, tuple) and len(darwinVersion) == 3
61 assert isinstance(gccVersion, tuple) and len(gccVersion) == 3
62 self.darwinVersion = darwinVersion
63 self.gccVersion = gccVersion
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +000064 self.archName = archName
Daniel Dunbar2dda5412009-01-12 07:45:49 +000065
Daniel Dunbar90c72cd2009-01-21 01:07:49 +000066 self.clangTool = Tools.Clang_CompileTool(self)
Daniel Dunbar34f60f62009-01-26 17:09:15 +000067 cc = Tools.Darwin_X86_CompileTool(self)
Daniel Dunbar08dea462009-01-10 02:07:54 +000068 self.toolMap = {
Daniel Dunbar7d494092009-01-20 00:47:24 +000069 Phases.PreprocessPhase : Tools.Darwin_X86_PreprocessTool(self),
Daniel Dunbar90c72cd2009-01-21 01:07:49 +000070 Phases.AnalyzePhase : self.clangTool,
Daniel Dunbar34f60f62009-01-26 17:09:15 +000071 Phases.SyntaxOnlyPhase : cc,
72 Phases.EmitLLVMPhase : cc,
73 Phases.CompilePhase : cc,
74 Phases.PrecompilePhase : cc,
Daniel Dunbar2dda5412009-01-12 07:45:49 +000075 Phases.AssemblePhase : Tools.Darwin_AssembleTool(self),
76 Phases.LinkPhase : Tools.Darwin_X86_LinkTool(self),
Daniel Dunbar08dea462009-01-10 02:07:54 +000077 Phases.LipoPhase : Tools.LipoTool(),
78 }
79
Daniel Dunbare28f9e92009-01-21 17:18:19 +000080 if archName == 'x86_64':
81 self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
82 '../lib/gcc',
83 self.getToolChainDir(),
84 'x86_64'))
85 self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
86 self.getToolChainDir(),
87 'x86_64'))
Daniel Dunbarf677a602009-01-21 02:03:52 +000088 self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
89 '../lib/gcc',
90 self.getToolChainDir()))
Daniel Dunbare28f9e92009-01-21 17:18:19 +000091 self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
Daniel Dunbarf677a602009-01-21 02:03:52 +000092 self.getToolChainDir()))
93
94 self.programPathPrefixes.append(os.path.join(self.driver.driverDir,
95 '../libexec/gcc',
96 self.getToolChainDir()))
Daniel Dunbare28f9e92009-01-21 17:18:19 +000097 self.programPathPrefixes.append(os.path.join('/usr/libexec/gcc',
98 self.getToolChainDir()))
Daniel Dunbarf677a602009-01-21 02:03:52 +000099 self.programPathPrefixes.append(self.driver.driverDir)
100
Daniel Dunbar2dda5412009-01-12 07:45:49 +0000101 def getToolChainDir(self):
102 return 'i686-apple-darwin%d/%s' % (self.darwinVersion[0],
103 '.'.join(map(str,self.gccVersion)))
104
Daniel Dunbarbafb8f42009-01-12 18:51:02 +0000105 def getMacosxVersionMin(self):
106 major,minor,minorminor = self.darwinVersion
107 return '%d.%d.%d' % (10, major-4, minor)
108
Daniel Dunbar08dea462009-01-10 02:07:54 +0000109 def selectTool(self, action):
110 assert isinstance(action, Phases.JobAction)
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +0000111
Daniel Dunbar386a51c2009-01-14 23:26:40 +0000112 if self.driver.cccClang and self.archName == 'i386':
113 if (action.inputs[0].type in (Types.CType, Types.CTypeNoPP,
114 Types.ObjCType, Types.ObjCTypeNoPP) and
Daniel Dunbar34f60f62009-01-26 17:09:15 +0000115 (isinstance(action.phase, Phases.CompilePhase) or
116 isinstance(action.phase, Phases.SyntaxOnlyPhase) or
117 isinstance(action.phase, Phases.EmitLLVMPhase))):
Daniel Dunbar386a51c2009-01-14 23:26:40 +0000118 return self.clangTool
119 elif (action.inputs[0].type in (Types.CHeaderType, Types.CHeaderNoPPType,
120 Types.ObjCHeaderType, Types.ObjCHeaderNoPPType) and
121 isinstance(action.phase, Phases.PrecompilePhase)):
122 return self.clangTool
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +0000123
Daniel Dunbar08dea462009-01-10 02:07:54 +0000124 return self.toolMap[action.phase.__class__]
125
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000126 def translateArgs(self, args, arch):
127 args = super(Darwin_X86_ToolChain, self).translateArgs(args, arch)
128
129 # If arch hasn't been bound we don't need to do anything yet.
130 if not arch:
131 return args
132
Daniel Dunbar7e184602009-01-16 20:25:36 +0000133 # FIXME: We really want to get out of the tool chain level
134 # argument translation business, as it makes the driver
135 # functionality much more opaque. For now, we follow gcc
136 # closely solely for the purpose of easily achieving feature
137 # parity & testability. Once we have something that works, we
138 # should reevaluate each translation and try to push it down
139 # into tool specific logic.
140
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000141 al = Arguments.DerivedArgList(args)
142 if not args.getLastArg(args.parser.m_macosxVersionMinOption):
143 al.append(al.makeJoinedArg(self.getMacosxVersionMin(),
144 args.parser.m_macosxVersionMinOption))
145 for arg in args:
Daniel Dunbar7e184602009-01-16 20:25:36 +0000146 # Sob. These is strictly gcc compatible for the time
147 # being. Apple gcc translates options twice, which means
148 # that self-expanding options add duplicates.
149 if arg.opt is args.parser.m_kernelOption:
150 al.append(arg)
151 al.append(al.makeFlagArg(args.parser.staticOption))
152 al.append(al.makeFlagArg(args.parser.staticOption))
153 elif arg.opt is args.parser.dependencyFileOption:
154 al.append(al.makeSeparateArg(args.getValue(arg),
155 args.parser.MFOption))
156 elif arg.opt is args.parser.gfullOption:
157 al.append(al.makeFlagArg(args.parser.gOption))
158 al.append(al.makeFlagArg(args.parser.f_noEliminateUnusedDebugSymbolsOption))
159 elif arg.opt is args.parser.gusedOption:
160 al.append(al.makeFlagArg(args.parser.gOption))
161 al.append(al.makeFlagArg(args.parser.f_eliminateUnusedDebugSymbolsOption))
162 elif arg.opt is args.parser.f_appleKextOption:
163 al.append(arg)
164 al.append(al.makeFlagArg(args.parser.staticOption))
165 al.append(al.makeFlagArg(args.parser.staticOption))
166 elif arg.opt is args.parser.f_terminatedVtablesOption:
167 al.append(al.makeFlagArg(args.parser.f_appleKextOption))
168 al.append(al.makeFlagArg(args.parser.staticOption))
169 elif arg.opt is args.parser.f_indirectVirtualCallsOption:
170 al.append(al.makeFlagArg(args.parser.f_appleKextOption))
171 al.append(al.makeFlagArg(args.parser.staticOption))
172 elif arg.opt is args.parser.f_constantCfstringsOption:
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000173 al.append(al.makeFlagArg(args.parser.m_constantCfstringsOption))
174 elif arg.opt is args.parser.f_noConstantCfstringsOption:
175 al.append(al.makeFlagArg(args.parser.m_noConstantCfstringsOption))
176 elif arg.opt is args.parser.WnonportableCfstringsOption:
177 al.append(al.makeFlagArg(args.parser.m_warnNonportableCfstringsOption))
178 elif arg.opt is args.parser.WnoNonportableCfstringsOption:
179 al.append(al.makeFlagArg(args.parser.m_noWarnNonportableCfstringsOption))
180 elif arg.opt is args.parser.f_pascalStringsOption:
181 al.append(al.makeFlagArg(args.parser.m_pascalStringsOption))
182 elif arg.opt is args.parser.f_noPascalStringsOption:
183 al.append(al.makeFlagArg(args.parser.m_noPascalStringsOption))
184 else:
185 al.append(arg)
186
187 # FIXME: Actually, gcc always adds this, but it is filtered
188 # for duplicates somewhere. This also changes the order of
189 # things, so look it up.
190 if arch and args.getValue(arch) == 'x86_64':
191 if not args.getLastArg(args.parser.m_64Option):
192 al.append(al.makeFlagArg(args.parser.m_64Option))
193
194 if not args.getLastArg(args.parser.m_tuneOption):
195 al.append(al.makeJoinedArg('core2',
196 args.parser.m_tuneOption))
197
198 return al
199
Daniel Dunbar08dea462009-01-10 02:07:54 +0000200class Generic_GCC_ToolChain(ToolChain):
201 """Generic_GCC_ToolChain - A tool chain using the 'gcc' command to
202 perform all subcommands; this relies on gcc translating the
203 options appropriately."""
204
205 def __init__(self, driver):
206 super(Generic_GCC_ToolChain, self).__init__(driver)
Daniel Dunbar34f60f62009-01-26 17:09:15 +0000207 cc = Tools.GCC_CompileTool()
Daniel Dunbaref993d12009-01-29 06:12:22 +0000208 self.clangTool = Tools.Clang_CompileTool(self)
Daniel Dunbar08dea462009-01-10 02:07:54 +0000209 self.toolMap = {
210 Phases.PreprocessPhase : Tools.GCC_PreprocessTool(),
Daniel Dunbaref993d12009-01-29 06:12:22 +0000211 Phases.AnalyzePhase : self.clangTool,
Daniel Dunbar34f60f62009-01-26 17:09:15 +0000212 Phases.SyntaxOnlyPhase : cc,
213 Phases.EmitLLVMPhase : cc,
214 Phases.CompilePhase : cc,
Daniel Dunbar08dea462009-01-10 02:07:54 +0000215 Phases.PrecompilePhase : Tools.GCC_PrecompileTool(),
216 Phases.AssemblePhase : Tools.GCC_AssembleTool(),
217 Phases.LinkPhase : Tools.GCC_LinkTool(),
218 }
219
220 def selectTool(self, action):
221 assert isinstance(action, Phases.JobAction)
Daniel Dunbaref993d12009-01-29 06:12:22 +0000222
223 if self.driver.cccClang:
224 if (action.inputs[0].type in (Types.CType, Types.CTypeNoPP,
225 Types.ObjCType, Types.ObjCTypeNoPP) and
226 (isinstance(action.phase, Phases.PreprocessPhase) or
227 isinstance(action.phase, Phases.CompilePhase) or
228 isinstance(action.phase, Phases.SyntaxOnlyPhase) or
229 isinstance(action.phase, Phases.EmitLLVMPhase))):
230 return self.clangTool
231 elif (action.inputs[0].type in (Types.CHeaderType, Types.CHeaderNoPPType,
232 Types.ObjCHeaderType, Types.ObjCHeaderNoPPType) and
233 isinstance(action.phase, Phases.PrecompilePhase)):
234 return self.clangTool
235
Daniel Dunbar08dea462009-01-10 02:07:54 +0000236 return self.toolMap[action.phase.__class__]