blob: d0c1fe19f5fd8bce0addabc1f445ef84abae0529 [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 Dunbar08dea462009-01-10 02:07:54 +000067 self.toolMap = {
Daniel Dunbar7d494092009-01-20 00:47:24 +000068 Phases.PreprocessPhase : Tools.Darwin_X86_PreprocessTool(self),
Daniel Dunbar90c72cd2009-01-21 01:07:49 +000069 Phases.AnalyzePhase : self.clangTool,
70 Phases.SyntaxOnlyPhase : Tools.Darwin_X86_CompileTool(self),
Daniel Dunbarb3492762009-01-13 18:51:26 +000071 Phases.CompilePhase : Tools.Darwin_X86_CompileTool(self),
Daniel Dunbar5ee4aa72009-01-20 05:51:52 +000072 Phases.PrecompilePhase : Tools.Darwin_X86_CompileTool(self),
Daniel Dunbar2dda5412009-01-12 07:45:49 +000073 Phases.AssemblePhase : Tools.Darwin_AssembleTool(self),
74 Phases.LinkPhase : Tools.Darwin_X86_LinkTool(self),
Daniel Dunbar08dea462009-01-10 02:07:54 +000075 Phases.LipoPhase : Tools.LipoTool(),
76 }
77
Daniel Dunbare28f9e92009-01-21 17:18:19 +000078 if archName == 'x86_64':
79 self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
80 '../lib/gcc',
81 self.getToolChainDir(),
82 'x86_64'))
83 self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
84 self.getToolChainDir(),
85 'x86_64'))
Daniel Dunbarf677a602009-01-21 02:03:52 +000086 self.filePathPrefixes.append(os.path.join(self.driver.driverDir,
87 '../lib/gcc',
88 self.getToolChainDir()))
Daniel Dunbare28f9e92009-01-21 17:18:19 +000089 self.filePathPrefixes.append(os.path.join('/usr/lib/gcc',
Daniel Dunbarf677a602009-01-21 02:03:52 +000090 self.getToolChainDir()))
91
92 self.programPathPrefixes.append(os.path.join(self.driver.driverDir,
93 '../libexec/gcc',
94 self.getToolChainDir()))
Daniel Dunbare28f9e92009-01-21 17:18:19 +000095 self.programPathPrefixes.append(os.path.join('/usr/libexec/gcc',
96 self.getToolChainDir()))
Daniel Dunbarf677a602009-01-21 02:03:52 +000097 self.programPathPrefixes.append(self.driver.driverDir)
98
Daniel Dunbar2dda5412009-01-12 07:45:49 +000099 def getToolChainDir(self):
100 return 'i686-apple-darwin%d/%s' % (self.darwinVersion[0],
101 '.'.join(map(str,self.gccVersion)))
102
Daniel Dunbarbafb8f42009-01-12 18:51:02 +0000103 def getMacosxVersionMin(self):
104 major,minor,minorminor = self.darwinVersion
105 return '%d.%d.%d' % (10, major-4, minor)
106
Daniel Dunbar08dea462009-01-10 02:07:54 +0000107 def selectTool(self, action):
108 assert isinstance(action, Phases.JobAction)
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +0000109
Daniel Dunbar386a51c2009-01-14 23:26:40 +0000110 if self.driver.cccClang and self.archName == 'i386':
111 if (action.inputs[0].type in (Types.CType, Types.CTypeNoPP,
112 Types.ObjCType, Types.ObjCTypeNoPP) and
113 isinstance(action.phase, Phases.CompilePhase)):
114 return self.clangTool
115 elif (action.inputs[0].type in (Types.CHeaderType, Types.CHeaderNoPPType,
116 Types.ObjCHeaderType, Types.ObjCHeaderNoPPType) and
117 isinstance(action.phase, Phases.PrecompilePhase)):
118 return self.clangTool
Daniel Dunbar7c2f91b2009-01-14 01:03:36 +0000119
Daniel Dunbar08dea462009-01-10 02:07:54 +0000120 return self.toolMap[action.phase.__class__]
121
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000122 def translateArgs(self, args, arch):
123 args = super(Darwin_X86_ToolChain, self).translateArgs(args, arch)
124
125 # If arch hasn't been bound we don't need to do anything yet.
126 if not arch:
127 return args
128
Daniel Dunbar7e184602009-01-16 20:25:36 +0000129 # FIXME: We really want to get out of the tool chain level
130 # argument translation business, as it makes the driver
131 # functionality much more opaque. For now, we follow gcc
132 # closely solely for the purpose of easily achieving feature
133 # parity & testability. Once we have something that works, we
134 # should reevaluate each translation and try to push it down
135 # into tool specific logic.
136
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000137 al = Arguments.DerivedArgList(args)
138 if not args.getLastArg(args.parser.m_macosxVersionMinOption):
139 al.append(al.makeJoinedArg(self.getMacosxVersionMin(),
140 args.parser.m_macosxVersionMinOption))
141 for arg in args:
Daniel Dunbar7e184602009-01-16 20:25:36 +0000142 # Sob. These is strictly gcc compatible for the time
143 # being. Apple gcc translates options twice, which means
144 # that self-expanding options add duplicates.
145 if arg.opt is args.parser.m_kernelOption:
146 al.append(arg)
147 al.append(al.makeFlagArg(args.parser.staticOption))
148 al.append(al.makeFlagArg(args.parser.staticOption))
149 elif arg.opt is args.parser.dependencyFileOption:
150 al.append(al.makeSeparateArg(args.getValue(arg),
151 args.parser.MFOption))
152 elif arg.opt is args.parser.gfullOption:
153 al.append(al.makeFlagArg(args.parser.gOption))
154 al.append(al.makeFlagArg(args.parser.f_noEliminateUnusedDebugSymbolsOption))
155 elif arg.opt is args.parser.gusedOption:
156 al.append(al.makeFlagArg(args.parser.gOption))
157 al.append(al.makeFlagArg(args.parser.f_eliminateUnusedDebugSymbolsOption))
158 elif arg.opt is args.parser.f_appleKextOption:
159 al.append(arg)
160 al.append(al.makeFlagArg(args.parser.staticOption))
161 al.append(al.makeFlagArg(args.parser.staticOption))
162 elif arg.opt is args.parser.f_terminatedVtablesOption:
163 al.append(al.makeFlagArg(args.parser.f_appleKextOption))
164 al.append(al.makeFlagArg(args.parser.staticOption))
165 elif arg.opt is args.parser.f_indirectVirtualCallsOption:
166 al.append(al.makeFlagArg(args.parser.f_appleKextOption))
167 al.append(al.makeFlagArg(args.parser.staticOption))
168 elif arg.opt is args.parser.f_constantCfstringsOption:
Daniel Dunbar6cb42052009-01-13 21:07:43 +0000169 al.append(al.makeFlagArg(args.parser.m_constantCfstringsOption))
170 elif arg.opt is args.parser.f_noConstantCfstringsOption:
171 al.append(al.makeFlagArg(args.parser.m_noConstantCfstringsOption))
172 elif arg.opt is args.parser.WnonportableCfstringsOption:
173 al.append(al.makeFlagArg(args.parser.m_warnNonportableCfstringsOption))
174 elif arg.opt is args.parser.WnoNonportableCfstringsOption:
175 al.append(al.makeFlagArg(args.parser.m_noWarnNonportableCfstringsOption))
176 elif arg.opt is args.parser.f_pascalStringsOption:
177 al.append(al.makeFlagArg(args.parser.m_pascalStringsOption))
178 elif arg.opt is args.parser.f_noPascalStringsOption:
179 al.append(al.makeFlagArg(args.parser.m_noPascalStringsOption))
180 else:
181 al.append(arg)
182
183 # FIXME: Actually, gcc always adds this, but it is filtered
184 # for duplicates somewhere. This also changes the order of
185 # things, so look it up.
186 if arch and args.getValue(arch) == 'x86_64':
187 if not args.getLastArg(args.parser.m_64Option):
188 al.append(al.makeFlagArg(args.parser.m_64Option))
189
190 if not args.getLastArg(args.parser.m_tuneOption):
191 al.append(al.makeJoinedArg('core2',
192 args.parser.m_tuneOption))
193
194 return al
195
Daniel Dunbar08dea462009-01-10 02:07:54 +0000196class Generic_GCC_ToolChain(ToolChain):
197 """Generic_GCC_ToolChain - A tool chain using the 'gcc' command to
198 perform all subcommands; this relies on gcc translating the
199 options appropriately."""
200
201 def __init__(self, driver):
202 super(Generic_GCC_ToolChain, self).__init__(driver)
203 self.toolMap = {
204 Phases.PreprocessPhase : Tools.GCC_PreprocessTool(),
Daniel Dunbar90c72cd2009-01-21 01:07:49 +0000205 Phases.AnalyzePhase : Tools.Clang_CompileTool(self),
206 Phases.SyntaxOnlyPhase : Tools.GCC_CompileTool(),
Daniel Dunbar08dea462009-01-10 02:07:54 +0000207 Phases.CompilePhase : Tools.GCC_CompileTool(),
208 Phases.PrecompilePhase : Tools.GCC_PrecompileTool(),
209 Phases.AssemblePhase : Tools.GCC_AssembleTool(),
210 Phases.LinkPhase : Tools.GCC_LinkTool(),
211 }
212
213 def selectTool(self, action):
214 assert isinstance(action, Phases.JobAction)
215 return self.toolMap[action.phase.__class__]