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