1 //===--- CompilationDatabase.cpp - ----------------------------------------===// 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 file contains implementations of the CompilationDatabase base class 11 // and the FixedCompilationDatabase. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/Tooling/CompilationDatabase.h" 16 #include "clang/Tooling/CompilationDatabasePluginRegistry.h" 17 #include "clang/Tooling/Tooling.h" 18 #include "llvm/ADT/SmallString.h" 19 #include "llvm/Support/Path.h" 20 #include "llvm/Support/system_error.h" 21 #include <sstream> 22 23 namespace clang { 24 namespace tooling { 25 26 CompilationDatabase::~CompilationDatabase() {} 27 28 CompilationDatabase * 29 CompilationDatabase::loadFromDirectory(StringRef BuildDirectory, 30 std::string &ErrorMessage) { 31 std::stringstream ErrorStream; 32 for (CompilationDatabasePluginRegistry::iterator 33 It = CompilationDatabasePluginRegistry::begin(), 34 Ie = CompilationDatabasePluginRegistry::end(); 35 It != Ie; ++It) { 36 std::string DatabaseErrorMessage; 37 OwningPtr<CompilationDatabasePlugin> Plugin(It->instantiate()); 38 if (CompilationDatabase *DB = 39 Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage)) 40 return DB; 41 else 42 ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n"; 43 } 44 ErrorMessage = ErrorStream.str(); 45 return NULL; 46 } 47 48 static CompilationDatabase * 49 findCompilationDatabaseFromDirectory(StringRef Directory, 50 std::string &ErrorMessage) { 51 std::stringstream ErrorStream; 52 bool HasErrorMessage = false; 53 while (!Directory.empty()) { 54 std::string LoadErrorMessage; 55 56 if (CompilationDatabase *DB = 57 CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage)) 58 return DB; 59 60 if (!HasErrorMessage) { 61 ErrorStream << "No compilation database found in " << Directory.str() 62 << " or any parent directory\n" << LoadErrorMessage; 63 HasErrorMessage = true; 64 } 65 66 Directory = llvm::sys::path::parent_path(Directory); 67 } 68 ErrorMessage = ErrorStream.str(); 69 return NULL; 70 } 71 72 CompilationDatabase * 73 CompilationDatabase::autoDetectFromSource(StringRef SourceFile, 74 std::string &ErrorMessage) { 75 SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile)); 76 StringRef Directory = llvm::sys::path::parent_path(AbsolutePath); 77 78 CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory, 79 ErrorMessage); 80 81 if (!DB) 82 ErrorMessage = ("Could not auto-detect compilation database for file \"" + 83 SourceFile + "\"\n" + ErrorMessage).str(); 84 return DB; 85 } 86 87 CompilationDatabase * 88 CompilationDatabase::autoDetectFromDirectory(StringRef SourceDir, 89 std::string &ErrorMessage) { 90 SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir)); 91 92 CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath, 93 ErrorMessage); 94 95 if (!DB) 96 ErrorMessage = ("Could not auto-detect compilation database from directory \"" + 97 SourceDir + "\"\n" + ErrorMessage).str(); 98 return DB; 99 } 100 101 CompilationDatabasePlugin::~CompilationDatabasePlugin() {} 102 103 FixedCompilationDatabase * 104 FixedCompilationDatabase::loadFromCommandLine(int &Argc, 105 const char **Argv, 106 Twine Directory) { 107 const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--")); 108 if (DoubleDash == Argv + Argc) 109 return NULL; 110 std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc); 111 Argc = DoubleDash - Argv; 112 return new FixedCompilationDatabase(Directory, CommandLine); 113 } 114 115 FixedCompilationDatabase:: 116 FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) { 117 std::vector<std::string> ToolCommandLine(1, "clang-tool"); 118 ToolCommandLine.insert(ToolCommandLine.end(), 119 CommandLine.begin(), CommandLine.end()); 120 CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine)); 121 } 122 123 std::vector<CompileCommand> 124 FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const { 125 std::vector<CompileCommand> Result(CompileCommands); 126 Result[0].CommandLine.push_back(FilePath); 127 return Result; 128 } 129 130 std::vector<std::string> 131 FixedCompilationDatabase::getAllFiles() const { 132 return std::vector<std::string>(); 133 } 134 135 std::vector<CompileCommand> 136 FixedCompilationDatabase::getAllCompileCommands() const { 137 return std::vector<CompileCommand>(); 138 } 139 140 // This anchor is used to force the linker to link in the generated object file 141 // and thus register the JSONCompilationDatabasePlugin. 142 extern volatile int JSONAnchorSource; 143 static int JSONAnchorDest = JSONAnchorSource; 144 145 } // end namespace tooling 146 } // end namespace clang 147