CompilationDatabase.cpp revision 245431
1234287Sdim//===--- CompilationDatabase.cpp - ----------------------------------------===// 2234287Sdim// 3234287Sdim// The LLVM Compiler Infrastructure 4234287Sdim// 5234287Sdim// This file is distributed under the University of Illinois Open Source 6234287Sdim// License. See LICENSE.TXT for details. 7234287Sdim// 8234287Sdim//===----------------------------------------------------------------------===// 9234287Sdim// 10245431Sdim// This file contains implementations of the CompilationDatabase base class 11245431Sdim// and the FixedCompilationDatabase. 12234287Sdim// 13234287Sdim//===----------------------------------------------------------------------===// 14234287Sdim 15245431Sdim#include <sstream> 16234287Sdim#include "clang/Tooling/CompilationDatabase.h" 17245431Sdim#include "clang/Tooling/CompilationDatabasePluginRegistry.h" 18245431Sdim#include "clang/Tooling/Tooling.h" 19234287Sdim#include "llvm/ADT/SmallString.h" 20234287Sdim#include "llvm/Support/Path.h" 21234287Sdim#include "llvm/Support/system_error.h" 22234287Sdim 23234287Sdimnamespace clang { 24234287Sdimnamespace tooling { 25234287Sdim 26245431SdimCompilationDatabase::~CompilationDatabase() {} 27234287Sdim 28245431SdimCompilationDatabase * 29245431SdimCompilationDatabase::loadFromDirectory(StringRef BuildDirectory, 30245431Sdim std::string &ErrorMessage) { 31245431Sdim std::stringstream ErrorStream; 32245431Sdim for (CompilationDatabasePluginRegistry::iterator 33245431Sdim It = CompilationDatabasePluginRegistry::begin(), 34245431Sdim Ie = CompilationDatabasePluginRegistry::end(); 35245431Sdim It != Ie; ++It) { 36245431Sdim std::string DatabaseErrorMessage; 37245431Sdim OwningPtr<CompilationDatabasePlugin> Plugin(It->instantiate()); 38245431Sdim if (CompilationDatabase *DB = 39245431Sdim Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage)) 40245431Sdim return DB; 41245431Sdim else 42245431Sdim ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n"; 43234287Sdim } 44245431Sdim ErrorMessage = ErrorStream.str(); 45245431Sdim return NULL; 46245431Sdim} 47234287Sdim 48245431Sdimstatic CompilationDatabase * 49245431SdimfindCompilationDatabaseFromDirectory(StringRef Directory, 50245431Sdim std::string &ErrorMessage) { 51245431Sdim std::stringstream ErrorStream; 52245431Sdim bool HasErrorMessage = false; 53245431Sdim while (!Directory.empty()) { 54245431Sdim std::string LoadErrorMessage; 55234287Sdim 56245431Sdim if (CompilationDatabase *DB = 57245431Sdim CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage)) 58245431Sdim return DB; 59234287Sdim 60245431Sdim if (!HasErrorMessage) { 61245431Sdim ErrorStream << "No compilation database found in " << Directory.str() 62245431Sdim << " or any parent directory\n" << LoadErrorMessage; 63245431Sdim HasErrorMessage = true; 64234287Sdim } 65234287Sdim 66245431Sdim Directory = llvm::sys::path::parent_path(Directory); 67234287Sdim } 68245431Sdim ErrorMessage = ErrorStream.str(); 69245431Sdim return NULL; 70245431Sdim} 71234287Sdim 72245431SdimCompilationDatabase * 73245431SdimCompilationDatabase::autoDetectFromSource(StringRef SourceFile, 74245431Sdim std::string &ErrorMessage) { 75245431Sdim llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile)); 76245431Sdim StringRef Directory = llvm::sys::path::parent_path(AbsolutePath); 77234287Sdim 78245431Sdim CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory, 79245431Sdim ErrorMessage); 80234287Sdim 81245431Sdim if (!DB) 82245431Sdim ErrorMessage = ("Could not auto-detect compilation database for file \"" + 83245431Sdim SourceFile + "\"\n" + ErrorMessage).str(); 84245431Sdim return DB; 85234287Sdim} 86234287Sdim 87245431SdimCompilationDatabase * 88245431SdimCompilationDatabase::autoDetectFromDirectory(StringRef SourceDir, 89245431Sdim std::string &ErrorMessage) { 90245431Sdim llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir)); 91234287Sdim 92245431Sdim CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath, 93245431Sdim ErrorMessage); 94234287Sdim 95245431Sdim if (!DB) 96245431Sdim ErrorMessage = ("Could not auto-detect compilation database from directory \"" + 97245431Sdim SourceDir + "\"\n" + ErrorMessage).str(); 98245431Sdim return DB; 99234287Sdim} 100234287Sdim 101245431SdimCompilationDatabasePlugin::~CompilationDatabasePlugin() {} 102245431Sdim 103235633SdimFixedCompilationDatabase * 104235633SdimFixedCompilationDatabase::loadFromCommandLine(int &Argc, 105235633Sdim const char **Argv, 106235633Sdim Twine Directory) { 107235633Sdim const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--")); 108235633Sdim if (DoubleDash == Argv + Argc) 109235633Sdim return NULL; 110235633Sdim std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc); 111235633Sdim Argc = DoubleDash - Argv; 112235633Sdim return new FixedCompilationDatabase(Directory, CommandLine); 113235633Sdim} 114235633Sdim 115235633SdimFixedCompilationDatabase:: 116235633SdimFixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) { 117235633Sdim std::vector<std::string> ToolCommandLine(1, "clang-tool"); 118235633Sdim ToolCommandLine.insert(ToolCommandLine.end(), 119235633Sdim CommandLine.begin(), CommandLine.end()); 120235633Sdim CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine)); 121235633Sdim} 122235633Sdim 123235633Sdimstd::vector<CompileCommand> 124235633SdimFixedCompilationDatabase::getCompileCommands(StringRef FilePath) const { 125235633Sdim std::vector<CompileCommand> Result(CompileCommands); 126235633Sdim Result[0].CommandLine.push_back(FilePath); 127235633Sdim return Result; 128235633Sdim} 129235633Sdim 130245431Sdimstd::vector<std::string> 131245431SdimFixedCompilationDatabase::getAllFiles() const { 132245431Sdim return std::vector<std::string>(); 133234287Sdim} 134234287Sdim 135245431Sdim// This anchor is used to force the linker to link in the generated object file 136245431Sdim// and thus register the JSONCompilationDatabasePlugin. 137245431Sdimextern volatile int JSONAnchorSource; 138245431Sdimstatic int JSONAnchorDest = JSONAnchorSource; 139234287Sdim 140234287Sdim} // end namespace tooling 141234287Sdim} // end namespace clang 142