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