xref: /freebsd-src/contrib/llvm-project/clang/include/clang/Tooling/CompilationDatabase.h (revision 6e516c87b6d779911edde7481d8aef165b837a03)
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