driver.cpp revision a1e2fd9b580ae583b91d3288d59c00ca9f6a56b8
1//===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===// 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// This is the entry point to the clang driver; it is a thin wrapper 11// for functionality in the Driver clang library. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/Driver/Compilation.h" 16#include "clang/Driver/Driver.h" 17#include "clang/Driver/Option.h" 18#include "clang/Driver/Options.h" 19 20#include "llvm/ADT/SmallString.h" 21#include "llvm/ADT/OwningPtr.h" 22#include "llvm/Config/config.h" 23#include "llvm/Support/ManagedStatic.h" 24#include "llvm/Support/PrettyStackTrace.h" 25#include "llvm/Support/raw_ostream.h" 26#include "llvm/System/Host.h" 27#include "llvm/System/Path.h" 28#include "llvm/System/Signals.h" 29using namespace clang; 30using namespace clang::driver; 31 32class DriverDiagnosticPrinter : public DiagnosticClient { 33 std::string ProgName; 34 llvm::raw_ostream &OS; 35 36public: 37 DriverDiagnosticPrinter(const std::string _ProgName, 38 llvm::raw_ostream &_OS) 39 : ProgName(_ProgName), 40 OS(_OS) {} 41 42 virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, 43 const DiagnosticInfo &Info); 44}; 45 46void DriverDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, 47 const DiagnosticInfo &Info) { 48 OS << ProgName << ": "; 49 50 switch (Level) { 51 case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type"); 52 case Diagnostic::Note: OS << "note: "; break; 53 case Diagnostic::Warning: OS << "warning: "; break; 54 case Diagnostic::Error: OS << "error: "; break; 55 case Diagnostic::Fatal: OS << "fatal error: "; break; 56 } 57 58 llvm::SmallString<100> OutStr; 59 Info.FormatDiagnostic(OutStr); 60 OS.write(OutStr.begin(), OutStr.size()); 61 OS << '\n'; 62} 63 64llvm::sys::Path GetExecutablePath(const char *Argv0) { 65 // This just needs to be some symbol in the binary; C++ doesn't 66 // allow taking the address of ::main however. 67 void *P = (void*) (intptr_t) GetExecutablePath; 68 return llvm::sys::Path::GetMainExecutable(Argv0, P); 69} 70 71int main(int argc, const char **argv) { 72 llvm::sys::PrintStackTraceOnErrorSignal(); 73 llvm::PrettyStackTraceProgram X(argc, argv); 74 75 llvm::sys::Path Path = GetExecutablePath(argv[0]); 76 llvm::OwningPtr<DiagnosticClient> 77 DiagClient(new DriverDiagnosticPrinter(Path.getBasename(), llvm::errs())); 78 79 Diagnostic Diags(DiagClient.get()); 80 81 llvm::OwningPtr<Driver> 82 TheDriver(new Driver(Path.getBasename().c_str(), Path.getDirname().c_str(), 83 llvm::sys::getHostTriple().c_str(), 84 "a.out", Diags)); 85 86 llvm::OwningPtr<Compilation> C; 87 88 // Handle CCC_ADD_ARGS, a comma separated list of extra arguments. 89 std::set<std::string> SavedStrings; 90 if (const char *Cur = ::getenv("CCC_ADD_ARGS")) { 91 std::vector<const char*> StringPointers; 92 93 // FIXME: Driver shouldn't take extra initial argument. 94 StringPointers.push_back(argv[0]); 95 96 for (;;) { 97 const char *Next = strchr(Cur, ','); 98 99 if (Next) { 100 const char *P = 101 SavedStrings.insert(std::string(Cur, Next)).first->c_str(); 102 StringPointers.push_back(P); 103 Cur = Next + 1; 104 } else { 105 if (*Cur != '\0') { 106 const char *P = 107 SavedStrings.insert(std::string(Cur)).first->c_str(); 108 StringPointers.push_back(P); 109 } 110 break; 111 } 112 } 113 114 StringPointers.insert(StringPointers.end(), argv + 1, argv + argc); 115 116 C.reset(TheDriver->BuildCompilation(StringPointers.size(), 117 &StringPointers[0])); 118 } else 119 C.reset(TheDriver->BuildCompilation(argc, argv)); 120 121 int Res = 0; 122 if (C.get()) 123 Res = C->Execute(); 124 125 llvm::llvm_shutdown(); 126 127 return Res; 128} 129 130