blob: 3e8ccb3de3d93c920eed35c403e83b1f4753419b [file] [log] [blame]
Daniel Dunbar47ac7d22009-03-18 06:00:36 +00001//===--- Tools.cpp - Tools Implementations ------------------------------*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Tools.h"
11
Daniel Dunbar1d460332009-03-18 10:01:51 +000012#include "clang/Driver/Action.h"
Daniel Dunbar871adcf2009-03-18 07:06:02 +000013#include "clang/Driver/Arg.h"
Daniel Dunbarb488c1d2009-03-18 08:07:30 +000014#include "clang/Driver/ArgList.h"
Daniel Dunbar1d460332009-03-18 10:01:51 +000015#include "clang/Driver/Driver.h" // FIXME: Remove?
16#include "clang/Driver/DriverDiagnostic.h" // FIXME: Remove?
Daniel Dunbar871adcf2009-03-18 07:06:02 +000017#include "clang/Driver/Compilation.h"
18#include "clang/Driver/Job.h"
Daniel Dunbarb488c1d2009-03-18 08:07:30 +000019#include "clang/Driver/HostInfo.h"
20#include "clang/Driver/Option.h"
21#include "clang/Driver/ToolChain.h"
Daniel Dunbar871adcf2009-03-18 07:06:02 +000022#include "clang/Driver/Util.h"
23
24#include "llvm/ADT/SmallVector.h"
Daniel Dunbar02633b52009-03-26 16:23:12 +000025#include "llvm/Support/Format.h"
26#include "llvm/Support/raw_ostream.h"
Daniel Dunbar871adcf2009-03-18 07:06:02 +000027
28#include "InputInfo.h"
Daniel Dunbar02633b52009-03-26 16:23:12 +000029#include "ToolChains.h"
Daniel Dunbar871adcf2009-03-18 07:06:02 +000030
Daniel Dunbar47ac7d22009-03-18 06:00:36 +000031using namespace clang::driver;
32using namespace clang::driver::tools;
33
34void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Daniel Dunbar871adcf2009-03-18 07:06:02 +000035 Job &Dest,
36 const InputInfo &Output,
Daniel Dunbar62cf6012009-03-18 06:07:59 +000037 const InputInfoList &Inputs,
Daniel Dunbar1d460332009-03-18 10:01:51 +000038 const ArgList &Args,
Daniel Dunbar47ac7d22009-03-18 06:00:36 +000039 const char *LinkingOutput) const {
Daniel Dunbarb488c1d2009-03-18 08:07:30 +000040 ArgStringList CmdArgs;
41
Daniel Dunbar1d460332009-03-18 10:01:51 +000042 if (isa<AnalyzeJobAction>(JA)) {
43 assert(JA.getType() == types::TY_Plist && "Invalid output type.");
44 CmdArgs.push_back("-analyze");
45 } else if (isa<PreprocessJobAction>(JA)) {
Daniel Dunbarcd8e4c42009-03-30 06:36:42 +000046 if (Output.getType() == types::TY_Dependencies)
47 CmdArgs.push_back("-Eonly");
48 else
49 CmdArgs.push_back("-E");
Daniel Dunbar1d460332009-03-18 10:01:51 +000050 } else if (isa<PrecompileJobAction>(JA)) {
51 // No special option needed, driven by -x.
52 //
53 // FIXME: Don't drive this by -x, that is gross.
Daniel Dunbar1d460332009-03-18 10:01:51 +000054 } else {
55 assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");
56
57 if (JA.getType() == types::TY_Nothing) {
58 CmdArgs.push_back("-fsyntax-only");
59 } else if (JA.getType() == types::TY_LLVMAsm) {
60 CmdArgs.push_back("-emit-llvm");
61 } else if (JA.getType() == types::TY_LLVMBC) {
62 CmdArgs.push_back("-emit-llvm-bc");
63 } else if (JA.getType() == types::TY_PP_Asm) {
64 CmdArgs.push_back("-S");
65 }
Daniel Dunbarb488c1d2009-03-18 08:07:30 +000066 }
67
Daniel Dunbar1d460332009-03-18 10:01:51 +000068 // The make clang go fast button.
69 CmdArgs.push_back("-disable-free");
70
71 if (isa<AnalyzeJobAction>(JA)) {
72 // Add default argument set.
73 //
74 // FIXME: Move into clang?
75 CmdArgs.push_back("-warn-dead-stores");
76 CmdArgs.push_back("-checker-cfref");
Ted Kremenek9b646da2009-03-25 00:38:14 +000077 CmdArgs.push_back("-analyzer-eagerly-assume");
Daniel Dunbar1d460332009-03-18 10:01:51 +000078 CmdArgs.push_back("-warn-objc-methodsigs");
79 // Do not enable the missing -dealloc check.
80 // '-warn-objc-missing-dealloc',
81 CmdArgs.push_back("-warn-objc-unused-ivars");
82
83 CmdArgs.push_back("-analyzer-output=plist");
84
85 // Add -Xanalyzer arguments when running as analyzer.
86 Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
87 } else {
88 // Perform argument translation for LLVM backend. This
89 // takes some care in reconciling with llvm-gcc. The
90 // issue is that llvm-gcc translates these options based on
91 // the values in cc1, whereas we are processing based on
92 // the driver arguments.
93 //
94 // FIXME: This is currently broken for -f flags when -fno
95 // variants are present.
96
97 // This comes from the default translation the driver + cc1
98 // would do to enable flag_pic.
99 //
100 // FIXME: Centralize this code.
101 bool PICEnabled = (Args.hasArg(options::OPT_fPIC) ||
102 Args.hasArg(options::OPT_fpic) ||
103 Args.hasArg(options::OPT_fPIE) ||
104 Args.hasArg(options::OPT_fpie));
105 bool PICDisabled = (Args.hasArg(options::OPT_mkernel) ||
106 Args.hasArg(options::OPT_static));
107 const char *Model = getToolChain().GetForcedPicModel();
108 if (!Model) {
109 if (Args.hasArg(options::OPT_mdynamic_no_pic))
110 Model = "dynamic-no-pic";
111 else if (PICDisabled)
112 Model = "static";
113 else if (PICEnabled)
114 Model = "pic";
115 else
116 Model = getToolChain().GetDefaultRelocationModel();
117 }
118 CmdArgs.push_back("--relocation-model");
119 CmdArgs.push_back(Model);
120
121 if (Args.hasArg(options::OPT_ftime_report))
122 CmdArgs.push_back("--time-passes");
123 // FIXME: Set --enable-unsafe-fp-math.
124 if (!Args.hasArg(options::OPT_fomit_frame_pointer))
125 CmdArgs.push_back("--disable-fp-elim");
126 if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
127 options::OPT_fno_zero_initialized_in_bss,
128 true))
129 CmdArgs.push_back("--nozero-initialized-in-bss");
Daniel Dunbarb3fd5002009-03-24 17:59:06 +0000130 if (Args.hasArg(options::OPT_dA) || Args.hasArg(options::OPT_fverbose_asm))
Daniel Dunbar1d460332009-03-18 10:01:51 +0000131 CmdArgs.push_back("--asm-verbose");
132 if (Args.hasArg(options::OPT_fdebug_pass_structure))
133 CmdArgs.push_back("--debug-pass=Structure");
134 if (Args.hasArg(options::OPT_fdebug_pass_arguments))
135 CmdArgs.push_back("--debug-pass=Arguments");
136 // FIXME: set --inline-threshhold=50 if (optimize_size || optimize
137 // < 3)
138 if (Args.hasFlag(options::OPT_funwind_tables,
139 options::OPT_fno_unwind_tables,
140 getToolChain().IsUnwindTablesDefault()))
141 CmdArgs.push_back("--unwind-tables=1");
142 else
143 CmdArgs.push_back("--unwind-tables=0");
144 if (!Args.hasFlag(options::OPT_mred_zone,
145 options::OPT_mno_red_zone,
146 true))
147 CmdArgs.push_back("--disable-red-zone");
148 if (Args.hasFlag(options::OPT_msoft_float,
149 options::OPT_mno_soft_float,
150 false))
151 CmdArgs.push_back("--soft-float");
152
153 // FIXME: Need target hooks.
154 if (memcmp(getToolChain().getPlatform().c_str(), "darwin", 6) == 0) {
155 if (getToolChain().getArchName() == "x86_64")
156 CmdArgs.push_back("--mcpu=core2");
157 else if (getToolChain().getArchName() == "i386")
158 CmdArgs.push_back("--mcpu=yonah");
159 }
160
161 // FIXME: Ignores ordering. Also, we need to find a realistic
162 // solution for this.
163 static const struct {
164 options::ID Pos, Neg;
165 const char *Name;
166 } FeatureOptions[] = {
167 { options::OPT_mmmx, options::OPT_mno_mmx, "mmx" },
168 { options::OPT_msse, options::OPT_mno_sse, "sse" },
169 { options::OPT_msse2, options::OPT_mno_sse2, "sse2" },
170 { options::OPT_msse3, options::OPT_mno_sse3, "sse3" },
171 { options::OPT_mssse3, options::OPT_mno_ssse3, "ssse3" },
172 { options::OPT_msse41, options::OPT_mno_sse41, "sse41" },
173 { options::OPT_msse42, options::OPT_mno_sse42, "sse42" },
174 { options::OPT_msse4a, options::OPT_mno_sse4a, "sse4a" },
175 { options::OPT_m3dnow, options::OPT_mno_3dnow, "3dnow" },
176 { options::OPT_m3dnowa, options::OPT_mno_3dnowa, "3dnowa" }
177 };
178 const unsigned NumFeatureOptions =
179 sizeof(FeatureOptions)/sizeof(FeatureOptions[0]);
180
181 // FIXME: Avoid std::string
182 std::string Attrs;
183 for (unsigned i=0; i < NumFeatureOptions; ++i) {
184 if (Args.hasArg(FeatureOptions[i].Pos)) {
Daniel Dunbar55b3b5f2009-03-19 17:36:04 +0000185 if (!Attrs.empty())
186 Attrs += ',';
Daniel Dunbar1d460332009-03-18 10:01:51 +0000187 Attrs += '+';
188 Attrs += FeatureOptions[i].Name;
189 } else if (Args.hasArg(FeatureOptions[i].Neg)) {
Daniel Dunbar55b3b5f2009-03-19 17:36:04 +0000190 if (!Attrs.empty())
191 Attrs += ',';
Daniel Dunbar1d460332009-03-18 10:01:51 +0000192 Attrs += '-';
193 Attrs += FeatureOptions[i].Name;
194 }
195 }
196 if (!Attrs.empty()) {
197 CmdArgs.push_back("--mattr");
198 CmdArgs.push_back(Args.MakeArgString(Attrs.c_str()));
199 }
200
201 if (Args.hasFlag(options::OPT_fmath_errno,
202 options::OPT_fno_math_errno,
203 getToolChain().IsMathErrnoDefault()))
204 CmdArgs.push_back("--fmath-errno=1");
205 else
206 CmdArgs.push_back("--fmath-errno=0");
207
208 if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
209 CmdArgs.push_back("--limit-float-precision");
210 CmdArgs.push_back(A->getValue(Args));
211 }
212
213 // FIXME: Add --stack-protector-buffer-size=<xxx> on
214 // -fstack-protect.
215
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000216 // Handle dependency file generation.
217 Arg *A;
218 if ((A = Args.getLastArg(options::OPT_M)) ||
219 (A = Args.getLastArg(options::OPT_MM)) ||
220 (A = Args.getLastArg(options::OPT_MD)) ||
221 (A = Args.getLastArg(options::OPT_MMD))) {
222 // Determine the output location.
223 const char *DepFile;
Daniel Dunbarcd8e4c42009-03-30 06:36:42 +0000224 if (Output.getType() == types::TY_Dependencies) {
225 if (Output.isPipe())
226 DepFile = "-";
227 else
228 DepFile = Output.getFilename();
229 } else if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000230 DepFile = MF->getValue(Args);
231 } else if (A->getOption().getId() == options::OPT_M ||
232 A->getOption().getId() == options::OPT_MM) {
233 DepFile = "-";
234 } else {
235 DepFile = darwin::CC1::getDependencyFileName(Args, Inputs);
236 }
237 CmdArgs.push_back("-dependency-file");
238 CmdArgs.push_back(DepFile);
239
240 // Add an -MT option if the user didn't specify their own.
241 // FIXME: This should use -MQ, when we support it.
242 if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
243 const char *DepTarget;
244
Daniel Dunbarcd8e4c42009-03-30 06:36:42 +0000245 // If user provided -o, that is the dependency target, except
246 // when we are only generating a dependency file.
247 Arg *OutputOpt = Args.getLastArg(options::OPT_o);
248 if (OutputOpt && Output.getType() != types::TY_Dependencies) {
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000249 DepTarget = A->getValue(Args);
250 } else {
251 // Otherwise derive from the base input.
252 //
253 // FIXME: This should use the computed output file location.
254 llvm::sys::Path P(Inputs[0].getBaseInput());
255
256 P.eraseSuffix();
257 P.appendSuffix("o");
258 DepTarget = Args.MakeArgString(P.getLast().c_str());
259 }
260
261 CmdArgs.push_back("-MT");
262 CmdArgs.push_back(DepTarget);
263 }
264
265 if (A->getOption().getId() == options::OPT_M ||
266 A->getOption().getId() == options::OPT_MD)
267 CmdArgs.push_back("-sys-header-deps");
268 }
269
Daniel Dunbar1d460332009-03-18 10:01:51 +0000270 Args.AddLastArg(CmdArgs, options::OPT_MP);
271 Args.AddAllArgs(CmdArgs, options::OPT_MT);
272
Daniel Dunbarcd8e4c42009-03-30 06:36:42 +0000273 Arg *Unsupported;
274 if ((Unsupported = Args.getLastArg(options::OPT_MG)) ||
275 (Unsupported = Args.getLastArg(options::OPT_MQ))) {
Daniel Dunbar1d460332009-03-18 10:01:51 +0000276 const Driver &D = getToolChain().getHost().getDriver();
277 D.Diag(clang::diag::err_drv_unsupported_opt)
278 << Unsupported->getOption().getName();
279 }
280 }
281
282 Args.AddAllArgs(CmdArgs, options::OPT_v);
283 Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
284 Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F);
285 Args.AddLastArg(CmdArgs, options::OPT_P);
286 Args.AddAllArgs(CmdArgs, options::OPT_mmacosx_version_min_EQ);
287
288 // Special case debug options to only pass -g to clang. This is
289 // wrong.
290 if (Args.hasArg(options::OPT_g_Group))
291 CmdArgs.push_back("-g");
292
293 Args.AddLastArg(CmdArgs, options::OPT_nostdinc);
294
295 // FIXME: Clang isn't going to accept just anything here.
Daniel Dunbar049853d2009-03-20 19:38:56 +0000296 // FIXME: Use iterator.
Daniel Dunbar1d460332009-03-18 10:01:51 +0000297
Daniel Dunbar049853d2009-03-20 19:38:56 +0000298 // Add -i* options, and automatically translate to -include-pth for
299 // transparent PCH support. It's wonky, but we include looking for
300 // .gch so we can support seamless replacement into a build system
301 // already set up to be generating .gch files.
Daniel Dunbar1d460332009-03-18 10:01:51 +0000302 for (ArgList::const_iterator
303 it = Args.begin(), ie = Args.end(); it != ie; ++it) {
304 const Arg *A = *it;
Daniel Dunbar049853d2009-03-20 19:38:56 +0000305 if (!A->getOption().matches(options::OPT_i_Group))
306 continue;
307
Daniel Dunbar1d460332009-03-18 10:01:51 +0000308 if (A->getOption().matches(options::OPT_include)) {
Daniel Dunbar049853d2009-03-20 19:38:56 +0000309 bool FoundPTH = false;
Daniel Dunbar1d460332009-03-18 10:01:51 +0000310 llvm::sys::Path P(A->getValue(Args));
311 P.appendSuffix("pth");
312 if (P.exists()) {
Daniel Dunbar049853d2009-03-20 19:38:56 +0000313 FoundPTH = true;
Daniel Dunbar1d460332009-03-18 10:01:51 +0000314 } else {
315 P.eraseSuffix();
316 P.appendSuffix("gch");
Daniel Dunbar049853d2009-03-20 19:38:56 +0000317 if (P.exists())
318 FoundPTH = true;
319 }
320
321 if (FoundPTH) {
322 A->claim();
323 CmdArgs.push_back("-include-pth");
324 CmdArgs.push_back(Args.MakeArgString(P.c_str()));
325 continue;
Daniel Dunbar1d460332009-03-18 10:01:51 +0000326 }
327 }
Daniel Dunbar049853d2009-03-20 19:38:56 +0000328
329 // Not translated, render as usual.
330 A->claim();
331 A->render(Args, CmdArgs);
Daniel Dunbar1d460332009-03-18 10:01:51 +0000332 }
333
Daniel Dunbar337a6272009-03-24 20:17:30 +0000334 // Manually translate -O to -O1 and -O4 to -O3; let clang reject
335 // others.
336 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
337 if (A->getOption().getId() == options::OPT_O4)
338 CmdArgs.push_back("-O3");
339 else if (A->getValue(Args)[0] == '\0')
Daniel Dunbar1d460332009-03-18 10:01:51 +0000340 CmdArgs.push_back("-O1");
341 else
Daniel Dunbar5697aa02009-03-18 23:39:35 +0000342 A->render(Args, CmdArgs);
Daniel Dunbar1d460332009-03-18 10:01:51 +0000343 }
344
Daniel Dunbarff7488d2009-03-20 00:52:38 +0000345 Args.AddAllArgs(CmdArgs, options::OPT_clang_W_Group,
346 options::OPT_pedantic_Group);
Daniel Dunbar1d460332009-03-18 10:01:51 +0000347 Args.AddLastArg(CmdArgs, options::OPT_w);
348 Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi,
349 options::OPT_trigraphs);
350
351 if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_)) {
352 CmdArgs.push_back("-ftemplate-depth");
353 CmdArgs.push_back(A->getValue(Args));
354 }
355
356 Args.AddAllArgs(CmdArgs, options::OPT_clang_f_Group);
357
Daniel Dunbarb9f3a772009-03-27 15:22:28 +0000358 // If tool chain translates fpascal-strings, we want to back
359 // translate here.
360 // FIXME: This is gross; that translation should be pulled from the
361 // tool chain.
362 if (Arg *A = Args.getLastArg(options::OPT_mpascal_strings,
363 options::OPT_mno_pascal_strings)) {
364 if (A->getOption().matches(options::OPT_mpascal_strings))
365 CmdArgs.push_back("-fpascal-strings");
366 else
367 CmdArgs.push_back("-fno-pascal-strings");
368 }
369
Daniel Dunbar1d460332009-03-18 10:01:51 +0000370 Args.AddLastArg(CmdArgs, options::OPT_dM);
371
372 Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
373
374 // FIXME: Always pass the full triple once we aren't concerned with
375 // ccc compat.
376 CmdArgs.push_back("-arch");
377 CmdArgs.push_back(getToolChain().getArchName().c_str());
378
Daniel Dunbarcd8e4c42009-03-30 06:36:42 +0000379 if (Output.getType() == types::TY_Dependencies) {
380 // Handled with other dependency code.
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000381 } else if (Output.isPipe()) {
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000382 CmdArgs.push_back("-o");
383 CmdArgs.push_back("-");
Daniel Dunbar115a7922009-03-19 07:29:38 +0000384 } else if (Output.isFilename()) {
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000385 CmdArgs.push_back("-o");
Daniel Dunbar115a7922009-03-19 07:29:38 +0000386 CmdArgs.push_back(Output.getFilename());
387 } else {
388 assert(Output.isNothing() && "Invalid output.");
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000389 }
390
Daniel Dunbar1d460332009-03-18 10:01:51 +0000391 for (InputInfoList::const_iterator
392 it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
393 const InputInfo &II = *it;
394 CmdArgs.push_back("-x");
395 CmdArgs.push_back(types::getTypeName(II.getType()));
396 if (II.isPipe())
397 CmdArgs.push_back("-");
Daniel Dunbar115a7922009-03-19 07:29:38 +0000398 else if (II.isFilename())
399 CmdArgs.push_back(II.getFilename());
Daniel Dunbar1d460332009-03-18 10:01:51 +0000400 else
Daniel Dunbar115a7922009-03-19 07:29:38 +0000401 II.getInputArg().renderAsInput(Args, CmdArgs);
Daniel Dunbar1d460332009-03-18 10:01:51 +0000402 }
403
404 const char *Exec =
Daniel Dunbard7d5f022009-03-24 02:24:46 +0000405 Args.MakeArgString(getToolChain().GetProgramPath(C, "clang-cc").c_str());
Daniel Dunbar1d460332009-03-18 10:01:51 +0000406 Dest.addCommand(new Command(Exec, CmdArgs));
Daniel Dunbara880db02009-03-23 19:03:36 +0000407
408 // Claim some arguments which clang doesn't support, but we don't
409 // care to warn the user about.
410
411 // FIXME: Use iterator.
412 for (ArgList::const_iterator
413 it = Args.begin(), ie = Args.end(); it != ie; ++it) {
414 const Arg *A = *it;
415 if (A->getOption().matches(options::OPT_clang_ignored_W_Group) ||
416 A->getOption().matches(options::OPT_clang_ignored_f_Group))
417 A->claim();
418 }
Daniel Dunbar47ac7d22009-03-18 06:00:36 +0000419}
420
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000421void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
422 Job &Dest,
423 const InputInfo &Output,
424 const InputInfoList &Inputs,
Daniel Dunbar1d460332009-03-18 10:01:51 +0000425 const ArgList &Args,
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000426 const char *LinkingOutput) const {
427 ArgStringList CmdArgs;
Daniel Dunbar47ac7d22009-03-18 06:00:36 +0000428
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000429 for (ArgList::const_iterator
Daniel Dunbar1d460332009-03-18 10:01:51 +0000430 it = Args.begin(), ie = Args.end(); it != ie; ++it) {
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000431 Arg *A = *it;
Daniel Dunbar75877192009-03-19 07:55:12 +0000432 if (A->getOption().hasForwardToGCC()) {
433 // It is unfortunate that we have to claim here, as this means
434 // we will basically never report anything interesting for
435 // platforms using a generic gcc.
436 A->claim();
Daniel Dunbar1d460332009-03-18 10:01:51 +0000437 A->render(Args, CmdArgs);
Daniel Dunbar75877192009-03-19 07:55:12 +0000438 }
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000439 }
440
441 RenderExtraToolArgs(CmdArgs);
442
443 // If using a driver driver, force the arch.
444 if (getToolChain().getHost().useDriverDriver()) {
445 CmdArgs.push_back("-arch");
446 CmdArgs.push_back(getToolChain().getArchName().c_str());
447 }
448
449 if (Output.isPipe()) {
450 CmdArgs.push_back("-o");
451 CmdArgs.push_back("-");
Daniel Dunbar115a7922009-03-19 07:29:38 +0000452 } else if (Output.isFilename()) {
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000453 CmdArgs.push_back("-o");
Daniel Dunbar115a7922009-03-19 07:29:38 +0000454 CmdArgs.push_back(Output.getFilename());
455 } else {
456 assert(Output.isNothing() && "Unexpected output");
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000457 CmdArgs.push_back("-fsyntax-only");
Daniel Dunbar115a7922009-03-19 07:29:38 +0000458 }
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000459
460
461 // Only pass -x if gcc will understand it; otherwise hope gcc
462 // understands the suffix correctly. The main use case this would go
463 // wrong in is for linker inputs if they happened to have an odd
464 // suffix; really the only way to get this to happen is a command
465 // like '-x foobar a.c' which will treat a.c like a linker input.
466 //
467 // FIXME: For the linker case specifically, can we safely convert
468 // inputs into '-Wl,' options?
469 for (InputInfoList::const_iterator
470 it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
471 const InputInfo &II = *it;
472 if (types::canTypeBeUserSpecified(II.getType())) {
473 CmdArgs.push_back("-x");
474 CmdArgs.push_back(types::getTypeName(II.getType()));
475 }
476
477 if (II.isPipe())
478 CmdArgs.push_back("-");
Daniel Dunbar115a7922009-03-19 07:29:38 +0000479 else if (II.isFilename())
480 CmdArgs.push_back(II.getFilename());
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000481 else
Daniel Dunbar115a7922009-03-19 07:29:38 +0000482 // Don't render as input, we need gcc to do the translations.
483 II.getInputArg().render(Args, CmdArgs);
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000484 }
485
Daniel Dunbar632f50e2009-03-18 21:34:08 +0000486 const char *Exec =
487 Args.MakeArgString(getToolChain().GetProgramPath(C, "gcc").c_str());
488 Dest.addCommand(new Command(Exec, CmdArgs));
Daniel Dunbar47ac7d22009-03-18 06:00:36 +0000489}
490
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000491void gcc::Preprocess::RenderExtraToolArgs(ArgStringList &CmdArgs) const {
492 CmdArgs.push_back("-E");
Daniel Dunbar47ac7d22009-03-18 06:00:36 +0000493}
494
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000495void gcc::Precompile::RenderExtraToolArgs(ArgStringList &CmdArgs) const {
496 // The type is good enough.
Daniel Dunbar47ac7d22009-03-18 06:00:36 +0000497}
498
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000499void gcc::Compile::RenderExtraToolArgs(ArgStringList &CmdArgs) const {
500 CmdArgs.push_back("-S");
Daniel Dunbar47ac7d22009-03-18 06:00:36 +0000501}
502
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000503void gcc::Assemble::RenderExtraToolArgs(ArgStringList &CmdArgs) const {
504 CmdArgs.push_back("-c");
Daniel Dunbar47ac7d22009-03-18 06:00:36 +0000505}
Daniel Dunbarb488c1d2009-03-18 08:07:30 +0000506
507void gcc::Link::RenderExtraToolArgs(ArgStringList &CmdArgs) const {
508 // The types are (hopefully) good enough.
509}
510
Daniel Dunbar40f12652009-03-29 17:08:39 +0000511const char *darwin::CC1::getCC1Name(types::ID Type) const {
512 switch (Type) {
513 default:
514 assert(0 && "Unexpected type for Darwin CC1 tool.");
515 case types::TY_Asm:
516 case types::TY_C: case types::TY_CHeader:
517 case types::TY_PP_C: case types::TY_PP_CHeader:
518 return "cc1";
519 case types::TY_ObjC: case types::TY_ObjCHeader:
520 case types::TY_PP_ObjC: case types::TY_PP_ObjCHeader:
521 return "cc1obj";
522 case types::TY_CXX: case types::TY_CXXHeader:
523 case types::TY_PP_CXX: case types::TY_PP_CXXHeader:
524 return "cc1plus";
525 case types::TY_ObjCXX: case types::TY_ObjCXXHeader:
526 case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXXHeader:
527 return "cc1objplus";
528 }
529}
530
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000531const char *darwin::CC1::getBaseInputName(const ArgList &Args,
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000532 const InputInfoList &Inputs) {
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000533 llvm::sys::Path P(Inputs[0].getBaseInput());
534 return Args.MakeArgString(P.getLast().c_str());
535}
536
537const char *darwin::CC1::getBaseInputStem(const ArgList &Args,
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000538 const InputInfoList &Inputs) {
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000539 const char *Str = getBaseInputName(Args, Inputs);
540
541 if (const char *End = strchr(Str, '.'))
542 return Args.MakeArgString(std::string(Str, End).c_str());
543
544 return Str;
545}
546
547const char *
548darwin::CC1::getDependencyFileName(const ArgList &Args,
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000549 const InputInfoList &Inputs) {
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000550 // FIXME: Think about this more.
551 std::string Res;
552
553 if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
554 std::string Str(OutputOpt->getValue(Args));
555
556 Res = Str.substr(0, Str.rfind('.'));
557 } else
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000558 Res = darwin::CC1::getBaseInputStem(Args, Inputs);
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000559
560 return Args.MakeArgString((Res + ".d").c_str());
561}
562
563void darwin::CC1::AddCC1Args(const ArgList &Args,
564 ArgStringList &CmdArgs) const {
565 // Derived from cc1 spec.
566
567 // FIXME: -fapple-kext seems to disable this too. Investigate.
568 if (!Args.hasArg(options::OPT_mkernel) && !Args.hasArg(options::OPT_static) &&
569 !Args.hasArg(options::OPT_mdynamic_no_pic))
570 CmdArgs.push_back("-fPIC");
571
572 // gcc has some code here to deal with when no -mmacosx-version-min
573 // and no -miphoneos-version-min is present, but this never happens
574 // due to tool chain specific argument translation.
575
576 // FIXME: Remove mthumb
577 // FIXME: Remove mno-thumb
578 // FIXME: Remove faltivec
579 // FIXME: Remove mno-fused-madd
580 // FIXME: Remove mlong-branch
581 // FIXME: Remove mlongcall
582 // FIXME: Remove mcpu=G4
583 // FIXME: Remove mcpu=G5
584
585 if (Args.hasArg(options::OPT_g_Flag) &&
586 !Args.hasArg(options::OPT_fno_eliminate_unused_debug_symbols))
587 CmdArgs.push_back("-feliminate-unused-debug-symbols");
588}
589
590void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
591 const InputInfoList &Inputs,
592 const ArgStringList &OutputArgs) const {
593 const Driver &D = getToolChain().getHost().getDriver();
594
595 // Derived from cc1_options spec.
596 if (Args.hasArg(options::OPT_fast) ||
597 Args.hasArg(options::OPT_fastf) ||
598 Args.hasArg(options::OPT_fastcp))
599 CmdArgs.push_back("-O3");
600
601 if (Arg *A = Args.getLastArg(options::OPT_pg))
602 if (Args.hasArg(options::OPT_fomit_frame_pointer))
603 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
604 << A->getAsString(Args) << "-fomit-frame-pointer";
605
606 AddCC1Args(Args, CmdArgs);
607
608 if (!Args.hasArg(options::OPT_Q))
609 CmdArgs.push_back("-quiet");
610
611 CmdArgs.push_back("-dumpbase");
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000612 CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs));
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000613
614 Args.AddAllArgs(CmdArgs, options::OPT_d_Group);
615
616 Args.AddAllArgs(CmdArgs, options::OPT_m_Group);
617 Args.AddAllArgs(CmdArgs, options::OPT_a_Group);
618
619 // FIXME: The goal is to use the user provided -o if that is our
620 // final output, otherwise to drive from the original input
621 // name. Find a clean way to go about this.
622 if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) &&
623 Args.hasArg(options::OPT_o)) {
624 Arg *OutputOpt = Args.getLastArg(options::OPT_o);
625 CmdArgs.push_back("-auxbase-strip");
626 CmdArgs.push_back(OutputOpt->getValue(Args));
627 } else {
628 CmdArgs.push_back("-auxbase");
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000629 CmdArgs.push_back(darwin::CC1::getBaseInputStem(Args, Inputs));
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000630 }
631
632 Args.AddAllArgs(CmdArgs, options::OPT_g_Group);
633
634 Args.AddAllArgs(CmdArgs, options::OPT_O);
635 // FIXME: -Wall is getting some special treatment. Investigate.
636 Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
637 Args.AddLastArg(CmdArgs, options::OPT_w);
638 Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi,
639 options::OPT_trigraphs);
640 if (Args.hasArg(options::OPT_v))
641 CmdArgs.push_back("-version");
642 if (Args.hasArg(options::OPT_pg))
643 CmdArgs.push_back("-p");
644 Args.AddLastArg(CmdArgs, options::OPT_p);
645
646 // The driver treats -fsyntax-only specially.
647 Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
648
649 Args.AddAllArgs(CmdArgs, options::OPT_undef);
650 if (Args.hasArg(options::OPT_Qn))
651 CmdArgs.push_back("-fno-ident");
652
653 // FIXME: This isn't correct.
654 //Args.AddLastArg(CmdArgs, options::OPT__help)
655 //Args.AddLastArg(CmdArgs, options::OPT__targetHelp)
656
657 CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
658
659 // FIXME: Still don't get what is happening here. Investigate.
660 Args.AddAllArgs(CmdArgs, options::OPT__param);
661
662 if (Args.hasArg(options::OPT_fmudflap) ||
663 Args.hasArg(options::OPT_fmudflapth)) {
664 CmdArgs.push_back("-fno-builtin");
665 CmdArgs.push_back("-fno-merge-constants");
666 }
667
668 if (Args.hasArg(options::OPT_coverage)) {
669 CmdArgs.push_back("-fprofile-arcs");
670 CmdArgs.push_back("-ftest-coverage");
671 }
672
673 if (types::isCXX(Inputs[0].getType()))
674 CmdArgs.push_back("-D__private_extern__=extern");
675}
676
677void darwin::CC1::AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
678 const InputInfoList &Inputs,
679 const ArgStringList &OutputArgs) const {
680 // Derived from cpp_options
681 AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs);
682
683 CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
684
685 AddCC1Args(Args, CmdArgs);
686
687 // NOTE: The code below has some commonality with cpp_options, but
688 // in classic gcc style ends up sending things in different
689 // orders. This may be a good merge candidate once we drop pedantic
690 // compatibility.
691
692 Args.AddAllArgs(CmdArgs, options::OPT_m_Group);
693 Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi,
694 options::OPT_trigraphs);
695 Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
696 Args.AddLastArg(CmdArgs, options::OPT_w);
697
698 // The driver treats -fsyntax-only specially.
699 Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
700
701 if (Args.hasArg(options::OPT_g_Group) && !Args.hasArg(options::OPT_g0) &&
702 !Args.hasArg(options::OPT_fno_working_directory))
703 CmdArgs.push_back("-fworking-directory");
704
705 Args.AddAllArgs(CmdArgs, options::OPT_O);
706 Args.AddAllArgs(CmdArgs, options::OPT_undef);
707 if (Args.hasArg(options::OPT_save_temps))
708 CmdArgs.push_back("-fpch-preprocess");
709}
710
711void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args,
712 ArgStringList &CmdArgs,
713 const InputInfoList &Inputs) const
714{
715 const Driver &D = getToolChain().getHost().getDriver();
716
717 // Derived from cpp_unique_options.
718 Arg *A;
719 if ((A = Args.getLastArg(options::OPT_C)) ||
720 (A = Args.getLastArg(options::OPT_CC))) {
721 if (!Args.hasArg(options::OPT_E))
722 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
723 << A->getAsString(Args) << "-E";
724 }
725 if (!Args.hasArg(options::OPT_Q))
726 CmdArgs.push_back("-quiet");
727 Args.AddAllArgs(CmdArgs, options::OPT_nostdinc);
728 Args.AddLastArg(CmdArgs, options::OPT_v);
729 Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F);
730 Args.AddLastArg(CmdArgs, options::OPT_P);
731
732 // FIXME: Handle %I properly.
733 if (getToolChain().getArchName() == "x86_64") {
734 CmdArgs.push_back("-imultilib");
735 CmdArgs.push_back("x86_64");
736 }
737
738 if (Args.hasArg(options::OPT_MD)) {
739 CmdArgs.push_back("-MD");
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000740 CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs));
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000741 }
742
743 if (Args.hasArg(options::OPT_MMD)) {
744 CmdArgs.push_back("-MMD");
Daniel Dunbara5a7bd02009-03-30 00:34:04 +0000745 CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs));
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000746 }
747
748 Args.AddLastArg(CmdArgs, options::OPT_M);
749 Args.AddLastArg(CmdArgs, options::OPT_MM);
750 Args.AddAllArgs(CmdArgs, options::OPT_MF);
751 Args.AddLastArg(CmdArgs, options::OPT_MG);
752 Args.AddLastArg(CmdArgs, options::OPT_MP);
753 Args.AddAllArgs(CmdArgs, options::OPT_MQ);
754 Args.AddAllArgs(CmdArgs, options::OPT_MT);
755 if (!Args.hasArg(options::OPT_M) && !Args.hasArg(options::OPT_MM) &&
756 (Args.hasArg(options::OPT_MD) || Args.hasArg(options::OPT_MMD))) {
757 if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
758 CmdArgs.push_back("-MQ");
759 CmdArgs.push_back(OutputOpt->getValue(Args));
760 }
761 }
762
763 Args.AddLastArg(CmdArgs, options::OPT_remap);
764 if (Args.hasArg(options::OPT_g3))
765 CmdArgs.push_back("-dD");
766 Args.AddLastArg(CmdArgs, options::OPT_H);
767
768 AddCPPArgs(Args, CmdArgs);
769
770 Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U, options::OPT_A);
771 Args.AddAllArgs(CmdArgs, options::OPT_i_Group);
772
773 for (InputInfoList::const_iterator
774 it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
775 const InputInfo &II = *it;
776
777 if (II.isPipe())
778 CmdArgs.push_back("-");
779 else
780 CmdArgs.push_back(II.getFilename());
781 }
782
783 Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
784 options::OPT_Xpreprocessor);
785
786 if (Args.hasArg(options::OPT_fmudflap)) {
787 CmdArgs.push_back("-D_MUDFLAP");
788 CmdArgs.push_back("-include");
789 CmdArgs.push_back("mf-runtime.h");
790 }
791
792 if (Args.hasArg(options::OPT_fmudflapth)) {
793 CmdArgs.push_back("-D_MUDFLAP");
794 CmdArgs.push_back("-D_MUDFLAPTH");
795 CmdArgs.push_back("-include");
796 CmdArgs.push_back("mf-runtime.h");
797 }
798}
799
800void darwin::CC1::AddCPPArgs(const ArgList &Args,
801 ArgStringList &CmdArgs) const {
802 // Derived from cpp spec.
803
804 if (Args.hasArg(options::OPT_static)) {
805 // The gcc spec is broken here, it refers to dynamic but
806 // that has been translated. Start by being bug compatible.
807
808 // if (!Args.hasArg(arglist.parser.dynamicOption))
809 CmdArgs.push_back("-D__STATIC__");
810 } else
811 CmdArgs.push_back("-D__DYNAMIC__");
812
813 if (Args.hasArg(options::OPT_pthread))
814 CmdArgs.push_back("-D_REENTRANT");
815}
816
Daniel Dunbar40f12652009-03-29 17:08:39 +0000817void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
818 Job &Dest, const InputInfo &Output,
819 const InputInfoList &Inputs,
820 const ArgList &Args,
821 const char *LinkingOutput) const {
822 ArgStringList CmdArgs;
823
824 assert(Inputs.size() == 1 && "Unexpected number of inputs!");
825
826 CmdArgs.push_back("-E");
827
828 if (Args.hasArg(options::OPT_traditional) ||
829 Args.hasArg(options::OPT_ftraditional) ||
830 Args.hasArg(options::OPT_traditional_cpp))
831 CmdArgs.push_back("-traditional-cpp");
832
833 ArgStringList OutputArgs;
834 if (Output.isFilename()) {
835 OutputArgs.push_back("-o");
836 OutputArgs.push_back(Output.getFilename());
837 } else {
838 assert(Output.isPipe() && "Unexpected CC1 output.");
839 }
840
Daniel Dunbar9120f172009-03-29 22:27:40 +0000841 if (Args.hasArg(options::OPT_E)) {
842 AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
843 } else {
844 AddCPPOptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
845 CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
846 }
Daniel Dunbar40f12652009-03-29 17:08:39 +0000847
848 const char *CC1Name = getCC1Name(Inputs[0].getType());
849 const char *Exec =
850 Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name).c_str());
851 Dest.addCommand(new Command(Exec, CmdArgs));
852}
853
854void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
855 Job &Dest, const InputInfo &Output,
856 const InputInfoList &Inputs,
857 const ArgList &Args,
858 const char *LinkingOutput) const {
859 const Driver &D = getToolChain().getHost().getDriver();
860 ArgStringList CmdArgs;
861
862 assert(Inputs.size() == 1 && "Unexpected number of inputs!");
863
864 types::ID InputType = Inputs[0].getType();
865 const Arg *A;
866 if ((A = Args.getLastArg(options::OPT_traditional)) ||
867 (A = Args.getLastArg(options::OPT_ftraditional)))
868 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
869 << A->getAsString(Args) << "-E";
870
871 if (Output.getType() == types::TY_LLVMAsm)
872 CmdArgs.push_back("-emit-llvm");
873 else if (Output.getType() == types::TY_LLVMBC)
874 CmdArgs.push_back("-emit-llvm-bc");
875
876 ArgStringList OutputArgs;
877 if (Output.getType() != types::TY_PCH) {
878 OutputArgs.push_back("-o");
879 if (Output.isPipe())
880 OutputArgs.push_back("-");
881 else if (Output.isNothing())
882 OutputArgs.push_back("/dev/null");
883 else
884 OutputArgs.push_back(Output.getFilename());
885 }
886
887 // There is no need for this level of compatibility, but it makes
888 // diffing easier.
889 bool OutputArgsEarly = (Args.hasArg(options::OPT_fsyntax_only) ||
890 Args.hasArg(options::OPT_S));
891
892 if (types::getPreprocessedType(InputType) != types::TY_INVALID) {
Daniel Dunbara3ec60e2009-03-29 18:40:18 +0000893 AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs);
Daniel Dunbar40f12652009-03-29 17:08:39 +0000894 if (OutputArgsEarly) {
895 AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
896 } else {
897 AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
898 CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
899 }
900 } else {
901 CmdArgs.push_back("-fpreprocessed");
902
903 // FIXME: There is a spec command to remove
904 // -fpredictive-compilation args here. Investigate.
905
906 for (InputInfoList::const_iterator
907 it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
908 const InputInfo &II = *it;
909
910 if (II.isPipe())
911 CmdArgs.push_back("-");
912 else
913 CmdArgs.push_back(II.getFilename());
914 }
915
916 if (OutputArgsEarly) {
917 AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
918 } else {
919 AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
920 CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
921 }
922 }
923
924 if (Output.getType() == types::TY_PCH) {
925 assert(Output.isFilename() && "Invalid PCH output.");
926
927 CmdArgs.push_back("-o");
928 // NOTE: gcc uses a temp .s file for this, but there doesn't seem
929 // to be a good reason.
930 CmdArgs.push_back("/dev/null");
931
932 CmdArgs.push_back("--output-pch=");
933 CmdArgs.push_back(Output.getFilename());
934 }
935
936 const char *CC1Name = getCC1Name(Inputs[0].getType());
937 const char *Exec =
938 Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name).c_str());
939 Dest.addCommand(new Command(Exec, CmdArgs));
940}
941
Daniel Dunbar8cac5f72009-03-20 16:06:39 +0000942void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
943 Job &Dest, const InputInfo &Output,
944 const InputInfoList &Inputs,
945 const ArgList &Args,
946 const char *LinkingOutput) const {
947 ArgStringList CmdArgs;
948
949 assert(Inputs.size() == 1 && "Unexpected number of inputs.");
950 const InputInfo &Input = Inputs[0];
951
952 // Bit of a hack, this is only used for original inputs.
953 if (Input.isFilename() &&
954 strcmp(Input.getFilename(), Input.getBaseInput()) == 0 &&
955 Args.hasArg(options::OPT_g_Group))
956 CmdArgs.push_back("--gstabs");
957
958 // Derived from asm spec.
959 CmdArgs.push_back("-arch");
960 CmdArgs.push_back(getToolChain().getArchName().c_str());
961
962 CmdArgs.push_back("-force_cpusubtype_ALL");
963 if ((Args.hasArg(options::OPT_mkernel) ||
964 Args.hasArg(options::OPT_static) ||
965 Args.hasArg(options::OPT_fapple_kext)) &&
966 !Args.hasArg(options::OPT_dynamic))
967 CmdArgs.push_back("-static");
968
969 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
970 options::OPT_Xassembler);
971
972 assert(Output.isFilename() && "Unexpected lipo output.");
973 CmdArgs.push_back("-o");
974 CmdArgs.push_back(Output.getFilename());
975
976 if (Input.isPipe()) {
977 CmdArgs.push_back("-");
978 } else {
979 assert(Input.isFilename() && "Invalid input.");
980 CmdArgs.push_back(Input.getFilename());
981 }
982
983 // asm_final spec is empty.
984
985 const char *Exec =
986 Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str());
987 Dest.addCommand(new Command(Exec, CmdArgs));
988}
Daniel Dunbarff7488d2009-03-20 00:52:38 +0000989
Daniel Dunbar02633b52009-03-26 16:23:12 +0000990static const char *MakeFormattedString(const ArgList &Args,
991 const llvm::format_object_base &Fmt) {
992 std::string Str;
993 llvm::raw_string_ostream(Str) << Fmt;
994 return Args.MakeArgString(Str.c_str());
995}
996
997/// Helper routine for seeing if we should use dsymutil; this is a
998/// gcc compatible hack, we should remove it and use the input
999/// type information.
1000static bool isSourceSuffix(const char *Str) {
1001 // match: 'C', 'CPP', 'c', 'cc', 'cp', 'c++', 'cpp', 'cxx', 'm',
1002 // 'mm'.
1003 switch (strlen(Str)) {
1004 default:
1005 return false;
1006 case 1:
1007 return (memcmp(Str, "C", 1) == 0 ||
1008 memcmp(Str, "c", 1) == 0 ||
1009 memcmp(Str, "m", 1) == 0);
1010 case 2:
1011 return (memcmp(Str, "cc", 2) == 0 ||
1012 memcmp(Str, "cp", 2) == 0 ||
1013 memcmp(Str, "mm", 2) == 0);
1014 case 3:
1015 return (memcmp(Str, "CPP", 3) == 0 ||
1016 memcmp(Str, "c++", 3) == 0 ||
1017 memcmp(Str, "cpp", 3) == 0 ||
1018 memcmp(Str, "cxx", 3) == 0);
1019 }
1020}
1021
1022static bool isMacosxVersionLT(unsigned (&A)[3], unsigned (&B)[3]) {
1023 for (unsigned i=0; i < 3; ++i) {
1024 if (A[i] > B[i]) return false;
1025 if (A[i] < B[i]) return true;
1026 }
1027 return false;
1028}
1029
1030static bool isMacosxVersionLT(unsigned (&A)[3],
1031 unsigned V0, unsigned V1=0, unsigned V2=0) {
1032 unsigned B[3] = { V0, V1, V2 };
1033 return isMacosxVersionLT(A, B);
1034}
1035
1036static bool isMacosxVersionGTE(unsigned(&A)[3],
1037 unsigned V0, unsigned V1=0, unsigned V2=0) {
1038 return !isMacosxVersionLT(A, V0, V1, V2);
1039}
1040
1041const toolchains::Darwin_X86 &darwin::Link::getDarwinToolChain() const {
1042 return reinterpret_cast<const toolchains::Darwin_X86&>(getToolChain());
1043}
1044
1045void darwin::Link::AddDarwinArch(const ArgList &Args,
1046 ArgStringList &CmdArgs) const {
1047 // Derived from darwin_arch spec.
1048 CmdArgs.push_back("-arch");
1049 CmdArgs.push_back(getToolChain().getArchName().c_str());
1050}
1051
1052void darwin::Link::AddDarwinSubArch(const ArgList &Args,
1053 ArgStringList &CmdArgs) const {
1054 // Derived from darwin_subarch spec, not sure what the distinction
1055 // exists for but at least for this chain it is the same.
1056 AddDarwinArch(Args, CmdArgs);
1057}
1058
1059void darwin::Link::AddLinkArgs(const ArgList &Args,
1060 ArgStringList &CmdArgs) const {
1061 const Driver &D = getToolChain().getHost().getDriver();
1062
1063 // Derived from the "link" spec.
1064 Args.AddAllArgs(CmdArgs, options::OPT_static);
1065 if (!Args.hasArg(options::OPT_static))
1066 CmdArgs.push_back("-dynamic");
1067 if (Args.hasArg(options::OPT_fgnu_runtime)) {
1068 // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
1069 // here. How do we wish to handle such things?
1070 }
1071
1072 if (!Args.hasArg(options::OPT_dynamiclib)) {
1073 if (Args.hasArg(options::OPT_force__cpusubtype__ALL)) {
1074 AddDarwinArch(Args, CmdArgs);
1075 CmdArgs.push_back("-force_cpusubtype_ALL");
1076 } else
1077 AddDarwinSubArch(Args, CmdArgs);
1078
1079 Args.AddLastArg(CmdArgs, options::OPT_bundle);
1080 Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
1081 Args.AddAllArgs(CmdArgs, options::OPT_client__name);
1082
1083 Arg *A;
1084 if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
1085 (A = Args.getLastArg(options::OPT_current__version)) ||
1086 (A = Args.getLastArg(options::OPT_install__name)))
1087 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
1088 << A->getAsString(Args) << "-dynamiclib";
1089
1090 Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
1091 Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
1092 Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
1093 } else {
1094 CmdArgs.push_back("-dylib");
1095
1096 Arg *A;
1097 if ((A = Args.getLastArg(options::OPT_bundle)) ||
1098 (A = Args.getLastArg(options::OPT_bundle__loader)) ||
1099 (A = Args.getLastArg(options::OPT_client__name)) ||
1100 (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
1101 (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
1102 (A = Args.getLastArg(options::OPT_private__bundle)))
1103 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1104 << A->getAsString(Args) << "-dynamiclib";
1105
1106 Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
1107 "-dylib_compatibility_version");
1108 Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
1109 "-dylib_current_version");
1110
1111 if (Args.hasArg(options::OPT_force__cpusubtype__ALL)) {
1112 AddDarwinArch(Args, CmdArgs);
1113 // NOTE: We don't add -force_cpusubtype_ALL on this path. Ok.
1114 } else
1115 AddDarwinSubArch(Args, CmdArgs);
1116
1117 Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
1118 "-dylib_install_name");
1119 }
1120
1121 Args.AddLastArg(CmdArgs, options::OPT_all__load);
1122 Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
1123 Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
1124 Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
1125 Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
1126 Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
1127 Args.AddLastArg(CmdArgs, options::OPT_dynamic);
1128 Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
1129 Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
1130 Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
1131 Args.AddAllArgs(CmdArgs, options::OPT_image__base);
1132 Args.AddAllArgs(CmdArgs, options::OPT_init);
1133
1134 if (!Args.hasArg(options::OPT_mmacosx_version_min_EQ)) {
1135 if (!Args.hasArg(options::OPT_miphoneos_version_min_EQ)) {
1136 // FIXME: I don't understand what is going on here. This is
1137 // supposed to come from darwin_ld_minversion, but gcc doesn't
1138 // seem to be following that; it must be getting overridden
1139 // somewhere.
1140 CmdArgs.push_back("-macosx_version_min");
1141 CmdArgs.push_back(getDarwinToolChain().getMacosxVersionStr());
1142 }
1143 } else {
1144 // Adding all arguments doesn't make sense here but this is what
1145 // gcc does.
1146 Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ,
1147 "-macosx_version_min");
1148 }
1149
1150 Args.AddAllArgsTranslated(CmdArgs, options::OPT_miphoneos_version_min_EQ,
1151 "-iphoneos_version_min");
1152 Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
1153 Args.AddLastArg(CmdArgs, options::OPT_multi__module);
1154 Args.AddLastArg(CmdArgs, options::OPT_single__module);
1155 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
1156 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
1157
1158 if (Args.hasArg(options::OPT_fpie))
1159 CmdArgs.push_back("-pie");
1160
1161 Args.AddLastArg(CmdArgs, options::OPT_prebind);
1162 Args.AddLastArg(CmdArgs, options::OPT_noprebind);
1163 Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
1164 Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
1165 Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
1166 Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
1167 Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
1168 Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
1169 Args.AddAllArgs(CmdArgs, options::OPT_segprot);
1170 Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
1171 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
1172 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
1173 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
1174 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
1175 Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
1176 Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
1177 Args.AddAllArgsTranslated(CmdArgs, options::OPT_isysroot, "-syslibroot");
1178 Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
1179 Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
1180 Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
1181 Args.AddAllArgs(CmdArgs, options::OPT_undefined);
1182 Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
1183 Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
1184
1185 if (!Args.hasArg(options::OPT_weak__reference__mismatches)) {
1186 CmdArgs.push_back("-weak_reference_mismatches");
1187 CmdArgs.push_back("non-weak");
1188 }
1189
1190 Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
1191 Args.AddAllArgs(CmdArgs, options::OPT_y);
1192 Args.AddLastArg(CmdArgs, options::OPT_w);
1193 Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
1194 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
1195 Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
1196 Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
1197 Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
1198 Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
1199 Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
1200 Args.AddLastArg(CmdArgs, options::OPT_whyload);
1201 Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
1202 Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
1203 Args.AddLastArg(CmdArgs, options::OPT_dylinker);
1204 Args.AddLastArg(CmdArgs, options::OPT_Mach);
1205}
1206
1207void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
1208 Job &Dest, const InputInfo &Output,
1209 const InputInfoList &Inputs,
1210 const ArgList &Args,
1211 const char *LinkingOutput) const {
1212 assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
1213 // The logic here is derived from gcc's behavior; most of which
1214 // comes from specs (starting with link_command). Consult gcc for
1215 // more information.
1216
1217 // FIXME: The spec references -fdump= which seems to have
1218 // disappeared?
1219
1220 ArgStringList CmdArgs;
1221
1222 // I'm not sure why this particular decomposition exists in gcc, but
1223 // we follow suite for ease of comparison.
1224 AddLinkArgs(Args, CmdArgs);
1225
1226 // FIXME: gcc has %{x} in here. How could this ever happen? Cruft?
1227 Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
1228 Args.AddAllArgs(CmdArgs, options::OPT_s);
1229 Args.AddAllArgs(CmdArgs, options::OPT_t);
1230 Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
1231 Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
1232 Args.AddAllArgs(CmdArgs, options::OPT_A);
1233 Args.AddLastArg(CmdArgs, options::OPT_e);
1234 Args.AddAllArgs(CmdArgs, options::OPT_m_Separate);
1235 Args.AddAllArgs(CmdArgs, options::OPT_r);
1236
1237 // FIXME: This is just being pedantically bug compatible, gcc
1238 // doesn't *mean* to forward this, it just does (yay for pattern
1239 // matching). It doesn't work, of course.
1240 Args.AddAllArgs(CmdArgs, options::OPT_object);
1241
1242 CmdArgs.push_back("-o");
1243 CmdArgs.push_back(Output.getFilename());
1244
1245 unsigned MacosxVersion[3];
1246 if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ)) {
1247 bool HadExtra;
1248 if (!Driver::GetReleaseVersion(A->getValue(Args), MacosxVersion[0],
1249 MacosxVersion[1], MacosxVersion[2],
1250 HadExtra) ||
1251 HadExtra) {
1252 const Driver &D = getToolChain().getHost().getDriver();
1253 D.Diag(clang::diag::err_drv_invalid_version_number)
1254 << A->getAsString(Args);
1255 }
1256 } else {
1257 getDarwinToolChain().getMacosxVersion(MacosxVersion);
1258 }
1259
1260 if (!Args.hasArg(options::OPT_A) &&
1261 !Args.hasArg(options::OPT_nostdlib) &&
1262 !Args.hasArg(options::OPT_nostartfiles)) {
1263 // Derived from startfile spec.
1264 if (Args.hasArg(options::OPT_dynamiclib)) {
1265 // Derived from darwin_dylib1 spec.
1266 if (Args.hasArg(options::OPT_miphoneos_version_min_EQ) ||
1267 isMacosxVersionLT(MacosxVersion, 10, 5))
1268 CmdArgs.push_back("-ldylib1.o");
1269 else
1270 CmdArgs.push_back("-ldylib1.10.5.o");
1271 } else {
1272 if (Args.hasArg(options::OPT_bundle)) {
1273 if (!Args.hasArg(options::OPT_static))
1274 CmdArgs.push_back("-lbundle1.o");
1275 } else {
1276 if (Args.hasArg(options::OPT_pg)) {
1277 if (Args.hasArg(options::OPT_static) ||
1278 Args.hasArg(options::OPT_object) ||
1279 Args.hasArg(options::OPT_preload)) {
1280 CmdArgs.push_back("-lgcrt0.o");
1281 } else {
1282 CmdArgs.push_back("-lgcrt1.o");
1283
1284 // darwin_crt2 spec is empty.
1285 }
1286 } else {
1287 if (Args.hasArg(options::OPT_static) ||
1288 Args.hasArg(options::OPT_object) ||
1289 Args.hasArg(options::OPT_preload)) {
1290 CmdArgs.push_back("-lcrt0.o");
1291 } else {
1292 // Derived from darwin_crt1 spec.
1293 if (Args.hasArg(options::OPT_miphoneos_version_min_EQ) ||
1294 isMacosxVersionLT(MacosxVersion, 10, 5)) {
1295 CmdArgs.push_back("-lcrt1.o");
1296 } else {
1297 CmdArgs.push_back("-lcrt1.10.5.o");
1298
1299 // darwin_crt2 spec is empty.
1300 }
1301 }
1302 }
1303 }
1304 }
1305
1306 if (Args.hasArg(options::OPT_shared_libgcc) &&
1307 !Args.hasArg(options::OPT_miphoneos_version_min_EQ) &&
1308 isMacosxVersionLT(MacosxVersion, 10, 5)) {
1309 const char *Str = getToolChain().GetFilePath(C, "crt3.o").c_str();
1310 CmdArgs.push_back(Args.MakeArgString(Str));
1311 }
1312 }
1313
1314 Args.AddAllArgs(CmdArgs, options::OPT_L);
1315
1316 if (Args.hasArg(options::OPT_fopenmp))
1317 // This is more complicated in gcc...
1318 CmdArgs.push_back("-lgomp");
1319
1320 // FIXME: Derive these correctly.
1321 const char *TCDir = getDarwinToolChain().getToolChainDir().c_str();
1322 if (getToolChain().getArchName() == "x86_64") {
1323 CmdArgs.push_back(MakeFormattedString(Args,
1324 llvm::format("-L/usr/lib/gcc/%s/x86_64", TCDir)));
1325 // Intentionally duplicated for (temporary) gcc bug compatibility.
1326 CmdArgs.push_back(MakeFormattedString(Args,
1327 llvm::format("-L/usr/lib/gcc/%s/x86_64", TCDir)));
1328 }
1329 CmdArgs.push_back(MakeFormattedString(Args,
1330 llvm::format("-L/usr/lib/%s", TCDir)));
1331 CmdArgs.push_back(MakeFormattedString(Args,
1332 llvm::format("-L/usr/lib/gcc/%s", TCDir)));
1333 // Intentionally duplicated for (temporary) gcc bug compatibility.
1334 CmdArgs.push_back(MakeFormattedString(Args,
1335 llvm::format("-L/usr/lib/gcc/%s", TCDir)));
1336 CmdArgs.push_back(MakeFormattedString(Args,
1337 llvm::format("-L/usr/lib/gcc/%s/../../../%s", TCDir, TCDir)));
1338 CmdArgs.push_back(MakeFormattedString(Args,
1339 llvm::format("-L/usr/lib/gcc/%s/../../..", TCDir)));
1340
1341 for (InputInfoList::const_iterator
1342 it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
1343 const InputInfo &II = *it;
1344 if (II.isFilename())
1345 CmdArgs.push_back(II.getFilename());
1346 else
1347 II.getInputArg().renderAsInput(Args, CmdArgs);
1348 }
1349
1350 if (LinkingOutput) {
1351 CmdArgs.push_back("-arch_multiple");
1352 CmdArgs.push_back("-final_output");
1353 CmdArgs.push_back(LinkingOutput);
1354 }
1355
1356 if (Args.hasArg(options::OPT_fprofile_arcs) ||
1357 Args.hasArg(options::OPT_fprofile_generate) ||
1358 Args.hasArg(options::OPT_fcreate_profile) ||
1359 Args.hasArg(options::OPT_coverage))
1360 CmdArgs.push_back("-lgcov");
1361
1362 if (Args.hasArg(options::OPT_fnested_functions))
1363 CmdArgs.push_back("-allow_stack_execute");
1364
1365 if (!Args.hasArg(options::OPT_nostdlib) &&
1366 !Args.hasArg(options::OPT_nodefaultlibs)) {
1367 // link_ssp spec is empty.
1368
1369 // Derived from libgcc spec.
1370 if (Args.hasArg(options::OPT_static)) {
1371 CmdArgs.push_back("-lgcc_static");
1372 } else if (Args.hasArg(options::OPT_static_libgcc)) {
1373 CmdArgs.push_back("-lgcc_eh");
1374 CmdArgs.push_back("-lgcc");
1375 } else if (Args.hasArg(options::OPT_miphoneos_version_min_EQ)) {
1376 // Derived from darwin_iphoneos_libgcc spec.
1377 CmdArgs.push_back("-lgcc_s.10.5");
1378 CmdArgs.push_back("-lgcc");
1379 } else if (Args.hasArg(options::OPT_shared_libgcc) ||
1380 Args.hasArg(options::OPT_fexceptions) ||
1381 Args.hasArg(options::OPT_fgnu_runtime)) {
1382 if (isMacosxVersionLT(MacosxVersion, 10, 5))
1383 CmdArgs.push_back("-lgcc_s.10.4");
1384 else
1385 CmdArgs.push_back("-lgcc_s.10.5");
1386 CmdArgs.push_back("-lgcc");
1387 } else {
1388 if (isMacosxVersionLT(MacosxVersion, 10, 5) &&
1389 isMacosxVersionGTE(MacosxVersion, 10, 3, 9))
1390 CmdArgs.push_back("-lgcc_s.10.4");
1391 if (isMacosxVersionGTE(MacosxVersion, 10, 5))
1392 CmdArgs.push_back("-lgcc_s.10.5");
1393 CmdArgs.push_back("-lgcc");
1394 }
1395
1396 // Derived from lib spec.
1397 if (!Args.hasArg(options::OPT_static))
1398 CmdArgs.push_back("-lSystem");
1399 }
1400
1401 if (!Args.hasArg(options::OPT_A) &&
1402 !Args.hasArg(options::OPT_nostdlib) &&
1403 !Args.hasArg(options::OPT_nostartfiles)) {
1404 // endfile_spec is empty.
1405 }
1406
1407 Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
1408 Args.AddAllArgs(CmdArgs, options::OPT_F);
1409
1410 const char *Exec =
1411 Args.MakeArgString(getToolChain().GetProgramPath(C, "collect2").c_str());
1412 Dest.addCommand(new Command(Exec, CmdArgs));
1413
1414 if (Args.getLastArg(options::OPT_g_Group) &&
1415 !Args.getLastArg(options::OPT_gstabs) &&
1416 !Args.getLastArg(options::OPT_g0)) {
1417 // FIXME: This is gross, but matches gcc. The test only considers
1418 // the suffix (not the -x type), and then only of the first
1419 // input. Awesome.
1420 const char *Suffix = strchr(Inputs[0].getBaseInput(), '.');
1421 if (Suffix && isSourceSuffix(Suffix + 1)) {
1422 const char *Exec =
1423 Args.MakeArgString(getToolChain().GetProgramPath(C, "dsymutil").c_str());
1424 ArgStringList CmdArgs;
1425 CmdArgs.push_back(Output.getFilename());
1426 C.getJobs().addCommand(new Command(Exec, CmdArgs));
1427 }
1428 }
1429}
1430
Daniel Dunbarff7488d2009-03-20 00:52:38 +00001431void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
Daniel Dunbar8cac5f72009-03-20 16:06:39 +00001432 Job &Dest, const InputInfo &Output,
Daniel Dunbarff7488d2009-03-20 00:52:38 +00001433 const InputInfoList &Inputs,
1434 const ArgList &Args,
1435 const char *LinkingOutput) const {
1436 ArgStringList CmdArgs;
1437
1438 CmdArgs.push_back("-create");
1439 assert(Output.isFilename() && "Unexpected lipo output.");
Daniel Dunbara428df82009-03-24 00:24:37 +00001440
1441 CmdArgs.push_back("-output");
Daniel Dunbarff7488d2009-03-20 00:52:38 +00001442 CmdArgs.push_back(Output.getFilename());
Daniel Dunbara428df82009-03-24 00:24:37 +00001443
Daniel Dunbarff7488d2009-03-20 00:52:38 +00001444 for (InputInfoList::const_iterator
1445 it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
1446 const InputInfo &II = *it;
1447 assert(II.isFilename() && "Unexpected lipo input.");
1448 CmdArgs.push_back(II.getFilename());
1449 }
1450 const char *Exec =
1451 Args.MakeArgString(getToolChain().GetProgramPath(C, "lipo").c_str());
1452 Dest.addCommand(new Command(Exec, CmdArgs));
1453}