CompilationDatabase.cpp revision 7fd90b03a28df0626fdb44d05be9ddcdb2562686
1cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===--- CompilationDatabase.cpp - ----------------------------------------===// 2cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// 3cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// The LLVM Compiler Infrastructure 4cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// 5cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// This file is distributed under the University of Illinois Open Source 6cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// License. See LICENSE.TXT for details. 7cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// 8cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===----------------------------------------------------------------------===// 9cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// 107fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// This file contains implementations of the CompilationDatabase base class 117fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// and the FixedCompilationDatabase. 12cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// 13cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===----------------------------------------------------------------------===// 14cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 157fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper#include <sstream> 16cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "clang/Tooling/CompilationDatabase.h" 177fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper#include "clang/Tooling/CompilationDatabasePluginRegistry.h" 188fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek#include "clang/Tooling/Tooling.h" 19cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "llvm/ADT/SmallString.h" 20cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "llvm/Support/Path.h" 21cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "llvm/Support/system_error.h" 22cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 23cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimeknamespace clang { 24cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimeknamespace tooling { 25cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 26cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekCompilationDatabase::~CompilationDatabase() {} 27cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 28cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekCompilationDatabase * 29cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekCompilationDatabase::loadFromDirectory(StringRef BuildDirectory, 30cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek std::string &ErrorMessage) { 317fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper std::stringstream ErrorStream; 327fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper for (CompilationDatabasePluginRegistry::iterator 337fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper It = CompilationDatabasePluginRegistry::begin(), 347fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper Ie = CompilationDatabasePluginRegistry::end(); 357fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper It != Ie; ++It) { 367fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper std::string DatabaseErrorMessage; 377fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper OwningPtr<CompilationDatabasePlugin> Plugin(It->instantiate()); 387fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (CompilationDatabase *DB = 397fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage)) 407fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return DB; 417fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper else 427fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n"; 43cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek } 447fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = ErrorStream.str(); 457fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return NULL; 46cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} 47cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 484187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaisonstatic CompilationDatabase * 497fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperfindCompilationDatabaseFromDirectory(StringRef Directory, 507fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper std::string &ErrorMessage) { 517fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper std::stringstream ErrorStream; 528fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek while (!Directory.empty()) { 538fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek std::string LoadErrorMessage; 544187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison 554187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison if (CompilationDatabase *DB = 564187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage)) 578fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek return DB; 587fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorStream << "No compilation database found in " << Directory.str() 597fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper << "\n" << LoadErrorMessage; 604187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison 618fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek Directory = llvm::sys::path::parent_path(Directory); 628fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek } 637fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = ErrorStream.str(); 648fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek return NULL; 658fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek} 668fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek 674187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de GrandmaisonCompilationDatabase * 684187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de GrandmaisonCompilationDatabase::autoDetectFromSource(StringRef SourceFile, 694187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison std::string &ErrorMessage) { 704187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile)); 714187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison StringRef Directory = llvm::sys::path::parent_path(AbsolutePath); 724187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison 737fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory, 747fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage); 754187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison 764187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison if (!DB) 774187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison ErrorMessage = ("Could not auto-detect compilation database for file \"" + 787fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper SourceFile + "\"\n" + ErrorMessage).str(); 794187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison return DB; 804187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison} 814187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison 824187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de GrandmaisonCompilationDatabase * 834187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de GrandmaisonCompilationDatabase::autoDetectFromDirectory(StringRef SourceDir, 844187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison std::string &ErrorMessage) { 854187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir)); 864187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison 877fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath, 887fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage); 894187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison 904187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison if (!DB) 914187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison ErrorMessage = ("Could not auto-detect compilation database from directory \"" + 927fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper SourceDir + "\"\n" + ErrorMessage).str(); 934187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison return DB; 944187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison} 954187df5f7bdda66d2fbe64a3f2660ee3977f0d12Arnaud A. de Grandmaison 967fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperCompilationDatabasePlugin::~CompilationDatabasePlugin() {} 977fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper 9830318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase * 9930318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase::loadFromCommandLine(int &Argc, 10030318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek const char **Argv, 10130318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek Twine Directory) { 10230318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--")); 10330318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek if (DoubleDash == Argv + Argc) 10430318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek return NULL; 10530318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc); 10630318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek Argc = DoubleDash - Argv; 10730318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek return new FixedCompilationDatabase(Directory, CommandLine); 10830318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek} 10930318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek 11030318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase:: 11130318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) { 11230318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek std::vector<std::string> ToolCommandLine(1, "clang-tool"); 11330318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek ToolCommandLine.insert(ToolCommandLine.end(), 11430318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek CommandLine.begin(), CommandLine.end()); 11530318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine)); 11630318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek} 11730318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek 11830318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimekstd::vector<CompileCommand> 11930318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase::getCompileCommands(StringRef FilePath) const { 12030318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek std::vector<CompileCommand> Result(CompileCommands); 12130318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek Result[0].CommandLine.push_back(FilePath); 12230318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek return Result; 12330318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek} 12430318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek 125a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel Klimekstd::vector<std::string> 126a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel KlimekFixedCompilationDatabase::getAllFiles() const { 127a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel Klimek return std::vector<std::string>(); 128a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel Klimek} 129a3c70966babdd6c63623470fbba9bb4ec37de4a5Manuel Klimek 1307fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// This anchor is used to force the linker to link in the generated object file 1317fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// and thus register the JSONCompilationDatabasePlugin. 1327fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperextern volatile int JSONAnchorSource; 1337fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperstatic int JSONAnchorDest = JSONAnchorSource; 134cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 135cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} // end namespace tooling 136cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} // end namespace clang 137