blob: 6ce6ebc341fa1de5a474af8785df75a01d85149e [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 Dunbar72999172009-01-29 23:54:06 +000057 def shouldUseClangCompiler(self, action):
58 # If user requested no clang, or this isn't a "compile" phase,
59 # or this isn't a C family option, then don't use clang.
60 if (self.driver.cccNoClang or
61 not isinstance(action.phase, (Phases.PreprocessPhase,
62 Phases.CompilePhase,
63 Phases.SyntaxOnlyPhase,
64 Phases.EmitLLVMPhase,
65 Phases.PrecompilePhase)) or
66 action.inputs[0].type not in Types.cTypesSet):
67 return False
68
69 if self.driver.cccNoClangPreprocessor:
70 if isinstance(action.phase, Phases.PreprocessPhase):
71 return False
72
73 if self.driver.cccNoClangCXX:
74 if action.inputs[0].type in Types.cxxTypesSet:
75 return False
76
77 return True
78
Daniel Dunbarc2148562009-01-12 04:21:12 +000079class Darwin_X86_ToolChain(ToolChain):
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +000080 def __init__(self, driver, darwinVersion, gccVersion, archName):
Daniel Dunbarc2148562009-01-12 04:21:12 +000081 super(Darwin_X86_ToolChain, self).__init__(driver)
Daniel Dunbar2dda5412009-01-12 07:45:49 +000082 assert isinstance(darwinVersion, tuple) and len(darwinVersion) == 3
83 assert isinstance(gccVersion, tuple) and len(gccVersion) == 3
84 self.darwinVersion = darwinVersion
85 self.gccVersion = gccVersion
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +000086 self.archName = archName
Daniel Dunbar2dda5412009-01-12 07:45:49 +000087
Daniel Dunbar90c72cd2009-01-21 01:07:49 +000088 self.clangTool = Tools.Clang_CompileTool(self)
Daniel Dunbar34f60f62009-01-26 17:09:15 +000089 cc = Tools.Darwin_X86_CompileTool(self)
Daniel Dunbar08dea462009-01-10 02:07:54 +000090 self.toolMap = {
Daniel Dunbar7d494092009-01-20 00:47:24 +000091 Phases.PreprocessPhase : Tools.Darwin_X86_PreprocessTool(self),
Daniel Dunbar90c72cd2009-01-21 01:07:49 +000092 Phases.AnalyzePhase : self.clangTool,
Daniel Dunbar34f60f62009-01-26 17:09:15 +000093 Phases.SyntaxOnlyPhase : cc,
94 Phases.EmitLLVMPhase : cc,
95 Phases.CompilePhase : cc,
96 Phases.PrecompilePhase : cc,
Daniel Dunbar2dda5412009-01-12 07:45:49 +000097 Phases.AssemblePhase : Tools.Darwin_AssembleTool(self),
98 Phases.LinkPhase : Tools.Darwin_X86_LinkTool(self),
Daniel Dunbar08dea462009-01-10 02:07:54 +000099 Phases.LipoPhase : Tools.LipoTool(),
100 }
101
Daniel Dunbare28f9e92009-01-21 17:18:19 +0000102 if archName == 'x86_64':
103 self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
104 '../lib/gcc',
105 self.getToolChainDir(),
106 'x86_64'))
107 self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
108 self.getToolChainDir(),
109 'x86_64'))
Daniel Dunbarf677a602009-01-21 02:03:52 +0000110 self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
111 '../lib/gcc',
112 self.getToolChainDir()))
Daniel Dunbare28f9e92009-01-21 17:18:19 +0000113 self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
Daniel Dunbarf677a602009-01-21 02:03:52 +0000114 self.getToolChainDir()))
115
116 self.programPathPrefixes.append(os.path.join(self.driver.driverDir,
117 '../libexec/gcc',
118 self.getToolChainDir()))
Daniel Dunbare28f9e92009-01-21 17:18:19 +0000119 self.programPathPrefixes.append(os.path.join('/usr/libexec/gcc',
120 self.getToolChainDir()))
Daniel Dunbarf677a602009-01-21 02:03:52 +0000121 self.programPathPrefixes.append(self.driver.driverDir)
122
Daniel Dunbar2dda5412009-01-12 07:45:49 +0000123 def getToolChainDir(self):
124 return 'i686-apple-darwin%d/%s' % (self.darwinVersion[0],
125 '.'.join(map(str,self.gccVersion)))
126
Daniel Dunbarbafb8f42009-01-12 18:51:02 +0000127 def getMacosxVersionMin(self):
128 major,minor,minorminor = self.darwinVersion
129 return '%d.%d.%d' % (10, major-4, minor)
130
Daniel Dunbar72999172009-01-29 23:54:06 +0000131 def shouldUseClangCompiler(self, action):
132 if not super(Darwin_X86_ToolChain, self).shouldUseClangCompiler(action):
133 return False
134
135 # Only use clang if user didn't override archs, or this is one
136 # of the ones they provided.
137 if (not self.driver.cccClangArchs or
138 self.archName in self.driver.cccClangArchs):
139 return True
140
141 return False
142
Daniel Dunbar08dea462009-01-10 02:07:54 +0000143 def selectTool(self, action):
144 assert isinstance(action, Phases.JobAction)
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +0000145
Daniel Dunbar72999172009-01-29 23:54:06 +0000146 if self.shouldUseClangCompiler(action):
147 return self.clangTool
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +0000148
Daniel Dunbar08dea462009-01-10 02:07:54 +0000149 return self.toolMap[action.phase.__class__]
150
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000151 def translateArgs(self, args, arch):
152 args = super(Darwin_X86_ToolChain, self).translateArgs(args, arch)
153
154 # If arch hasn't been bound we don't need to do anything yet.
155 if not arch:
156 return args
157
Daniel Dunbar7e184602009-01-16 20:25:36 +0000158 # FIXME: We really want to get out of the tool chain level
159 # argument translation business, as it makes the driver
160 # functionality much more opaque. For now, we follow gcc
161 # closely solely for the purpose of easily achieving feature
162 # parity & testability. Once we have something that works, we
163 # should reevaluate each translation and try to push it down
164 # into tool specific logic.
165
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000166 al = Arguments.DerivedArgList(args)
167 if not args.getLastArg(args.parser.m_macosxVersionMinOption):
168 al.append(al.makeJoinedArg(self.getMacosxVersionMin(),
169 args.parser.m_macosxVersionMinOption))
170 for arg in args:
Daniel Dunbar7e184602009-01-16 20:25:36 +0000171 # Sob. These is strictly gcc compatible for the time
172 # being. Apple gcc translates options twice, which means
173 # that self-expanding options add duplicates.
174 if arg.opt is args.parser.m_kernelOption:
175 al.append(arg)
176 al.append(al.makeFlagArg(args.parser.staticOption))
177 al.append(al.makeFlagArg(args.parser.staticOption))
178 elif arg.opt is args.parser.dependencyFileOption:
179 al.append(al.makeSeparateArg(args.getValue(arg),
180 args.parser.MFOption))
181 elif arg.opt is args.parser.gfullOption:
182 al.append(al.makeFlagArg(args.parser.gOption))
183 al.append(al.makeFlagArg(args.parser.f_noEliminateUnusedDebugSymbolsOption))
184 elif arg.opt is args.parser.gusedOption:
185 al.append(al.makeFlagArg(args.parser.gOption))
186 al.append(al.makeFlagArg(args.parser.f_eliminateUnusedDebugSymbolsOption))
187 elif arg.opt is args.parser.f_appleKextOption:
188 al.append(arg)
189 al.append(al.makeFlagArg(args.parser.staticOption))
190 al.append(al.makeFlagArg(args.parser.staticOption))
191 elif arg.opt is args.parser.f_terminatedVtablesOption:
192 al.append(al.makeFlagArg(args.parser.f_appleKextOption))
193 al.append(al.makeFlagArg(args.parser.staticOption))
194 elif arg.opt is args.parser.f_indirectVirtualCallsOption:
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_constantCfstringsOption:
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000198 al.append(al.makeFlagArg(args.parser.m_constantCfstringsOption))
199 elif arg.opt is args.parser.f_noConstantCfstringsOption:
200 al.append(al.makeFlagArg(args.parser.m_noConstantCfstringsOption))
201 elif arg.opt is args.parser.WnonportableCfstringsOption:
202 al.append(al.makeFlagArg(args.parser.m_warnNonportableCfstringsOption))
203 elif arg.opt is args.parser.WnoNonportableCfstringsOption:
204 al.append(al.makeFlagArg(args.parser.m_noWarnNonportableCfstringsOption))
205 elif arg.opt is args.parser.f_pascalStringsOption:
206 al.append(al.makeFlagArg(args.parser.m_pascalStringsOption))
207 elif arg.opt is args.parser.f_noPascalStringsOption:
208 al.append(al.makeFlagArg(args.parser.m_noPascalStringsOption))
209 else:
210 al.append(arg)
211
212 # FIXME: Actually, gcc always adds this, but it is filtered
213 # for duplicates somewhere. This also changes the order of
214 # things, so look it up.
215 if arch and args.getValue(arch) == 'x86_64':
216 if not args.getLastArg(args.parser.m_64Option):
217 al.append(al.makeFlagArg(args.parser.m_64Option))
218
219 if not args.getLastArg(args.parser.m_tuneOption):
220 al.append(al.makeJoinedArg('core2',
221 args.parser.m_tuneOption))
222
223 return al
224
Daniel Dunbar08dea462009-01-10 02:07:54 +0000225class Generic_GCC_ToolChain(ToolChain):
226 """Generic_GCC_ToolChain - A tool chain using the 'gcc' command to
227 perform all subcommands; this relies on gcc translating the
228 options appropriately."""
229
230 def __init__(self, driver):
231 super(Generic_GCC_ToolChain, self).__init__(driver)
Daniel Dunbar34f60f62009-01-26 17:09:15 +0000232 cc = Tools.GCC_CompileTool()
Daniel Dunbaref993d12009-01-29 06:12:22 +0000233 self.clangTool = Tools.Clang_CompileTool(self)
Daniel Dunbar08dea462009-01-10 02:07:54 +0000234 self.toolMap = {
235 Phases.PreprocessPhase : Tools.GCC_PreprocessTool(),
Daniel Dunbaref993d12009-01-29 06:12:22 +0000236 Phases.AnalyzePhase : self.clangTool,
Daniel Dunbar34f60f62009-01-26 17:09:15 +0000237 Phases.SyntaxOnlyPhase : cc,
238 Phases.EmitLLVMPhase : cc,
239 Phases.CompilePhase : cc,
Daniel Dunbar08dea462009-01-10 02:07:54 +0000240 Phases.PrecompilePhase : Tools.GCC_PrecompileTool(),
241 Phases.AssemblePhase : Tools.GCC_AssembleTool(),
242 Phases.LinkPhase : Tools.GCC_LinkTool(),
243 }
244
245 def selectTool(self, action):
246 assert isinstance(action, Phases.JobAction)
Daniel Dunbaref993d12009-01-29 06:12:22 +0000247
Daniel Dunbar72999172009-01-29 23:54:06 +0000248 if self.shouldUseClangCompiler(action):
249 return self.clangTool
Daniel Dunbaref993d12009-01-29 06:12:22 +0000250
Daniel Dunbar08dea462009-01-10 02:07:54 +0000251 return self.toolMap[action.phase.__class__]