blob: 2fe482ecd24f31d104555c2ee45f1f97fb97240f [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 Dunbard47bf282009-02-20 01:36:35 +000013 def __init__(self, driver, archName,
Daniel Dunbarf677a602009-01-21 02:03:52 +000014 filePathPrefixes=[],
15 programPathPrefixes=[]):
Daniel Dunbar08dea462009-01-10 02:07:54 +000016 self.driver = driver
Daniel Dunbard47bf282009-02-20 01:36:35 +000017 self.archName = archName
Daniel Dunbarf677a602009-01-21 02:03:52 +000018 self.filePathPrefixes = list(filePathPrefixes)
19 self.programPathPrefixes = list(programPathPrefixes)
20
21 def getFilePath(self, name):
22 return self.driver.getFilePath(name, self)
23
24 def getProgramPath(self, name):
25 return self.driver.getProgramPath(name, self)
Daniel Dunbar08dea462009-01-10 02:07:54 +000026
27 def selectTool(self, action):
28 """selectTool - Return a Tool instance to use for handling
29 some particular action."""
30 abstract
31
Daniel Dunbarb3492762009-01-13 18:51:26 +000032 def translateArgs(self, args, arch):
33 """translateArgs - Callback to allow argument translation for
34 an entire toolchain."""
35
36 # FIXME: Would be nice to move arch handling out of generic
37 # code.
38 if arch:
39 archName = args.getValue(arch)
40 al = Arguments.DerivedArgList(args)
41 for arg in args.args:
42 if arg.opt is args.parser.archOption:
43 if arg is arch:
44 al.append(arg)
45 elif arg.opt is args.parser.XarchOption:
46 if args.getJoinedValue(arg) == archName:
47 # FIXME: Fix this.
48 arg = args.parser.lookupOptForArg(Arguments.InputIndex(0, arg.index.pos + 1),
49 args.getSeparateValue(arg),
50 iter([]))
51 al.append(arg)
52 else:
53 al.append(arg)
54 return al
55 else:
56 return args
57
Daniel Dunbar72999172009-01-29 23:54:06 +000058 def shouldUseClangCompiler(self, action):
59 # If user requested no clang, or this isn't a "compile" phase,
60 # or this isn't a C family option, then don't use clang.
61 if (self.driver.cccNoClang or
62 not isinstance(action.phase, (Phases.PreprocessPhase,
63 Phases.CompilePhase,
64 Phases.SyntaxOnlyPhase,
65 Phases.EmitLLVMPhase,
66 Phases.PrecompilePhase)) or
67 action.inputs[0].type not in Types.cTypesSet):
68 return False
69
70 if self.driver.cccNoClangPreprocessor:
71 if isinstance(action.phase, Phases.PreprocessPhase):
72 return False
73
74 if self.driver.cccNoClangCXX:
75 if action.inputs[0].type in Types.cxxTypesSet:
76 return False
77
78 return True
79
Daniel Dunbar43e66e12009-02-17 00:42:05 +000080 def isMathErrnoDefault(self):
81 return True
82
Daniel Dunbarc2148562009-01-12 04:21:12 +000083class Darwin_X86_ToolChain(ToolChain):
Daniel Dunbard47bf282009-02-20 01:36:35 +000084 def __init__(self, driver, archName, darwinVersion, gccVersion):
85 super(Darwin_X86_ToolChain, self).__init__(driver, archName)
Daniel Dunbar2dda5412009-01-12 07:45:49 +000086 assert isinstance(darwinVersion, tuple) and len(darwinVersion) == 3
87 assert isinstance(gccVersion, tuple) and len(gccVersion) == 3
88 self.darwinVersion = darwinVersion
89 self.gccVersion = gccVersion
90
Daniel Dunbar90c72cd2009-01-21 01:07:49 +000091 self.clangTool = Tools.Clang_CompileTool(self)
Daniel Dunbar34f60f62009-01-26 17:09:15 +000092 cc = Tools.Darwin_X86_CompileTool(self)
Daniel Dunbar08dea462009-01-10 02:07:54 +000093 self.toolMap = {
Daniel Dunbar7d494092009-01-20 00:47:24 +000094 Phases.PreprocessPhase : Tools.Darwin_X86_PreprocessTool(self),
Daniel Dunbar90c72cd2009-01-21 01:07:49 +000095 Phases.AnalyzePhase : self.clangTool,
Daniel Dunbar34f60f62009-01-26 17:09:15 +000096 Phases.SyntaxOnlyPhase : cc,
97 Phases.EmitLLVMPhase : cc,
98 Phases.CompilePhase : cc,
99 Phases.PrecompilePhase : cc,
Daniel Dunbar2dda5412009-01-12 07:45:49 +0000100 Phases.AssemblePhase : Tools.Darwin_AssembleTool(self),
101 Phases.LinkPhase : Tools.Darwin_X86_LinkTool(self),
Daniel Dunbar302b9672009-02-20 01:30:38 +0000102 Phases.LipoPhase : Tools.LipoTool(self),
Daniel Dunbar08dea462009-01-10 02:07:54 +0000103 }
104
Daniel Dunbare28f9e92009-01-21 17:18:19 +0000105 if archName == 'x86_64':
106 self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
107 '../lib/gcc',
108 self.getToolChainDir(),
109 'x86_64'))
110 self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
111 self.getToolChainDir(),
112 'x86_64'))
Daniel Dunbarf677a602009-01-21 02:03:52 +0000113 self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
114 '../lib/gcc',
115 self.getToolChainDir()))
Daniel Dunbare28f9e92009-01-21 17:18:19 +0000116 self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
Daniel Dunbarf677a602009-01-21 02:03:52 +0000117 self.getToolChainDir()))
118
119 self.programPathPrefixes.append(os.path.join(self.driver.driverDir,
120 '../libexec/gcc',
121 self.getToolChainDir()))
Daniel Dunbare28f9e92009-01-21 17:18:19 +0000122 self.programPathPrefixes.append(os.path.join('/usr/libexec/gcc',
123 self.getToolChainDir()))
Daniel Dunbarf677a602009-01-21 02:03:52 +0000124 self.programPathPrefixes.append(self.driver.driverDir)
125
Daniel Dunbar2dda5412009-01-12 07:45:49 +0000126 def getToolChainDir(self):
127 return 'i686-apple-darwin%d/%s' % (self.darwinVersion[0],
128 '.'.join(map(str,self.gccVersion)))
129
Daniel Dunbarbafb8f42009-01-12 18:51:02 +0000130 def getMacosxVersionMin(self):
131 major,minor,minorminor = self.darwinVersion
132 return '%d.%d.%d' % (10, major-4, minor)
133
Daniel Dunbar72999172009-01-29 23:54:06 +0000134 def shouldUseClangCompiler(self, action):
135 if not super(Darwin_X86_ToolChain, self).shouldUseClangCompiler(action):
136 return False
137
138 # Only use clang if user didn't override archs, or this is one
139 # of the ones they provided.
140 if (not self.driver.cccClangArchs or
141 self.archName in self.driver.cccClangArchs):
142 return True
143
144 return False
145
Daniel Dunbar08dea462009-01-10 02:07:54 +0000146 def selectTool(self, action):
147 assert isinstance(action, Phases.JobAction)
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +0000148
Daniel Dunbar72999172009-01-29 23:54:06 +0000149 if self.shouldUseClangCompiler(action):
150 return self.clangTool
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +0000151
Daniel Dunbar08dea462009-01-10 02:07:54 +0000152 return self.toolMap[action.phase.__class__]
153
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000154 def translateArgs(self, args, arch):
155 args = super(Darwin_X86_ToolChain, self).translateArgs(args, arch)
156
157 # If arch hasn't been bound we don't need to do anything yet.
158 if not arch:
159 return args
160
Daniel Dunbar7e184602009-01-16 20:25:36 +0000161 # FIXME: We really want to get out of the tool chain level
162 # argument translation business, as it makes the driver
163 # functionality much more opaque. For now, we follow gcc
164 # closely solely for the purpose of easily achieving feature
165 # parity & testability. Once we have something that works, we
166 # should reevaluate each translation and try to push it down
167 # into tool specific logic.
168
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000169 al = Arguments.DerivedArgList(args)
170 if not args.getLastArg(args.parser.m_macosxVersionMinOption):
171 al.append(al.makeJoinedArg(self.getMacosxVersionMin(),
172 args.parser.m_macosxVersionMinOption))
173 for arg in args:
Daniel Dunbar7e184602009-01-16 20:25:36 +0000174 # Sob. These is strictly gcc compatible for the time
175 # being. Apple gcc translates options twice, which means
176 # that self-expanding options add duplicates.
177 if arg.opt is args.parser.m_kernelOption:
178 al.append(arg)
179 al.append(al.makeFlagArg(args.parser.staticOption))
180 al.append(al.makeFlagArg(args.parser.staticOption))
181 elif arg.opt is args.parser.dependencyFileOption:
182 al.append(al.makeSeparateArg(args.getValue(arg),
183 args.parser.MFOption))
184 elif arg.opt is args.parser.gfullOption:
185 al.append(al.makeFlagArg(args.parser.gOption))
186 al.append(al.makeFlagArg(args.parser.f_noEliminateUnusedDebugSymbolsOption))
187 elif arg.opt is args.parser.gusedOption:
188 al.append(al.makeFlagArg(args.parser.gOption))
189 al.append(al.makeFlagArg(args.parser.f_eliminateUnusedDebugSymbolsOption))
190 elif arg.opt is args.parser.f_appleKextOption:
191 al.append(arg)
192 al.append(al.makeFlagArg(args.parser.staticOption))
193 al.append(al.makeFlagArg(args.parser.staticOption))
194 elif arg.opt is args.parser.f_terminatedVtablesOption:
195 al.append(al.makeFlagArg(args.parser.f_appleKextOption))
196 al.append(al.makeFlagArg(args.parser.staticOption))
197 elif arg.opt is args.parser.f_indirectVirtualCallsOption:
198 al.append(al.makeFlagArg(args.parser.f_appleKextOption))
199 al.append(al.makeFlagArg(args.parser.staticOption))
Daniel Dunbar039b1d02009-02-06 19:18:58 +0000200 elif arg.opt is args.parser.sharedOption:
201 al.append(al.makeFlagArg(args.parser.dynamiclibOption))
Daniel Dunbar7e184602009-01-16 20:25:36 +0000202 elif arg.opt is args.parser.f_constantCfstringsOption:
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000203 al.append(al.makeFlagArg(args.parser.m_constantCfstringsOption))
204 elif arg.opt is args.parser.f_noConstantCfstringsOption:
205 al.append(al.makeFlagArg(args.parser.m_noConstantCfstringsOption))
206 elif arg.opt is args.parser.WnonportableCfstringsOption:
207 al.append(al.makeFlagArg(args.parser.m_warnNonportableCfstringsOption))
208 elif arg.opt is args.parser.WnoNonportableCfstringsOption:
209 al.append(al.makeFlagArg(args.parser.m_noWarnNonportableCfstringsOption))
210 elif arg.opt is args.parser.f_pascalStringsOption:
211 al.append(al.makeFlagArg(args.parser.m_pascalStringsOption))
212 elif arg.opt is args.parser.f_noPascalStringsOption:
213 al.append(al.makeFlagArg(args.parser.m_noPascalStringsOption))
214 else:
215 al.append(arg)
216
217 # FIXME: Actually, gcc always adds this, but it is filtered
218 # for duplicates somewhere. This also changes the order of
219 # things, so look it up.
220 if arch and args.getValue(arch) == 'x86_64':
221 if not args.getLastArg(args.parser.m_64Option):
222 al.append(al.makeFlagArg(args.parser.m_64Option))
223
224 if not args.getLastArg(args.parser.m_tuneOption):
225 al.append(al.makeJoinedArg('core2',
226 args.parser.m_tuneOption))
227
228 return al
229
Daniel Dunbar43e66e12009-02-17 00:42:05 +0000230 def isMathErrnoDefault(self):
231 return False
232
Daniel Dunbar08dea462009-01-10 02:07:54 +0000233class Generic_GCC_ToolChain(ToolChain):
234 """Generic_GCC_ToolChain - A tool chain using the 'gcc' command to
235 perform all subcommands; this relies on gcc translating the
236 options appropriately."""
237
Daniel Dunbard47bf282009-02-20 01:36:35 +0000238 def __init__(self, driver, archName):
239 super(Generic_GCC_ToolChain, self).__init__(driver, archName)
Daniel Dunbar302b9672009-02-20 01:30:38 +0000240 cc = Tools.GCC_CompileTool(self)
Daniel Dunbaref993d12009-01-29 06:12:22 +0000241 self.clangTool = Tools.Clang_CompileTool(self)
Daniel Dunbar08dea462009-01-10 02:07:54 +0000242 self.toolMap = {
Daniel Dunbar302b9672009-02-20 01:30:38 +0000243 Phases.PreprocessPhase : Tools.GCC_PreprocessTool(self),
Daniel Dunbaref993d12009-01-29 06:12:22 +0000244 Phases.AnalyzePhase : self.clangTool,
Daniel Dunbar34f60f62009-01-26 17:09:15 +0000245 Phases.SyntaxOnlyPhase : cc,
246 Phases.EmitLLVMPhase : cc,
247 Phases.CompilePhase : cc,
Daniel Dunbar302b9672009-02-20 01:30:38 +0000248 Phases.PrecompilePhase : Tools.GCC_PrecompileTool(self),
249 Phases.AssemblePhase : Tools.GCC_AssembleTool(self),
250 Phases.LinkPhase : Tools.GCC_LinkTool(self),
Daniel Dunbar08dea462009-01-10 02:07:54 +0000251 }
252
253 def selectTool(self, action):
254 assert isinstance(action, Phases.JobAction)
Daniel Dunbaref993d12009-01-29 06:12:22 +0000255
Daniel Dunbar72999172009-01-29 23:54:06 +0000256 if self.shouldUseClangCompiler(action):
257 return self.clangTool
Daniel Dunbaref993d12009-01-29 06:12:22 +0000258
Daniel Dunbar08dea462009-01-10 02:07:54 +0000259 return self.toolMap[action.phase.__class__]