1e5dd7070Spatrick //===- CompilationDatabase.h ------------------------------------*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9e5dd7070Spatrick // This file provides an interface and multiple implementations for 10e5dd7070Spatrick // CompilationDatabases. 11e5dd7070Spatrick // 12e5dd7070Spatrick // While C++ refactoring and analysis tools are not compilers, and thus 13e5dd7070Spatrick // don't run as part of the build system, they need the exact information 14e5dd7070Spatrick // of a build in order to be able to correctly understand the C++ code of 15e5dd7070Spatrick // the project. This information is provided via the CompilationDatabase 16e5dd7070Spatrick // interface. 17e5dd7070Spatrick // 18e5dd7070Spatrick // To create a CompilationDatabase from a build directory one can call 19e5dd7070Spatrick // CompilationDatabase::loadFromDirectory(), which deduces the correct 20e5dd7070Spatrick // compilation database from the root of the build tree. 21e5dd7070Spatrick // 22e5dd7070Spatrick // See the concrete subclasses of CompilationDatabase for currently supported 23e5dd7070Spatrick // formats. 24e5dd7070Spatrick // 25e5dd7070Spatrick //===----------------------------------------------------------------------===// 26e5dd7070Spatrick 27e5dd7070Spatrick #ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H 28e5dd7070Spatrick #define LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H 29e5dd7070Spatrick 30e5dd7070Spatrick #include "clang/Basic/LLVM.h" 31e5dd7070Spatrick #include "llvm/ADT/ArrayRef.h" 32e5dd7070Spatrick #include "llvm/ADT/StringRef.h" 33e5dd7070Spatrick #include "llvm/ADT/Twine.h" 34e5dd7070Spatrick #include "llvm/Support/VirtualFileSystem.h" 35e5dd7070Spatrick #include <memory> 36e5dd7070Spatrick #include <string> 37e5dd7070Spatrick #include <utility> 38e5dd7070Spatrick #include <vector> 39e5dd7070Spatrick 40e5dd7070Spatrick namespace clang { 41e5dd7070Spatrick namespace tooling { 42e5dd7070Spatrick 43e5dd7070Spatrick /// Specifies the working directory and command of a compilation. 44e5dd7070Spatrick struct CompileCommand { 45e5dd7070Spatrick CompileCommand() = default; CompileCommandCompileCommand46a9ac8606Spatrick CompileCommand(const Twine &Directory, const Twine &Filename, 47a9ac8606Spatrick std::vector<std::string> CommandLine, const Twine &Output) 48e5dd7070Spatrick : Directory(Directory.str()), Filename(Filename.str()), 49e5dd7070Spatrick CommandLine(std::move(CommandLine)), Output(Output.str()) {} 50e5dd7070Spatrick 51e5dd7070Spatrick /// The working directory the command was executed from. 52e5dd7070Spatrick std::string Directory; 53e5dd7070Spatrick 54e5dd7070Spatrick /// The source file associated with the command. 55e5dd7070Spatrick std::string Filename; 56e5dd7070Spatrick 57e5dd7070Spatrick /// The command line that was executed. 58e5dd7070Spatrick std::vector<std::string> CommandLine; 59e5dd7070Spatrick 60e5dd7070Spatrick /// The output file associated with the command. 61e5dd7070Spatrick std::string Output; 62e5dd7070Spatrick 63e5dd7070Spatrick /// If this compile command was guessed rather than read from an authoritative 64e5dd7070Spatrick /// source, a short human-readable explanation. 65e5dd7070Spatrick /// e.g. "inferred from foo/bar.h". 66e5dd7070Spatrick std::string Heuristic; 67e5dd7070Spatrick 68e5dd7070Spatrick friend bool operator==(const CompileCommand &LHS, const CompileCommand &RHS) { 69e5dd7070Spatrick return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename && 70e5dd7070Spatrick LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output && 71e5dd7070Spatrick LHS.Heuristic == RHS.Heuristic; 72e5dd7070Spatrick } 73e5dd7070Spatrick 74e5dd7070Spatrick friend bool operator!=(const CompileCommand &LHS, const CompileCommand &RHS) { 75e5dd7070Spatrick return !(LHS == RHS); 76e5dd7070Spatrick } 77e5dd7070Spatrick }; 78e5dd7070Spatrick 79e5dd7070Spatrick /// Interface for compilation databases. 80e5dd7070Spatrick /// 81e5dd7070Spatrick /// A compilation database allows the user to retrieve compile command lines 82e5dd7070Spatrick /// for the files in a project. 83e5dd7070Spatrick /// 84e5dd7070Spatrick /// Many implementations are enumerable, allowing all command lines to be 85e5dd7070Spatrick /// retrieved. These can be used to run clang tools over a subset of the files 86e5dd7070Spatrick /// in a project. 87e5dd7070Spatrick class CompilationDatabase { 88e5dd7070Spatrick public: 89e5dd7070Spatrick virtual ~CompilationDatabase(); 90e5dd7070Spatrick 91e5dd7070Spatrick /// Loads a compilation database from a build directory. 92e5dd7070Spatrick /// 93e5dd7070Spatrick /// Looks at the specified 'BuildDirectory' and creates a compilation database 94e5dd7070Spatrick /// that allows to query compile commands for source files in the 95e5dd7070Spatrick /// corresponding source tree. 96e5dd7070Spatrick /// 97e5dd7070Spatrick /// Returns NULL and sets ErrorMessage if we were not able to build up a 98e5dd7070Spatrick /// compilation database for the build directory. 99e5dd7070Spatrick /// 100e5dd7070Spatrick /// FIXME: Currently only supports JSON compilation databases, which 101e5dd7070Spatrick /// are named 'compile_commands.json' in the given directory. Extend this 102e5dd7070Spatrick /// for other build types (like ninja build files). 103e5dd7070Spatrick static std::unique_ptr<CompilationDatabase> 104e5dd7070Spatrick loadFromDirectory(StringRef BuildDirectory, std::string &ErrorMessage); 105e5dd7070Spatrick 106e5dd7070Spatrick /// Tries to detect a compilation database location and load it. 107e5dd7070Spatrick /// 108e5dd7070Spatrick /// Looks for a compilation database in all parent paths of file 'SourceFile' 109e5dd7070Spatrick /// by calling loadFromDirectory. 110e5dd7070Spatrick static std::unique_ptr<CompilationDatabase> 111e5dd7070Spatrick autoDetectFromSource(StringRef SourceFile, std::string &ErrorMessage); 112e5dd7070Spatrick 113e5dd7070Spatrick /// Tries to detect a compilation database location and load it. 114e5dd7070Spatrick /// 115e5dd7070Spatrick /// Looks for a compilation database in directory 'SourceDir' and all 116e5dd7070Spatrick /// its parent paths by calling loadFromDirectory. 117e5dd7070Spatrick static std::unique_ptr<CompilationDatabase> 118e5dd7070Spatrick autoDetectFromDirectory(StringRef SourceDir, std::string &ErrorMessage); 119e5dd7070Spatrick 120e5dd7070Spatrick /// Returns all compile commands in which the specified file was 121e5dd7070Spatrick /// compiled. 122e5dd7070Spatrick /// 123e5dd7070Spatrick /// This includes compile commands that span multiple source files. 124e5dd7070Spatrick /// For example, consider a project with the following compilations: 125e5dd7070Spatrick /// $ clang++ -o test a.cc b.cc t.cc 126e5dd7070Spatrick /// $ clang++ -o production a.cc b.cc -DPRODUCTION 127e5dd7070Spatrick /// A compilation database representing the project would return both command 128e5dd7070Spatrick /// lines for a.cc and b.cc and only the first command line for t.cc. 129e5dd7070Spatrick virtual std::vector<CompileCommand> getCompileCommands( 130e5dd7070Spatrick StringRef FilePath) const = 0; 131e5dd7070Spatrick 132e5dd7070Spatrick /// Returns the list of all files available in the compilation database. 133e5dd7070Spatrick /// 134e5dd7070Spatrick /// By default, returns nothing. Implementations should override this if they 135e5dd7070Spatrick /// can enumerate their source files. getAllFiles()136e5dd7070Spatrick virtual std::vector<std::string> getAllFiles() const { return {}; } 137e5dd7070Spatrick 138e5dd7070Spatrick /// Returns all compile commands for all the files in the compilation 139e5dd7070Spatrick /// database. 140e5dd7070Spatrick /// 141e5dd7070Spatrick /// FIXME: Add a layer in Tooling that provides an interface to run a tool 142e5dd7070Spatrick /// over all files in a compilation database. Not all build systems have the 143e5dd7070Spatrick /// ability to provide a feasible implementation for \c getAllCompileCommands. 144e5dd7070Spatrick /// 145e5dd7070Spatrick /// By default, this is implemented in terms of getAllFiles() and 146e5dd7070Spatrick /// getCompileCommands(). Subclasses may override this for efficiency. 147e5dd7070Spatrick virtual std::vector<CompileCommand> getAllCompileCommands() const; 148e5dd7070Spatrick }; 149e5dd7070Spatrick 150e5dd7070Spatrick /// A compilation database that returns a single compile command line. 151e5dd7070Spatrick /// 152e5dd7070Spatrick /// Useful when we want a tool to behave more like a compiler invocation. 153e5dd7070Spatrick /// This compilation database is not enumerable: getAllFiles() returns {}. 154e5dd7070Spatrick class FixedCompilationDatabase : public CompilationDatabase { 155e5dd7070Spatrick public: 156e5dd7070Spatrick /// Creates a FixedCompilationDatabase from the arguments after "--". 157e5dd7070Spatrick /// 158e5dd7070Spatrick /// Parses the given command line for "--". If "--" is found, the rest of 159e5dd7070Spatrick /// the arguments will make up the command line in the returned 160e5dd7070Spatrick /// FixedCompilationDatabase. 161e5dd7070Spatrick /// The arguments after "--" must not include positional parameters or the 162e5dd7070Spatrick /// argv[0] of the tool. Those will be added by the FixedCompilationDatabase 163e5dd7070Spatrick /// when a CompileCommand is requested. The argv[0] of the returned command 164e5dd7070Spatrick /// line will be "clang-tool". 165e5dd7070Spatrick /// 166e5dd7070Spatrick /// Returns NULL in case "--" is not found. 167e5dd7070Spatrick /// 168e5dd7070Spatrick /// The argument list is meant to be compatible with normal llvm command line 169e5dd7070Spatrick /// parsing in main methods. 170e5dd7070Spatrick /// int main(int argc, char **argv) { 171e5dd7070Spatrick /// std::unique_ptr<FixedCompilationDatabase> Compilations( 172e5dd7070Spatrick /// FixedCompilationDatabase::loadFromCommandLine(argc, argv)); 173e5dd7070Spatrick /// cl::ParseCommandLineOptions(argc, argv); 174e5dd7070Spatrick /// ... 175e5dd7070Spatrick /// } 176e5dd7070Spatrick /// 177e5dd7070Spatrick /// \param Argc The number of command line arguments - will be changed to 178e5dd7070Spatrick /// the number of arguments before "--", if "--" was found in the argument 179e5dd7070Spatrick /// list. 180e5dd7070Spatrick /// \param Argv Points to the command line arguments. 181e5dd7070Spatrick /// \param ErrorMsg Contains error text if the function returns null pointer. 182e5dd7070Spatrick /// \param Directory The base directory used in the FixedCompilationDatabase. 183a9ac8606Spatrick static std::unique_ptr<FixedCompilationDatabase> 184a9ac8606Spatrick loadFromCommandLine(int &Argc, const char *const *Argv, std::string &ErrorMsg, 185a9ac8606Spatrick const Twine &Directory = "."); 186e5dd7070Spatrick 187a9ac8606Spatrick /// Reads flags from the given file, one-per-line. 188e5dd7070Spatrick /// Returns nullptr and sets ErrorMessage if we can't read the file. 189e5dd7070Spatrick static std::unique_ptr<FixedCompilationDatabase> 190e5dd7070Spatrick loadFromFile(StringRef Path, std::string &ErrorMsg); 191e5dd7070Spatrick 192a9ac8606Spatrick /// Reads flags from the given buffer, one-per-line. 193a9ac8606Spatrick /// Directory is the command CWD, typically the parent of compile_flags.txt. 194a9ac8606Spatrick static std::unique_ptr<FixedCompilationDatabase> 195a9ac8606Spatrick loadFromBuffer(StringRef Directory, StringRef Data, std::string &ErrorMsg); 196a9ac8606Spatrick 197e5dd7070Spatrick /// Constructs a compilation data base from a specified directory 198e5dd7070Spatrick /// and command line. 199a9ac8606Spatrick FixedCompilationDatabase(const Twine &Directory, 200a9ac8606Spatrick ArrayRef<std::string> CommandLine); 201e5dd7070Spatrick 202e5dd7070Spatrick /// Returns the given compile command. 203e5dd7070Spatrick /// 204e5dd7070Spatrick /// Will always return a vector with one entry that contains the directory 205e5dd7070Spatrick /// and command line specified at construction with "clang-tool" as argv[0] 206e5dd7070Spatrick /// and 'FilePath' as positional argument. 207e5dd7070Spatrick std::vector<CompileCommand> 208e5dd7070Spatrick getCompileCommands(StringRef FilePath) const override; 209e5dd7070Spatrick 210e5dd7070Spatrick private: 211e5dd7070Spatrick /// This is built up to contain a single entry vector to be returned from 212e5dd7070Spatrick /// getCompileCommands after adding the positional argument. 213e5dd7070Spatrick std::vector<CompileCommand> CompileCommands; 214e5dd7070Spatrick }; 215e5dd7070Spatrick 216a9ac8606Spatrick /// Transforms a compile command so that it applies the same configuration to 217a9ac8606Spatrick /// a different file. Most args are left intact, but tweaks may be needed 218a9ac8606Spatrick /// to certain flags (-x, -std etc). 219*12c85518Srobert /// 220*12c85518Srobert /// The output command will always end in {"--", Filename}. 221a9ac8606Spatrick tooling::CompileCommand transferCompileCommand(tooling::CompileCommand, 222a9ac8606Spatrick StringRef Filename); 223a9ac8606Spatrick 224e5dd7070Spatrick /// Returns a wrapped CompilationDatabase that defers to the provided one, 225e5dd7070Spatrick /// but getCompileCommands() will infer commands for unknown files. 226e5dd7070Spatrick /// The return value of getAllFiles() or getAllCompileCommands() is unchanged. 227e5dd7070Spatrick /// See InterpolatingCompilationDatabase.cpp for details on heuristics. 228e5dd7070Spatrick std::unique_ptr<CompilationDatabase> 229e5dd7070Spatrick inferMissingCompileCommands(std::unique_ptr<CompilationDatabase>); 230e5dd7070Spatrick 231e5dd7070Spatrick /// Returns a wrapped CompilationDatabase that will add -target and -mode flags 232e5dd7070Spatrick /// to commandline when they can be deduced from argv[0] of commandline returned 233e5dd7070Spatrick /// by underlying database. 234e5dd7070Spatrick std::unique_ptr<CompilationDatabase> 235e5dd7070Spatrick inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base); 236e5dd7070Spatrick 237e5dd7070Spatrick /// Returns a wrapped CompilationDatabase that will expand all rsp(response) 238e5dd7070Spatrick /// files on commandline returned by underlying database. 239e5dd7070Spatrick std::unique_ptr<CompilationDatabase> 240e5dd7070Spatrick expandResponseFiles(std::unique_ptr<CompilationDatabase> Base, 241e5dd7070Spatrick llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS); 242e5dd7070Spatrick 243e5dd7070Spatrick } // namespace tooling 244e5dd7070Spatrick } // namespace clang 245e5dd7070Spatrick 246e5dd7070Spatrick #endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H 247