xref: /aosp_15_r20/external/clang/lib/Tooling/CommonOptionsParser.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- CommonOptionsParser.cpp - common options for clang tools ---------===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li //  This file implements the CommonOptionsParser class used to parse common
11*67e74705SXin Li //  command-line options for clang tools, so that they can be run as separate
12*67e74705SXin Li //  command-line applications with a consistent common interface for handling
13*67e74705SXin Li //  compilation database and input files.
14*67e74705SXin Li //
15*67e74705SXin Li //  It provides a common subset of command-line options, common algorithm
16*67e74705SXin Li //  for locating a compilation database and source files, and help messages
17*67e74705SXin Li //  for the basic command-line interface.
18*67e74705SXin Li //
19*67e74705SXin Li //  It creates a CompilationDatabase and reads common command-line options.
20*67e74705SXin Li //
21*67e74705SXin Li //  This class uses the Clang Tooling infrastructure, see
22*67e74705SXin Li //    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
23*67e74705SXin Li //  for details on setting it up with LLVM source tree.
24*67e74705SXin Li //
25*67e74705SXin Li //===----------------------------------------------------------------------===//
26*67e74705SXin Li 
27*67e74705SXin Li #include "llvm/Support/CommandLine.h"
28*67e74705SXin Li #include "clang/Tooling/ArgumentsAdjusters.h"
29*67e74705SXin Li #include "clang/Tooling/CommonOptionsParser.h"
30*67e74705SXin Li #include "clang/Tooling/Tooling.h"
31*67e74705SXin Li 
32*67e74705SXin Li using namespace clang::tooling;
33*67e74705SXin Li using namespace llvm;
34*67e74705SXin Li 
35*67e74705SXin Li const char *const CommonOptionsParser::HelpMessage =
36*67e74705SXin Li     "\n"
37*67e74705SXin Li     "-p <build-path> is used to read a compile command database.\n"
38*67e74705SXin Li     "\n"
39*67e74705SXin Li     "\tFor example, it can be a CMake build directory in which a file named\n"
40*67e74705SXin Li     "\tcompile_commands.json exists (use -DCMAKE_EXPORT_COMPILE_COMMANDS=ON\n"
41*67e74705SXin Li     "\tCMake option to get this output). When no build path is specified,\n"
42*67e74705SXin Li     "\ta search for compile_commands.json will be attempted through all\n"
43*67e74705SXin Li     "\tparent paths of the first input file . See:\n"
44*67e74705SXin Li     "\thttp://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an\n"
45*67e74705SXin Li     "\texample of setting up Clang Tooling on a source tree.\n"
46*67e74705SXin Li     "\n"
47*67e74705SXin Li     "<source0> ... specify the paths of source files. These paths are\n"
48*67e74705SXin Li     "\tlooked up in the compile command database. If the path of a file is\n"
49*67e74705SXin Li     "\tabsolute, it needs to point into CMake's source tree. If the path is\n"
50*67e74705SXin Li     "\trelative, the current working directory needs to be in the CMake\n"
51*67e74705SXin Li     "\tsource tree and the file must be in a subdirectory of the current\n"
52*67e74705SXin Li     "\tworking directory. \"./\" prefixes in the relative files will be\n"
53*67e74705SXin Li     "\tautomatically removed, but the rest of a relative path must be a\n"
54*67e74705SXin Li     "\tsuffix of a path in the compile command database.\n"
55*67e74705SXin Li     "\n";
56*67e74705SXin Li 
57*67e74705SXin Li namespace {
58*67e74705SXin Li class ArgumentsAdjustingCompilations : public CompilationDatabase {
59*67e74705SXin Li public:
ArgumentsAdjustingCompilations(std::unique_ptr<CompilationDatabase> Compilations)60*67e74705SXin Li   ArgumentsAdjustingCompilations(
61*67e74705SXin Li       std::unique_ptr<CompilationDatabase> Compilations)
62*67e74705SXin Li       : Compilations(std::move(Compilations)) {}
63*67e74705SXin Li 
appendArgumentsAdjuster(ArgumentsAdjuster Adjuster)64*67e74705SXin Li   void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster) {
65*67e74705SXin Li     Adjusters.push_back(std::move(Adjuster));
66*67e74705SXin Li   }
67*67e74705SXin Li 
68*67e74705SXin Li   std::vector<CompileCommand>
getCompileCommands(StringRef FilePath) const69*67e74705SXin Li   getCompileCommands(StringRef FilePath) const override {
70*67e74705SXin Li     return adjustCommands(Compilations->getCompileCommands(FilePath));
71*67e74705SXin Li   }
72*67e74705SXin Li 
getAllFiles() const73*67e74705SXin Li   std::vector<std::string> getAllFiles() const override {
74*67e74705SXin Li     return Compilations->getAllFiles();
75*67e74705SXin Li   }
76*67e74705SXin Li 
getAllCompileCommands() const77*67e74705SXin Li   std::vector<CompileCommand> getAllCompileCommands() const override {
78*67e74705SXin Li     return adjustCommands(Compilations->getAllCompileCommands());
79*67e74705SXin Li   }
80*67e74705SXin Li 
81*67e74705SXin Li private:
82*67e74705SXin Li   std::unique_ptr<CompilationDatabase> Compilations;
83*67e74705SXin Li   std::vector<ArgumentsAdjuster> Adjusters;
84*67e74705SXin Li 
85*67e74705SXin Li   std::vector<CompileCommand>
adjustCommands(std::vector<CompileCommand> Commands) const86*67e74705SXin Li   adjustCommands(std::vector<CompileCommand> Commands) const {
87*67e74705SXin Li     for (CompileCommand &Command : Commands)
88*67e74705SXin Li       for (const auto &Adjuster : Adjusters)
89*67e74705SXin Li         Command.CommandLine = Adjuster(Command.CommandLine, Command.Filename);
90*67e74705SXin Li     return Commands;
91*67e74705SXin Li   }
92*67e74705SXin Li };
93*67e74705SXin Li } // namespace
94*67e74705SXin Li 
CommonOptionsParser(int & argc,const char ** argv,cl::OptionCategory & Category,llvm::cl::NumOccurrencesFlag OccurrencesFlag,const char * Overview)95*67e74705SXin Li CommonOptionsParser::CommonOptionsParser(
96*67e74705SXin Li     int &argc, const char **argv, cl::OptionCategory &Category,
97*67e74705SXin Li     llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
98*67e74705SXin Li   static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
99*67e74705SXin Li 
100*67e74705SXin Li   static cl::opt<std::string> BuildPath("p", cl::desc("Build path"),
101*67e74705SXin Li                                         cl::Optional, cl::cat(Category));
102*67e74705SXin Li 
103*67e74705SXin Li   static cl::list<std::string> SourcePaths(
104*67e74705SXin Li       cl::Positional, cl::desc("<source0> [... <sourceN>]"), OccurrencesFlag,
105*67e74705SXin Li       cl::cat(Category));
106*67e74705SXin Li 
107*67e74705SXin Li   static cl::list<std::string> ArgsAfter(
108*67e74705SXin Li       "extra-arg",
109*67e74705SXin Li       cl::desc("Additional argument to append to the compiler command line"),
110*67e74705SXin Li       cl::cat(Category));
111*67e74705SXin Li 
112*67e74705SXin Li   static cl::list<std::string> ArgsBefore(
113*67e74705SXin Li       "extra-arg-before",
114*67e74705SXin Li       cl::desc("Additional argument to prepend to the compiler command line"),
115*67e74705SXin Li       cl::cat(Category));
116*67e74705SXin Li 
117*67e74705SXin Li   cl::HideUnrelatedOptions(Category);
118*67e74705SXin Li 
119*67e74705SXin Li   Compilations.reset(FixedCompilationDatabase::loadFromCommandLine(argc, argv));
120*67e74705SXin Li   cl::ParseCommandLineOptions(argc, argv, Overview);
121*67e74705SXin Li   cl::PrintOptionValues();
122*67e74705SXin Li 
123*67e74705SXin Li   SourcePathList = SourcePaths;
124*67e74705SXin Li   if ((OccurrencesFlag == cl::ZeroOrMore || OccurrencesFlag == cl::Optional) &&
125*67e74705SXin Li       SourcePathList.empty())
126*67e74705SXin Li     return;
127*67e74705SXin Li   if (!Compilations) {
128*67e74705SXin Li     std::string ErrorMessage;
129*67e74705SXin Li     if (!BuildPath.empty()) {
130*67e74705SXin Li       Compilations =
131*67e74705SXin Li           CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage);
132*67e74705SXin Li     } else {
133*67e74705SXin Li       Compilations = CompilationDatabase::autoDetectFromSource(SourcePaths[0],
134*67e74705SXin Li                                                                ErrorMessage);
135*67e74705SXin Li     }
136*67e74705SXin Li     if (!Compilations) {
137*67e74705SXin Li       llvm::errs() << "Error while trying to load a compilation database:\n"
138*67e74705SXin Li                    << ErrorMessage << "Running without flags.\n";
139*67e74705SXin Li       Compilations.reset(
140*67e74705SXin Li           new FixedCompilationDatabase(".", std::vector<std::string>()));
141*67e74705SXin Li     }
142*67e74705SXin Li   }
143*67e74705SXin Li   auto AdjustingCompilations =
144*67e74705SXin Li       llvm::make_unique<ArgumentsAdjustingCompilations>(
145*67e74705SXin Li           std::move(Compilations));
146*67e74705SXin Li   AdjustingCompilations->appendArgumentsAdjuster(
147*67e74705SXin Li       getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN));
148*67e74705SXin Li   AdjustingCompilations->appendArgumentsAdjuster(
149*67e74705SXin Li       getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END));
150*67e74705SXin Li   Compilations = std::move(AdjustingCompilations);
151*67e74705SXin Li }
152