blob: ac9a493cbff772b340242d70335371037f3acb3a [file] [log] [blame]
Dan Gohmanf17a25c2007-07-18 16:29:46 +00001//===-- ToolRunner.cpp ----------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the interfaces described in the ToolRunner.h file.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "toolrunner"
15#include "ToolRunner.h"
16#include "llvm/Config/config.h" // for HAVE_LINK_R
17#include "llvm/System/Program.h"
18#include "llvm/Support/CommandLine.h"
19#include "llvm/Support/Debug.h"
20#include "llvm/Support/FileUtilities.h"
21#include <fstream>
22#include <sstream>
23#include <iostream>
24using namespace llvm;
25
26namespace {
27 cl::opt<std::string>
28 RSHHost("rsh-host",
29 cl::desc("Remote execution (rsh) host"));
30
31 cl::opt<std::string>
32 RSHUser("rsh-user",
33 cl::desc("Remote execution (rsh) user id"));
34}
35
36ToolExecutionError::~ToolExecutionError() throw() { }
37
38/// RunProgramWithTimeout - This function provides an alternate interface to the
39/// sys::Program::ExecuteAndWait interface.
40/// @see sys:Program::ExecuteAndWait
41static int RunProgramWithTimeout(const sys::Path &ProgramPath,
42 const char **Args,
43 const sys::Path &StdInFile,
44 const sys::Path &StdOutFile,
45 const sys::Path &StdErrFile,
46 unsigned NumSeconds = 0,
47 unsigned MemoryLimit = 0) {
48 const sys::Path* redirects[3];
49 redirects[0] = &StdInFile;
50 redirects[1] = &StdOutFile;
51 redirects[2] = &StdErrFile;
52
53 if (0) {
54 std::cerr << "RUN:";
55 for (unsigned i = 0; Args[i]; ++i)
56 std::cerr << " " << Args[i];
57 std::cerr << "\n";
58 }
59
60 return
61 sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects,
62 NumSeconds, MemoryLimit);
63}
64
65
66
67static void ProcessFailure(sys::Path ProgPath, const char** Args) {
68 std::ostringstream OS;
69 OS << "\nError running tool:\n ";
70 for (const char **Arg = Args; *Arg; ++Arg)
71 OS << " " << *Arg;
72 OS << "\n";
73
74 // Rerun the compiler, capturing any error messages to print them.
75 sys::Path ErrorFilename("error_messages");
76 std::string ErrMsg;
77 if (ErrorFilename.makeUnique(true, &ErrMsg)) {
78 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
79 exit(1);
80 }
81 RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename,
82 ErrorFilename); // FIXME: check return code ?
83
84 // Print out the error messages generated by GCC if possible...
85 std::ifstream ErrorFile(ErrorFilename.c_str());
86 if (ErrorFile) {
87 std::copy(std::istreambuf_iterator<char>(ErrorFile),
88 std::istreambuf_iterator<char>(),
89 std::ostreambuf_iterator<char>(OS));
90 ErrorFile.close();
91 }
92
93 ErrorFilename.eraseFromDisk();
94 throw ToolExecutionError(OS.str());
95}
96
97//===---------------------------------------------------------------------===//
98// LLI Implementation of AbstractIntepreter interface
99//
100namespace {
101 class LLI : public AbstractInterpreter {
102 std::string LLIPath; // The path to the LLI executable
103 std::vector<std::string> ToolArgs; // Args to pass to LLI
104 public:
105 LLI(const std::string &Path, const std::vector<std::string> *Args)
106 : LLIPath(Path) {
107 ToolArgs.clear ();
108 if (Args) { ToolArgs = *Args; }
109 }
110
111 virtual int ExecuteProgram(const std::string &Bitcode,
112 const std::vector<std::string> &Args,
113 const std::string &InputFile,
114 const std::string &OutputFile,
115 const std::vector<std::string> &GCCArgs,
116 const std::vector<std::string> &SharedLibs =
117 std::vector<std::string>(),
118 unsigned Timeout = 0,
119 unsigned MemoryLimit = 0);
120 };
121}
122
123int LLI::ExecuteProgram(const std::string &Bitcode,
124 const std::vector<std::string> &Args,
125 const std::string &InputFile,
126 const std::string &OutputFile,
127 const std::vector<std::string> &GCCArgs,
128 const std::vector<std::string> &SharedLibs,
129 unsigned Timeout,
130 unsigned MemoryLimit) {
131 if (!SharedLibs.empty())
132 throw ToolExecutionError("LLI currently does not support "
133 "loading shared libraries.");
134
135 if (!GCCArgs.empty())
136 throw ToolExecutionError("LLI currently does not support "
137 "GCC Arguments.");
138 std::vector<const char*> LLIArgs;
139 LLIArgs.push_back(LLIPath.c_str());
140 LLIArgs.push_back("-force-interpreter=true");
141
142 // Add any extra LLI args.
143 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
144 LLIArgs.push_back(ToolArgs[i].c_str());
145
146 LLIArgs.push_back(Bitcode.c_str());
147 // Add optional parameters to the running program from Argv
148 for (unsigned i=0, e = Args.size(); i != e; ++i)
149 LLIArgs.push_back(Args[i].c_str());
150 LLIArgs.push_back(0);
151
152 std::cout << "<lli>" << std::flush;
153 DEBUG(std::cerr << "\nAbout to run:\t";
154 for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i)
155 std::cerr << " " << LLIArgs[i];
156 std::cerr << "\n";
157 );
158 return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
159 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
160 Timeout, MemoryLimit);
161}
162
163// LLI create method - Try to find the LLI executable
164AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath,
165 std::string &Message,
166 const std::vector<std::string> *ToolArgs) {
167 std::string LLIPath = FindExecutable("lli", ProgPath).toString();
168 if (!LLIPath.empty()) {
169 Message = "Found lli: " + LLIPath + "\n";
170 return new LLI(LLIPath, ToolArgs);
171 }
172
173 Message = "Cannot find `lli' in executable directory or PATH!\n";
174 return 0;
175}
176
177//===----------------------------------------------------------------------===//
178// LLC Implementation of AbstractIntepreter interface
179//
180GCC::FileType LLC::OutputCode(const std::string &Bitcode,
181 sys::Path &OutputAsmFile) {
182 sys::Path uniqueFile(Bitcode+".llc.s");
183 std::string ErrMsg;
184 if (uniqueFile.makeUnique(true, &ErrMsg)) {
185 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
186 exit(1);
187 }
188 OutputAsmFile = uniqueFile;
189 std::vector<const char *> LLCArgs;
190 LLCArgs.push_back (LLCPath.c_str());
191
192 // Add any extra LLC args.
193 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
194 LLCArgs.push_back(ToolArgs[i].c_str());
195
196 LLCArgs.push_back ("-o");
197 LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file
198 LLCArgs.push_back ("-f"); // Overwrite as necessary...
199 LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
200 LLCArgs.push_back (0);
201
202 std::cout << "<llc>" << std::flush;
203 DEBUG(std::cerr << "\nAbout to run:\t";
204 for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
205 std::cerr << " " << LLCArgs[i];
206 std::cerr << "\n";
207 );
208 if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0],
209 sys::Path(), sys::Path(), sys::Path()))
210 ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]);
211
212 return GCC::AsmFile;
213}
214
215void LLC::compileProgram(const std::string &Bitcode) {
216 sys::Path OutputAsmFile;
217 OutputCode(Bitcode, OutputAsmFile);
218 OutputAsmFile.eraseFromDisk();
219}
220
221int LLC::ExecuteProgram(const std::string &Bitcode,
222 const std::vector<std::string> &Args,
223 const std::string &InputFile,
224 const std::string &OutputFile,
225 const std::vector<std::string> &ArgsForGCC,
226 const std::vector<std::string> &SharedLibs,
227 unsigned Timeout,
228 unsigned MemoryLimit) {
229
230 sys::Path OutputAsmFile;
231 OutputCode(Bitcode, OutputAsmFile);
232 FileRemover OutFileRemover(OutputAsmFile);
233
234 std::vector<std::string> GCCArgs(ArgsForGCC);
235 GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end());
236
237 // Assuming LLC worked, compile the result with GCC and run it.
238 return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile,
239 InputFile, OutputFile, GCCArgs,
240 Timeout, MemoryLimit);
241}
242
243/// createLLC - Try to find the LLC executable
244///
245LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath,
246 std::string &Message,
247 const std::vector<std::string> *Args) {
248 std::string LLCPath = FindExecutable("llc", ProgramPath).toString();
249 if (LLCPath.empty()) {
250 Message = "Cannot find `llc' in executable directory or PATH!\n";
251 return 0;
252 }
253
254 Message = "Found llc: " + LLCPath + "\n";
255 GCC *gcc = GCC::create(ProgramPath, Message);
256 if (!gcc) {
257 std::cerr << Message << "\n";
258 exit(1);
259 }
260 return new LLC(LLCPath, gcc, Args);
261}
262
263//===---------------------------------------------------------------------===//
264// JIT Implementation of AbstractIntepreter interface
265//
266namespace {
267 class JIT : public AbstractInterpreter {
268 std::string LLIPath; // The path to the LLI executable
269 std::vector<std::string> ToolArgs; // Args to pass to LLI
270 public:
271 JIT(const std::string &Path, const std::vector<std::string> *Args)
272 : LLIPath(Path) {
273 ToolArgs.clear ();
274 if (Args) { ToolArgs = *Args; }
275 }
276
277 virtual int ExecuteProgram(const std::string &Bitcode,
278 const std::vector<std::string> &Args,
279 const std::string &InputFile,
280 const std::string &OutputFile,
281 const std::vector<std::string> &GCCArgs =
282 std::vector<std::string>(),
283 const std::vector<std::string> &SharedLibs =
284 std::vector<std::string>(),
285 unsigned Timeout =0,
286 unsigned MemoryLimit =0);
287 };
288}
289
290int JIT::ExecuteProgram(const std::string &Bitcode,
291 const std::vector<std::string> &Args,
292 const std::string &InputFile,
293 const std::string &OutputFile,
294 const std::vector<std::string> &GCCArgs,
295 const std::vector<std::string> &SharedLibs,
296 unsigned Timeout,
297 unsigned MemoryLimit) {
298 if (!GCCArgs.empty())
299 throw ToolExecutionError("JIT does not support GCC Arguments.");
300 // Construct a vector of parameters, incorporating those from the command-line
301 std::vector<const char*> JITArgs;
302 JITArgs.push_back(LLIPath.c_str());
303 JITArgs.push_back("-force-interpreter=false");
304
305 // Add any extra LLI args.
306 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
307 JITArgs.push_back(ToolArgs[i].c_str());
308
309 for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
310 JITArgs.push_back("-load");
311 JITArgs.push_back(SharedLibs[i].c_str());
312 }
313 JITArgs.push_back(Bitcode.c_str());
314 // Add optional parameters to the running program from Argv
315 for (unsigned i=0, e = Args.size(); i != e; ++i)
316 JITArgs.push_back(Args[i].c_str());
317 JITArgs.push_back(0);
318
319 std::cout << "<jit>" << std::flush;
320 DEBUG(std::cerr << "\nAbout to run:\t";
321 for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i)
322 std::cerr << " " << JITArgs[i];
323 std::cerr << "\n";
324 );
325 DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n");
326 return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
327 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
328 Timeout, MemoryLimit);
329}
330
331/// createJIT - Try to find the LLI executable
332///
333AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath,
334 std::string &Message, const std::vector<std::string> *Args) {
335 std::string LLIPath = FindExecutable("lli", ProgPath).toString();
336 if (!LLIPath.empty()) {
337 Message = "Found lli: " + LLIPath + "\n";
338 return new JIT(LLIPath, Args);
339 }
340
341 Message = "Cannot find `lli' in executable directory or PATH!\n";
342 return 0;
343}
344
345GCC::FileType CBE::OutputCode(const std::string &Bitcode,
346 sys::Path &OutputCFile) {
347 sys::Path uniqueFile(Bitcode+".cbe.c");
348 std::string ErrMsg;
349 if (uniqueFile.makeUnique(true, &ErrMsg)) {
350 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
351 exit(1);
352 }
353 OutputCFile = uniqueFile;
354 std::vector<const char *> LLCArgs;
355 LLCArgs.push_back (LLCPath.c_str());
356
357 // Add any extra LLC args.
358 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
359 LLCArgs.push_back(ToolArgs[i].c_str());
360
361 LLCArgs.push_back ("-o");
362 LLCArgs.push_back (OutputCFile.c_str()); // Output to the C file
363 LLCArgs.push_back ("-march=c"); // Output C language
364 LLCArgs.push_back ("-f"); // Overwrite as necessary...
365 LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
366 LLCArgs.push_back (0);
367
368 std::cout << "<cbe>" << std::flush;
369 DEBUG(std::cerr << "\nAbout to run:\t";
370 for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
371 std::cerr << " " << LLCArgs[i];
372 std::cerr << "\n";
373 );
374 if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(),
375 sys::Path()))
376 ProcessFailure(LLCPath, &LLCArgs[0]);
377 return GCC::CFile;
378}
379
380void CBE::compileProgram(const std::string &Bitcode) {
381 sys::Path OutputCFile;
382 OutputCode(Bitcode, OutputCFile);
383 OutputCFile.eraseFromDisk();
384}
385
386int CBE::ExecuteProgram(const std::string &Bitcode,
387 const std::vector<std::string> &Args,
388 const std::string &InputFile,
389 const std::string &OutputFile,
390 const std::vector<std::string> &ArgsForGCC,
391 const std::vector<std::string> &SharedLibs,
392 unsigned Timeout,
393 unsigned MemoryLimit) {
394 sys::Path OutputCFile;
395 OutputCode(Bitcode, OutputCFile);
396
397 FileRemover CFileRemove(OutputCFile);
398
399 std::vector<std::string> GCCArgs(ArgsForGCC);
400 GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end());
401 return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile,
402 InputFile, OutputFile, GCCArgs,
403 Timeout, MemoryLimit);
404}
405
406/// createCBE - Try to find the 'llc' executable
407///
408CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath,
409 std::string &Message,
410 const std::vector<std::string> *Args) {
411 sys::Path LLCPath = FindExecutable("llc", ProgramPath);
412 if (LLCPath.isEmpty()) {
413 Message =
414 "Cannot find `llc' in executable directory or PATH!\n";
415 return 0;
416 }
417
418 Message = "Found llc: " + LLCPath.toString() + "\n";
419 GCC *gcc = GCC::create(ProgramPath, Message);
420 if (!gcc) {
421 std::cerr << Message << "\n";
422 exit(1);
423 }
424 return new CBE(LLCPath, gcc, Args);
425}
426
427//===---------------------------------------------------------------------===//
428// GCC abstraction
429//
430int GCC::ExecuteProgram(const std::string &ProgramFile,
431 const std::vector<std::string> &Args,
432 FileType fileType,
433 const std::string &InputFile,
434 const std::string &OutputFile,
435 const std::vector<std::string> &ArgsForGCC,
436 unsigned Timeout,
437 unsigned MemoryLimit) {
438 std::vector<const char*> GCCArgs;
439
440 GCCArgs.push_back(GCCPath.c_str());
441
442 // Specify -x explicitly in case the extension is wonky
443 GCCArgs.push_back("-x");
444 if (fileType == CFile) {
445 GCCArgs.push_back("c");
446 GCCArgs.push_back("-fno-strict-aliasing");
447 } else {
448 GCCArgs.push_back("assembler");
449#ifdef __APPLE__
450 GCCArgs.push_back("-force_cpusubtype_ALL");
451#endif
452 }
453 GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename...
454 GCCArgs.push_back("-x");
455 GCCArgs.push_back("none");
456 GCCArgs.push_back("-o");
457 sys::Path OutputBinary (ProgramFile+".gcc.exe");
458 std::string ErrMsg;
459 if (OutputBinary.makeUnique(true, &ErrMsg)) {
460 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
461 exit(1);
462 }
463 GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
464
465 // Add any arguments intended for GCC. We locate them here because this is
466 // most likely -L and -l options that need to come before other libraries but
467 // after the source. Other options won't be sensitive to placement on the
468 // command line, so this should be safe.
469 for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
470 GCCArgs.push_back(ArgsForGCC[i].c_str());
471
472 GCCArgs.push_back("-lm"); // Hard-code the math library...
473 GCCArgs.push_back("-O2"); // Optimize the program a bit...
474#if defined (HAVE_LINK_R)
475 GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files
476#endif
477#ifdef __sparc__
478 GCCArgs.push_back("-mcpu=v9");
479#endif
480 GCCArgs.push_back(0); // NULL terminator
481
482 std::cout << "<gcc>" << std::flush;
483 DEBUG(std::cerr << "\nAbout to run:\t";
484 for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
485 std::cerr << " " << GCCArgs[i];
486 std::cerr << "\n";
487 );
488 if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
489 sys::Path())) {
490 ProcessFailure(GCCPath, &GCCArgs[0]);
491 exit(1);
492 }
493
494 std::vector<const char*> ProgramArgs;
495
496 if (RSHPath.isEmpty())
497 ProgramArgs.push_back(OutputBinary.c_str());
498 else {
499 ProgramArgs.push_back(RSHPath.c_str());
500 ProgramArgs.push_back(RSHHost.c_str());
501 ProgramArgs.push_back("-l");
502 ProgramArgs.push_back(RSHUser.c_str());
503
504 char* env_pwd = getenv("PWD");
505 std::string Exec = "cd ";
506 Exec += env_pwd;
507 Exec += "; ./";
508 Exec += OutputBinary.c_str();
509 ProgramArgs.push_back(Exec.c_str());
510 }
511
512 // Add optional parameters to the running program from Argv
513 for (unsigned i=0, e = Args.size(); i != e; ++i)
514 ProgramArgs.push_back(Args[i].c_str());
515 ProgramArgs.push_back(0); // NULL terminator
516
517 // Now that we have a binary, run it!
518 std::cout << "<program>" << std::flush;
519 DEBUG(std::cerr << "\nAbout to run:\t";
520 for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i)
521 std::cerr << " " << ProgramArgs[i];
522 std::cerr << "\n";
523 );
524
525 FileRemover OutputBinaryRemover(OutputBinary);
526
527 if (RSHPath.isEmpty())
528 return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
529 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
530 Timeout, MemoryLimit);
531 else
532 return RunProgramWithTimeout(sys::Path(RSHPath), &ProgramArgs[0],
533 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
534 Timeout, MemoryLimit);
535}
536
537int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
538 std::string &OutputFile,
539 const std::vector<std::string> &ArgsForGCC) {
540 sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT);
541 std::string ErrMsg;
542 if (uniqueFilename.makeUnique(true, &ErrMsg)) {
543 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
544 exit(1);
545 }
546 OutputFile = uniqueFilename.toString();
547
548 std::vector<const char*> GCCArgs;
549
550 GCCArgs.push_back(GCCPath.c_str());
551
552
553 // Compile the C/asm file into a shared object
554 GCCArgs.push_back("-x");
555 GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
556 GCCArgs.push_back("-fno-strict-aliasing");
557 GCCArgs.push_back(InputFile.c_str()); // Specify the input filename.
558 GCCArgs.push_back("-x");
559 GCCArgs.push_back("none");
560#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
561 GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
562#elif defined(__APPLE__)
563 // link all source files into a single module in data segment, rather than
564 // generating blocks. dynamic_lookup requires that you set
565 // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for
566 // bugpoint to just pass that in the environment of GCC.
567 GCCArgs.push_back("-single_module");
568 GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC
569 GCCArgs.push_back("-undefined");
570 GCCArgs.push_back("dynamic_lookup");
571#else
572 GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others
573#endif
574
575#if defined(__ia64__) || defined(__alpha__)
576 GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
577#endif
578#ifdef __sparc__
579 GCCArgs.push_back("-mcpu=v9");
580#endif
581 GCCArgs.push_back("-o");
582 GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
583 GCCArgs.push_back("-O2"); // Optimize the program a bit.
584
585
586
587 // Add any arguments intended for GCC. We locate them here because this is
588 // most likely -L and -l options that need to come before other libraries but
589 // after the source. Other options won't be sensitive to placement on the
590 // command line, so this should be safe.
591 for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
592 GCCArgs.push_back(ArgsForGCC[i].c_str());
593 GCCArgs.push_back(0); // NULL terminator
594
595
596
597 std::cout << "<gcc>" << std::flush;
598 DEBUG(std::cerr << "\nAbout to run:\t";
599 for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
600 std::cerr << " " << GCCArgs[i];
601 std::cerr << "\n";
602 );
603 if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
604 sys::Path())) {
605 ProcessFailure(GCCPath, &GCCArgs[0]);
606 return 1;
607 }
608 return 0;
609}
610
611/// create - Try to find the `gcc' executable
612///
613GCC *GCC::create(const std::string &ProgramPath, std::string &Message) {
614 sys::Path GCCPath = FindExecutable("gcc", ProgramPath);
615 if (GCCPath.isEmpty()) {
616 Message = "Cannot find `gcc' in executable directory or PATH!\n";
617 return 0;
618 }
619
620 sys::Path RSHPath;
621 if (!RSHHost.empty())
622 RSHPath = FindExecutable("rsh", ProgramPath);
623
624 Message = "Found gcc: " + GCCPath.toString() + "\n";
625 return new GCC(GCCPath, RSHPath);
626}