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 <sstream> 16 #include "clang/Tooling/CompilationDatabase.h" 17 #include "clang/Tooling/CompilationDatabasePluginRegistry.h" 18 #include "clang/Tooling/Tooling.h" 19 #include "llvm/ADT/SmallString.h" 20 #include "llvm/Support/Path.h" 21 #include "llvm/Support/system_error.h" 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 while (!Directory.empty()) { 53 std::string LoadErrorMessage; 54 55 if (CompilationDatabase *DB = 56 CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage)) 57 return DB; 58 ErrorStream << "No compilation database found in " << Directory.str() 59 << "\n" << LoadErrorMessage; 60 61 Directory = llvm::sys::path::parent_path(Directory); 62 } 63 ErrorMessage = ErrorStream.str(); 64 return NULL; 65 } 66 67 CompilationDatabase * 68 CompilationDatabase::autoDetectFromSource(StringRef SourceFile, 69 std::string &ErrorMessage) { 70 llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile)); 71 StringRef Directory = llvm::sys::path::parent_path(AbsolutePath); 72 73 CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory, 74 ErrorMessage); 75 76 if (!DB) 77 ErrorMessage = ("Could not auto-detect compilation database for file \"" + 78 SourceFile + "\"\n" + ErrorMessage).str(); 79 return DB; 80 } 81 82 CompilationDatabase * 83 CompilationDatabase::autoDetectFromDirectory(StringRef SourceDir, 84 std::string &ErrorMessage) { 85 llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir)); 86 87 CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath, 88 ErrorMessage); 89 90 if (!DB) 91 ErrorMessage = ("Could not auto-detect compilation database from directory \"" + 92 SourceDir + "\"\n" + ErrorMessage).str(); 93 return DB; 94 } 95 96 CompilationDatabasePlugin::~CompilationDatabasePlugin() {} 97 98 FixedCompilationDatabase * 99 FixedCompilationDatabase::loadFromCommandLine(int &Argc, 100 const char **Argv, 101 Twine Directory) { 102 const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--")); 103 if (DoubleDash == Argv + Argc) 104 return NULL; 105 std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc); 106 Argc = DoubleDash - Argv; 107 return new FixedCompilationDatabase(Directory, CommandLine); 108 } 109 110 FixedCompilationDatabase:: 111 FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) { 112 std::vector<std::string> ToolCommandLine(1, "clang-tool"); 113 ToolCommandLine.insert(ToolCommandLine.end(), 114 CommandLine.begin(), CommandLine.end()); 115 CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine)); 116 } 117 118 std::vector<CompileCommand> 119 FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const { 120 std::vector<CompileCommand> Result(CompileCommands); 121 Result[0].CommandLine.push_back(FilePath); 122 return Result; 123 } 124 125 std::vector<std::string> 126 FixedCompilationDatabase::getAllFiles() const { 127 return std::vector<std::string>(); 128 } 129 130 // This anchor is used to force the linker to link in the generated object file 131 // and thus register the JSONCompilationDatabasePlugin. 132 extern volatile int JSONAnchorSource; 133 static int JSONAnchorDest = JSONAnchorSource; 134 135 } // end namespace tooling 136 } // end namespace clang 137