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