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