Home | History | Annotate | Download | only in Tooling
      1 //===--- CompilationDatabase.h - --------------------------------*- C++ -*-===//
      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 provides an interface and multiple implementations for
     11 //  CompilationDatabases.
     12 //
     13 //  While C++ refactoring and analysis tools are not compilers, and thus
     14 //  don't run as part of the build system, they need the exact information
     15 //  of a build in order to be able to correctly understand the C++ code of
     16 //  the project. This information is provided via the CompilationDatabase
     17 //  interface.
     18 //
     19 //  To create a CompilationDatabase from a build directory one can call
     20 //  CompilationDatabase::loadFromDirectory(), which deduces the correct
     21 //  compilation database from the root of the build tree.
     22 //
     23 //  See the concrete subclasses of CompilationDatabase for currently supported
     24 //  formats.
     25 //
     26 //===----------------------------------------------------------------------===//
     27 
     28 #ifndef LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H
     29 #define LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H
     30 
     31 #include "clang/Basic/LLVM.h"
     32 #include "llvm/ADT/ArrayRef.h"
     33 #include "llvm/ADT/OwningPtr.h"
     34 #include "llvm/ADT/StringMap.h"
     35 #include "llvm/ADT/StringRef.h"
     36 #include "llvm/ADT/Twine.h"
     37 #include "llvm/Support/MemoryBuffer.h"
     38 #include "llvm/Support/SourceMgr.h"
     39 #include "llvm/Support/YAMLParser.h"
     40 #include <string>
     41 #include <vector>
     42 
     43 namespace clang {
     44 namespace tooling {
     45 
     46 /// \brief Specifies the working directory and command of a compilation.
     47 struct CompileCommand {
     48   CompileCommand() {}
     49   CompileCommand(Twine Directory, ArrayRef<std::string> CommandLine)
     50     : Directory(Directory.str()), CommandLine(CommandLine) {}
     51 
     52   /// \brief The working directory the command was executed from.
     53   std::string Directory;
     54 
     55   /// \brief The command line that was executed.
     56   std::vector<std::string> CommandLine;
     57 };
     58 
     59 /// \brief Interface for compilation databases.
     60 ///
     61 /// A compilation database allows the user to retrieve all compile command lines
     62 /// that a specified file is compiled with in a project.
     63 /// The retrieved compile command lines can be used to run clang tools over
     64 /// a subset of the files in a project.
     65 class CompilationDatabase {
     66 public:
     67   virtual ~CompilationDatabase();
     68 
     69   /// \brief Loads a compilation database from a build directory.
     70   ///
     71   /// Looks at the specified 'BuildDirectory' and creates a compilation database
     72   /// that allows to query compile commands for source files in the
     73   /// corresponding source tree.
     74   ///
     75   /// Returns NULL and sets ErrorMessage if we were not able to build up a
     76   /// compilation database for the build directory.
     77   ///
     78   /// FIXME: Currently only supports JSON compilation databases, which
     79   /// are named 'compile_commands.json' in the given directory. Extend this
     80   /// for other build types (like ninja build files).
     81   static CompilationDatabase *loadFromDirectory(StringRef BuildDirectory,
     82                                                 std::string &ErrorMessage);
     83 
     84   /// \brief Returns all compile commands in which the specified file was
     85   /// compiled.
     86   ///
     87   /// This includes compile comamnds that span multiple source files.
     88   /// For example, consider a project with the following compilations:
     89   /// $ clang++ -o test a.cc b.cc t.cc
     90   /// $ clang++ -o production a.cc b.cc -DPRODUCTION
     91   /// A compilation database representing the project would return both command
     92   /// lines for a.cc and b.cc and only the first command line for t.cc.
     93   virtual std::vector<CompileCommand> getCompileCommands(
     94     StringRef FilePath) const = 0;
     95 };
     96 
     97 /// \brief A compilation database that returns a single compile command line.
     98 ///
     99 /// Useful when we want a tool to behave more like a compiler invocation.
    100 class FixedCompilationDatabase : public CompilationDatabase {
    101 public:
    102   /// \brief Creates a FixedCompilationDatabase from the arguments after "--".
    103   ///
    104   /// Parses the given command line for "--". If "--" is found, the rest of
    105   /// the arguments will make up the command line in the returned
    106   /// FixedCompilationDatabase.
    107   /// The arguments after "--" must not include positional parameters or the
    108   /// argv[0] of the tool. Those will be added by the FixedCompilationDatabase
    109   /// when a CompileCommand is requested. The argv[0] of the returned command
    110   /// line will be "clang-tool".
    111   ///
    112   /// Returns NULL in case "--" is not found.
    113   ///
    114   /// The argument list is meant to be compatible with normal llvm command line
    115   /// parsing in main methods.
    116   /// int main(int argc, char **argv) {
    117   ///   llvm::OwningPtr<FixedCompilationDatabase> Compilations(
    118   ///     FixedCompilationDatabase::loadFromCommandLine(argc, argv));
    119   ///   cl::ParseCommandLineOptions(argc, argv);
    120   ///   ...
    121   /// }
    122   ///
    123   /// \param Argc The number of command line arguments - will be changed to
    124   /// the number of arguments before "--", if "--" was found in the argument
    125   /// list.
    126   /// \param Argv Points to the command line arguments.
    127   /// \param Directory The base directory used in the FixedCompilationDatabase.
    128   static FixedCompilationDatabase *loadFromCommandLine(int &Argc,
    129                                                        const char **Argv,
    130                                                        Twine Directory = ".");
    131 
    132   /// \brief Constructs a compilation data base from a specified directory
    133   /// and command line.
    134   FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine);
    135 
    136   /// \brief Returns the given compile command.
    137   ///
    138   /// Will always return a vector with one entry that contains the directory
    139   /// and command line specified at construction with "clang-tool" as argv[0]
    140   /// and 'FilePath' as positional argument.
    141   virtual std::vector<CompileCommand> getCompileCommands(
    142     StringRef FilePath) const;
    143 
    144 private:
    145   /// This is built up to contain a single entry vector to be returned from
    146   /// getCompileCommands after adding the positional argument.
    147   std::vector<CompileCommand> CompileCommands;
    148 };
    149 
    150 /// \brief A JSON based compilation database.
    151 ///
    152 /// JSON compilation database files must contain a list of JSON objects which
    153 /// provide the command lines in the attributes 'directory', 'command' and
    154 /// 'file':
    155 /// [
    156 ///   { "directory": "<working directory of the compile>",
    157 ///     "command": "<compile command line>",
    158 ///     "file": "<path to source file>"
    159 ///   },
    160 ///   ...
    161 /// ]
    162 /// Each object entry defines one compile action. The specified file is
    163 /// considered to be the main source file for the translation unit.
    164 ///
    165 /// JSON compilation databases can for example be generated in CMake projects
    166 /// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS.
    167 class JSONCompilationDatabase : public CompilationDatabase {
    168 public:
    169   /// \brief Loads a JSON compilation database from the specified file.
    170   ///
    171   /// Returns NULL and sets ErrorMessage if the database could not be
    172   /// loaded from the given file.
    173   static JSONCompilationDatabase *loadFromFile(StringRef FilePath,
    174                                                std::string &ErrorMessage);
    175 
    176   /// \brief Loads a JSON compilation database from a data buffer.
    177   ///
    178   /// Returns NULL and sets ErrorMessage if the database could not be loaded.
    179   static JSONCompilationDatabase *loadFromBuffer(StringRef DatabaseString,
    180                                                  std::string &ErrorMessage);
    181 
    182   /// \brief Returns all compile comamnds in which the specified file was
    183   /// compiled.
    184   ///
    185   /// FIXME: Currently FilePath must be an absolute path inside the
    186   /// source directory which does not have symlinks resolved.
    187   virtual std::vector<CompileCommand> getCompileCommands(
    188     StringRef FilePath) const;
    189 
    190 private:
    191   /// \brief Constructs a JSON compilation database on a memory buffer.
    192   JSONCompilationDatabase(llvm::MemoryBuffer *Database)
    193     : Database(Database), YAMLStream(Database->getBuffer(), SM) {}
    194 
    195   /// \brief Parses the database file and creates the index.
    196   ///
    197   /// Returns whether parsing succeeded. Sets ErrorMessage if parsing
    198   /// failed.
    199   bool parse(std::string &ErrorMessage);
    200 
    201   // Tuple (directory, commandline) where 'commandline' pointing to the
    202   // corresponding nodes in the YAML stream.
    203   typedef std::pair<llvm::yaml::ScalarNode*,
    204                     llvm::yaml::ScalarNode*> CompileCommandRef;
    205 
    206   // Maps file paths to the compile command lines for that file.
    207   llvm::StringMap< std::vector<CompileCommandRef> > IndexByFile;
    208 
    209   llvm::OwningPtr<llvm::MemoryBuffer> Database;
    210   llvm::SourceMgr SM;
    211   llvm::yaml::Stream YAMLStream;
    212 };
    213 
    214 } // end namespace tooling
    215 } // end namespace clang
    216 
    217 #endif // LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H
    218 
    219