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