147c245a5SManuel Klimek //===--- CompilationDatabase.cpp - ----------------------------------------===// 247c245a5SManuel Klimek // 347c245a5SManuel Klimek // The LLVM Compiler Infrastructure 447c245a5SManuel Klimek // 547c245a5SManuel Klimek // This file is distributed under the University of Illinois Open Source 647c245a5SManuel Klimek // License. See LICENSE.TXT for details. 747c245a5SManuel Klimek // 847c245a5SManuel Klimek //===----------------------------------------------------------------------===// 947c245a5SManuel Klimek // 106ed1f85cSDaniel Jasper // This file contains implementations of the CompilationDatabase base class 116ed1f85cSDaniel Jasper // and the FixedCompilationDatabase. 1247c245a5SManuel Klimek // 1347c245a5SManuel Klimek //===----------------------------------------------------------------------===// 1447c245a5SManuel Klimek 1547c245a5SManuel Klimek #include "clang/Tooling/CompilationDatabase.h" 166ed1f85cSDaniel Jasper #include "clang/Tooling/CompilationDatabasePluginRegistry.h" 1765fd0e1fSManuel Klimek #include "clang/Tooling/Tooling.h" 1847c245a5SManuel Klimek #include "llvm/ADT/SmallString.h" 1947c245a5SManuel Klimek #include "llvm/Support/Path.h" 2047c245a5SManuel Klimek #include "llvm/Support/system_error.h" 21*3a02247dSChandler Carruth #include <sstream> 2247c245a5SManuel Klimek 2347c245a5SManuel Klimek namespace clang { 2447c245a5SManuel Klimek namespace tooling { 2547c245a5SManuel Klimek 2647c245a5SManuel Klimek CompilationDatabase::~CompilationDatabase() {} 2747c245a5SManuel Klimek 2847c245a5SManuel Klimek CompilationDatabase * 2947c245a5SManuel Klimek CompilationDatabase::loadFromDirectory(StringRef BuildDirectory, 3047c245a5SManuel Klimek std::string &ErrorMessage) { 316ed1f85cSDaniel Jasper std::stringstream ErrorStream; 326ed1f85cSDaniel Jasper for (CompilationDatabasePluginRegistry::iterator 336ed1f85cSDaniel Jasper It = CompilationDatabasePluginRegistry::begin(), 346ed1f85cSDaniel Jasper Ie = CompilationDatabasePluginRegistry::end(); 356ed1f85cSDaniel Jasper It != Ie; ++It) { 366ed1f85cSDaniel Jasper std::string DatabaseErrorMessage; 376ed1f85cSDaniel Jasper OwningPtr<CompilationDatabasePlugin> Plugin(It->instantiate()); 386ed1f85cSDaniel Jasper if (CompilationDatabase *DB = 396ed1f85cSDaniel Jasper Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage)) 406ed1f85cSDaniel Jasper return DB; 416ed1f85cSDaniel Jasper else 426ed1f85cSDaniel Jasper ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n"; 4347c245a5SManuel Klimek } 446ed1f85cSDaniel Jasper ErrorMessage = ErrorStream.str(); 456ed1f85cSDaniel Jasper return NULL; 4647c245a5SManuel Klimek } 4747c245a5SManuel Klimek 48617f5269SArnaud A. de Grandmaison static CompilationDatabase * 496ed1f85cSDaniel Jasper findCompilationDatabaseFromDirectory(StringRef Directory, 506ed1f85cSDaniel Jasper std::string &ErrorMessage) { 516ed1f85cSDaniel Jasper std::stringstream ErrorStream; 5274351ff4SDaniel Jasper bool HasErrorMessage = false; 53617f5269SArnaud A. de Grandmaison while (!Directory.empty()) { 54617f5269SArnaud A. de Grandmaison std::string LoadErrorMessage; 55617f5269SArnaud A. de Grandmaison 56617f5269SArnaud A. de Grandmaison if (CompilationDatabase *DB = 57617f5269SArnaud A. de Grandmaison CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage)) 58617f5269SArnaud A. de Grandmaison return DB; 5974351ff4SDaniel Jasper 6074351ff4SDaniel Jasper if (!HasErrorMessage) { 616ed1f85cSDaniel Jasper ErrorStream << "No compilation database found in " << Directory.str() 6274351ff4SDaniel Jasper << " or any parent directory\n" << LoadErrorMessage; 6374351ff4SDaniel Jasper HasErrorMessage = true; 6474351ff4SDaniel Jasper } 65617f5269SArnaud A. de Grandmaison 66617f5269SArnaud A. de Grandmaison Directory = llvm::sys::path::parent_path(Directory); 67617f5269SArnaud A. de Grandmaison } 686ed1f85cSDaniel Jasper ErrorMessage = ErrorStream.str(); 69617f5269SArnaud A. de Grandmaison return NULL; 70617f5269SArnaud A. de Grandmaison } 71617f5269SArnaud A. de Grandmaison 7265fd0e1fSManuel Klimek CompilationDatabase * 7365fd0e1fSManuel Klimek CompilationDatabase::autoDetectFromSource(StringRef SourceFile, 7465fd0e1fSManuel Klimek std::string &ErrorMessage) { 7565fd0e1fSManuel Klimek llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile)); 7665fd0e1fSManuel Klimek StringRef Directory = llvm::sys::path::parent_path(AbsolutePath); 77617f5269SArnaud A. de Grandmaison 786ed1f85cSDaniel Jasper CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory, 796ed1f85cSDaniel Jasper ErrorMessage); 80617f5269SArnaud A. de Grandmaison 81617f5269SArnaud A. de Grandmaison if (!DB) 8265fd0e1fSManuel Klimek ErrorMessage = ("Could not auto-detect compilation database for file \"" + 836ed1f85cSDaniel Jasper SourceFile + "\"\n" + ErrorMessage).str(); 84617f5269SArnaud A. de Grandmaison return DB; 85617f5269SArnaud A. de Grandmaison } 86617f5269SArnaud A. de Grandmaison 87617f5269SArnaud A. de Grandmaison CompilationDatabase * 88617f5269SArnaud A. de Grandmaison CompilationDatabase::autoDetectFromDirectory(StringRef SourceDir, 89617f5269SArnaud A. de Grandmaison std::string &ErrorMessage) { 90617f5269SArnaud A. de Grandmaison llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir)); 91617f5269SArnaud A. de Grandmaison 926ed1f85cSDaniel Jasper CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath, 936ed1f85cSDaniel Jasper ErrorMessage); 94617f5269SArnaud A. de Grandmaison 95617f5269SArnaud A. de Grandmaison if (!DB) 96617f5269SArnaud A. de Grandmaison ErrorMessage = ("Could not auto-detect compilation database from directory \"" + 976ed1f85cSDaniel Jasper SourceDir + "\"\n" + ErrorMessage).str(); 98617f5269SArnaud A. de Grandmaison return DB; 9965fd0e1fSManuel Klimek } 10065fd0e1fSManuel Klimek 1016ed1f85cSDaniel Jasper CompilationDatabasePlugin::~CompilationDatabasePlugin() {} 1026ed1f85cSDaniel Jasper 103ff26efceSManuel Klimek FixedCompilationDatabase * 104ff26efceSManuel Klimek FixedCompilationDatabase::loadFromCommandLine(int &Argc, 105ff26efceSManuel Klimek const char **Argv, 106ff26efceSManuel Klimek Twine Directory) { 107ff26efceSManuel Klimek const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--")); 108ff26efceSManuel Klimek if (DoubleDash == Argv + Argc) 109ff26efceSManuel Klimek return NULL; 110ff26efceSManuel Klimek std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc); 111ff26efceSManuel Klimek Argc = DoubleDash - Argv; 112ff26efceSManuel Klimek return new FixedCompilationDatabase(Directory, CommandLine); 113ff26efceSManuel Klimek } 114ff26efceSManuel Klimek 115ff26efceSManuel Klimek FixedCompilationDatabase:: 116ff26efceSManuel Klimek FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) { 117ff26efceSManuel Klimek std::vector<std::string> ToolCommandLine(1, "clang-tool"); 118ff26efceSManuel Klimek ToolCommandLine.insert(ToolCommandLine.end(), 119ff26efceSManuel Klimek CommandLine.begin(), CommandLine.end()); 120ff26efceSManuel Klimek CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine)); 121ff26efceSManuel Klimek } 122ff26efceSManuel Klimek 123ff26efceSManuel Klimek std::vector<CompileCommand> 124ff26efceSManuel Klimek FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const { 125ff26efceSManuel Klimek std::vector<CompileCommand> Result(CompileCommands); 126ff26efceSManuel Klimek Result[0].CommandLine.push_back(FilePath); 127ff26efceSManuel Klimek return Result; 128ff26efceSManuel Klimek } 129ff26efceSManuel Klimek 13060b80161SManuel Klimek std::vector<std::string> 13160b80161SManuel Klimek FixedCompilationDatabase::getAllFiles() const { 13260b80161SManuel Klimek return std::vector<std::string>(); 13360b80161SManuel Klimek } 13460b80161SManuel Klimek 135251ad5e0SArgyrios Kyrtzidis std::vector<CompileCommand> 136251ad5e0SArgyrios Kyrtzidis FixedCompilationDatabase::getAllCompileCommands() const { 137251ad5e0SArgyrios Kyrtzidis return std::vector<CompileCommand>(); 138251ad5e0SArgyrios Kyrtzidis } 139251ad5e0SArgyrios Kyrtzidis 1406ed1f85cSDaniel Jasper // This anchor is used to force the linker to link in the generated object file 1416ed1f85cSDaniel Jasper // and thus register the JSONCompilationDatabasePlugin. 1426ed1f85cSDaniel Jasper extern volatile int JSONAnchorSource; 1436ed1f85cSDaniel Jasper static int JSONAnchorDest = JSONAnchorSource; 14447c245a5SManuel Klimek 14547c245a5SManuel Klimek } // end namespace tooling 14647c245a5SManuel Klimek } // end namespace clang 147