10b57cec5SDimitry Andric //===- CompilationDatabase.h ------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file provides an interface and multiple implementations for 100b57cec5SDimitry Andric // CompilationDatabases. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric // While C++ refactoring and analysis tools are not compilers, and thus 130b57cec5SDimitry Andric // don't run as part of the build system, they need the exact information 140b57cec5SDimitry Andric // of a build in order to be able to correctly understand the C++ code of 150b57cec5SDimitry Andric // the project. This information is provided via the CompilationDatabase 160b57cec5SDimitry Andric // interface. 170b57cec5SDimitry Andric // 180b57cec5SDimitry Andric // To create a CompilationDatabase from a build directory one can call 190b57cec5SDimitry Andric // CompilationDatabase::loadFromDirectory(), which deduces the correct 200b57cec5SDimitry Andric // compilation database from the root of the build tree. 210b57cec5SDimitry Andric // 220b57cec5SDimitry Andric // See the concrete subclasses of CompilationDatabase for currently supported 230b57cec5SDimitry Andric // formats. 240b57cec5SDimitry Andric // 250b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric #ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H 280b57cec5SDimitry Andric #define LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 310b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 320b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 330b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 34480093f4SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 350b57cec5SDimitry Andric #include <memory> 360b57cec5SDimitry Andric #include <string> 370b57cec5SDimitry Andric #include <utility> 380b57cec5SDimitry Andric #include <vector> 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric namespace clang { 410b57cec5SDimitry Andric namespace tooling { 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric /// Specifies the working directory and command of a compilation. 440b57cec5SDimitry Andric struct CompileCommand { 450b57cec5SDimitry Andric CompileCommand() = default; 46e8d8bef9SDimitry Andric CompileCommand(const Twine &Directory, const Twine &Filename, 47e8d8bef9SDimitry Andric std::vector<std::string> CommandLine, const Twine &Output) 480b57cec5SDimitry Andric : Directory(Directory.str()), Filename(Filename.str()), 490b57cec5SDimitry Andric CommandLine(std::move(CommandLine)), Output(Output.str()) {} 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric /// The working directory the command was executed from. 520b57cec5SDimitry Andric std::string Directory; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric /// The source file associated with the command. 550b57cec5SDimitry Andric std::string Filename; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric /// The command line that was executed. 580b57cec5SDimitry Andric std::vector<std::string> CommandLine; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric /// The output file associated with the command. 610b57cec5SDimitry Andric std::string Output; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// If this compile command was guessed rather than read from an authoritative 640b57cec5SDimitry Andric /// source, a short human-readable explanation. 650b57cec5SDimitry Andric /// e.g. "inferred from foo/bar.h". 660b57cec5SDimitry Andric std::string Heuristic; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric friend bool operator==(const CompileCommand &LHS, const CompileCommand &RHS) { 690b57cec5SDimitry Andric return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename && 700b57cec5SDimitry Andric LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output && 710b57cec5SDimitry Andric LHS.Heuristic == RHS.Heuristic; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric friend bool operator!=(const CompileCommand &LHS, const CompileCommand &RHS) { 750b57cec5SDimitry Andric return !(LHS == RHS); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric }; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Interface for compilation databases. 800b57cec5SDimitry Andric /// 810b57cec5SDimitry Andric /// A compilation database allows the user to retrieve compile command lines 820b57cec5SDimitry Andric /// for the files in a project. 830b57cec5SDimitry Andric /// 840b57cec5SDimitry Andric /// Many implementations are enumerable, allowing all command lines to be 850b57cec5SDimitry Andric /// retrieved. These can be used to run clang tools over a subset of the files 860b57cec5SDimitry Andric /// in a project. 870b57cec5SDimitry Andric class CompilationDatabase { 880b57cec5SDimitry Andric public: 890b57cec5SDimitry Andric virtual ~CompilationDatabase(); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric /// Loads a compilation database from a build directory. 920b57cec5SDimitry Andric /// 930b57cec5SDimitry Andric /// Looks at the specified 'BuildDirectory' and creates a compilation database 940b57cec5SDimitry Andric /// that allows to query compile commands for source files in the 950b57cec5SDimitry Andric /// corresponding source tree. 960b57cec5SDimitry Andric /// 970b57cec5SDimitry Andric /// Returns NULL and sets ErrorMessage if we were not able to build up a 980b57cec5SDimitry Andric /// compilation database for the build directory. 990b57cec5SDimitry Andric /// 1000b57cec5SDimitry Andric /// FIXME: Currently only supports JSON compilation databases, which 1010b57cec5SDimitry Andric /// are named 'compile_commands.json' in the given directory. Extend this 1020b57cec5SDimitry Andric /// for other build types (like ninja build files). 1030b57cec5SDimitry Andric static std::unique_ptr<CompilationDatabase> 1040b57cec5SDimitry Andric loadFromDirectory(StringRef BuildDirectory, std::string &ErrorMessage); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric /// Tries to detect a compilation database location and load it. 1070b57cec5SDimitry Andric /// 1080b57cec5SDimitry Andric /// Looks for a compilation database in all parent paths of file 'SourceFile' 1090b57cec5SDimitry Andric /// by calling loadFromDirectory. 1100b57cec5SDimitry Andric static std::unique_ptr<CompilationDatabase> 1110b57cec5SDimitry Andric autoDetectFromSource(StringRef SourceFile, std::string &ErrorMessage); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric /// Tries to detect a compilation database location and load it. 1140b57cec5SDimitry Andric /// 1150b57cec5SDimitry Andric /// Looks for a compilation database in directory 'SourceDir' and all 1160b57cec5SDimitry Andric /// its parent paths by calling loadFromDirectory. 1170b57cec5SDimitry Andric static std::unique_ptr<CompilationDatabase> 1180b57cec5SDimitry Andric autoDetectFromDirectory(StringRef SourceDir, std::string &ErrorMessage); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric /// Returns all compile commands in which the specified file was 1210b57cec5SDimitry Andric /// compiled. 1220b57cec5SDimitry Andric /// 1230b57cec5SDimitry Andric /// This includes compile commands that span multiple source files. 1240b57cec5SDimitry Andric /// For example, consider a project with the following compilations: 1250b57cec5SDimitry Andric /// $ clang++ -o test a.cc b.cc t.cc 1260b57cec5SDimitry Andric /// $ clang++ -o production a.cc b.cc -DPRODUCTION 1270b57cec5SDimitry Andric /// A compilation database representing the project would return both command 1280b57cec5SDimitry Andric /// lines for a.cc and b.cc and only the first command line for t.cc. 1290b57cec5SDimitry Andric virtual std::vector<CompileCommand> getCompileCommands( 1300b57cec5SDimitry Andric StringRef FilePath) const = 0; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric /// Returns the list of all files available in the compilation database. 1330b57cec5SDimitry Andric /// 1340b57cec5SDimitry Andric /// By default, returns nothing. Implementations should override this if they 1350b57cec5SDimitry Andric /// can enumerate their source files. 1360b57cec5SDimitry Andric virtual std::vector<std::string> getAllFiles() const { return {}; } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric /// Returns all compile commands for all the files in the compilation 1390b57cec5SDimitry Andric /// database. 1400b57cec5SDimitry Andric /// 1410b57cec5SDimitry Andric /// FIXME: Add a layer in Tooling that provides an interface to run a tool 1420b57cec5SDimitry Andric /// over all files in a compilation database. Not all build systems have the 1430b57cec5SDimitry Andric /// ability to provide a feasible implementation for \c getAllCompileCommands. 1440b57cec5SDimitry Andric /// 1450b57cec5SDimitry Andric /// By default, this is implemented in terms of getAllFiles() and 1460b57cec5SDimitry Andric /// getCompileCommands(). Subclasses may override this for efficiency. 1470b57cec5SDimitry Andric virtual std::vector<CompileCommand> getAllCompileCommands() const; 1480b57cec5SDimitry Andric }; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric /// A compilation database that returns a single compile command line. 1510b57cec5SDimitry Andric /// 1520b57cec5SDimitry Andric /// Useful when we want a tool to behave more like a compiler invocation. 1530b57cec5SDimitry Andric /// This compilation database is not enumerable: getAllFiles() returns {}. 1540b57cec5SDimitry Andric class FixedCompilationDatabase : public CompilationDatabase { 1550b57cec5SDimitry Andric public: 1560b57cec5SDimitry Andric /// Creates a FixedCompilationDatabase from the arguments after "--". 1570b57cec5SDimitry Andric /// 1580b57cec5SDimitry Andric /// Parses the given command line for "--". If "--" is found, the rest of 1590b57cec5SDimitry Andric /// the arguments will make up the command line in the returned 1600b57cec5SDimitry Andric /// FixedCompilationDatabase. 1610b57cec5SDimitry Andric /// The arguments after "--" must not include positional parameters or the 1620b57cec5SDimitry Andric /// argv[0] of the tool. Those will be added by the FixedCompilationDatabase 1630b57cec5SDimitry Andric /// when a CompileCommand is requested. The argv[0] of the returned command 1640b57cec5SDimitry Andric /// line will be "clang-tool". 1650b57cec5SDimitry Andric /// 1660b57cec5SDimitry Andric /// Returns NULL in case "--" is not found. 1670b57cec5SDimitry Andric /// 1680b57cec5SDimitry Andric /// The argument list is meant to be compatible with normal llvm command line 1690b57cec5SDimitry Andric /// parsing in main methods. 1700b57cec5SDimitry Andric /// int main(int argc, char **argv) { 1710b57cec5SDimitry Andric /// std::unique_ptr<FixedCompilationDatabase> Compilations( 1720b57cec5SDimitry Andric /// FixedCompilationDatabase::loadFromCommandLine(argc, argv)); 1730b57cec5SDimitry Andric /// cl::ParseCommandLineOptions(argc, argv); 1740b57cec5SDimitry Andric /// ... 1750b57cec5SDimitry Andric /// } 1760b57cec5SDimitry Andric /// 1770b57cec5SDimitry Andric /// \param Argc The number of command line arguments - will be changed to 1780b57cec5SDimitry Andric /// the number of arguments before "--", if "--" was found in the argument 1790b57cec5SDimitry Andric /// list. 1800b57cec5SDimitry Andric /// \param Argv Points to the command line arguments. 1810b57cec5SDimitry Andric /// \param ErrorMsg Contains error text if the function returns null pointer. 1820b57cec5SDimitry Andric /// \param Directory The base directory used in the FixedCompilationDatabase. 183e8d8bef9SDimitry Andric static std::unique_ptr<FixedCompilationDatabase> 184e8d8bef9SDimitry Andric loadFromCommandLine(int &Argc, const char *const *Argv, std::string &ErrorMsg, 185e8d8bef9SDimitry Andric const Twine &Directory = "."); 1860b57cec5SDimitry Andric 187e8d8bef9SDimitry Andric /// Reads flags from the given file, one-per-line. 1880b57cec5SDimitry Andric /// Returns nullptr and sets ErrorMessage if we can't read the file. 1890b57cec5SDimitry Andric static std::unique_ptr<FixedCompilationDatabase> 1900b57cec5SDimitry Andric loadFromFile(StringRef Path, std::string &ErrorMsg); 1910b57cec5SDimitry Andric 192e8d8bef9SDimitry Andric /// Reads flags from the given buffer, one-per-line. 193e8d8bef9SDimitry Andric /// Directory is the command CWD, typically the parent of compile_flags.txt. 194e8d8bef9SDimitry Andric static std::unique_ptr<FixedCompilationDatabase> 195e8d8bef9SDimitry Andric loadFromBuffer(StringRef Directory, StringRef Data, std::string &ErrorMsg); 196e8d8bef9SDimitry Andric 1970b57cec5SDimitry Andric /// Constructs a compilation data base from a specified directory 1980b57cec5SDimitry Andric /// and command line. 199e8d8bef9SDimitry Andric FixedCompilationDatabase(const Twine &Directory, 200e8d8bef9SDimitry Andric ArrayRef<std::string> CommandLine); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric /// Returns the given compile command. 2030b57cec5SDimitry Andric /// 2040b57cec5SDimitry Andric /// Will always return a vector with one entry that contains the directory 2050b57cec5SDimitry Andric /// and command line specified at construction with "clang-tool" as argv[0] 2060b57cec5SDimitry Andric /// and 'FilePath' as positional argument. 2070b57cec5SDimitry Andric std::vector<CompileCommand> 2080b57cec5SDimitry Andric getCompileCommands(StringRef FilePath) const override; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric private: 2110b57cec5SDimitry Andric /// This is built up to contain a single entry vector to be returned from 2120b57cec5SDimitry Andric /// getCompileCommands after adding the positional argument. 2130b57cec5SDimitry Andric std::vector<CompileCommand> CompileCommands; 2140b57cec5SDimitry Andric }; 2150b57cec5SDimitry Andric 216fe6060f1SDimitry Andric /// Transforms a compile command so that it applies the same configuration to 217fe6060f1SDimitry Andric /// a different file. Most args are left intact, but tweaks may be needed 218fe6060f1SDimitry Andric /// to certain flags (-x, -std etc). 21904eeddc0SDimitry Andric /// 22004eeddc0SDimitry Andric /// The output command will always end in {"--", Filename}. 221fe6060f1SDimitry Andric tooling::CompileCommand transferCompileCommand(tooling::CompileCommand, 222fe6060f1SDimitry Andric StringRef Filename); 223fe6060f1SDimitry Andric 2240b57cec5SDimitry Andric /// Returns a wrapped CompilationDatabase that defers to the provided one, 2250b57cec5SDimitry Andric /// but getCompileCommands() will infer commands for unknown files. 2260b57cec5SDimitry Andric /// The return value of getAllFiles() or getAllCompileCommands() is unchanged. 2270b57cec5SDimitry Andric /// See InterpolatingCompilationDatabase.cpp for details on heuristics. 2280b57cec5SDimitry Andric std::unique_ptr<CompilationDatabase> 2290b57cec5SDimitry Andric inferMissingCompileCommands(std::unique_ptr<CompilationDatabase>); 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric /// Returns a wrapped CompilationDatabase that will add -target and -mode flags 2320b57cec5SDimitry Andric /// to commandline when they can be deduced from argv[0] of commandline returned 2330b57cec5SDimitry Andric /// by underlying database. 2340b57cec5SDimitry Andric std::unique_ptr<CompilationDatabase> 2350b57cec5SDimitry Andric inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base); 2360b57cec5SDimitry Andric 237*6e516c87SDimitry Andric /// Returns a wrapped CompilationDatabase that will transform argv[0] to an 238*6e516c87SDimitry Andric /// absolute path, if it currently is a plain tool name, looking it up in 239*6e516c87SDimitry Andric /// PATH. 240*6e516c87SDimitry Andric std::unique_ptr<CompilationDatabase> 241*6e516c87SDimitry Andric inferToolLocation(std::unique_ptr<CompilationDatabase> Base); 242*6e516c87SDimitry Andric 243480093f4SDimitry Andric /// Returns a wrapped CompilationDatabase that will expand all rsp(response) 244480093f4SDimitry Andric /// files on commandline returned by underlying database. 245480093f4SDimitry Andric std::unique_ptr<CompilationDatabase> 246480093f4SDimitry Andric expandResponseFiles(std::unique_ptr<CompilationDatabase> Base, 247480093f4SDimitry Andric llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS); 248480093f4SDimitry Andric 2490b57cec5SDimitry Andric } // namespace tooling 2500b57cec5SDimitry Andric } // namespace clang 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric #endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H 253