clang API Documentation

CommonOptionsParser.cpp
Go to the documentation of this file.
00001 //===--- CommonOptionsParser.cpp - common options for clang tools ---------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file implements the CommonOptionsParser class used to parse common
00011 //  command-line options for clang tools, so that they can be run as separate
00012 //  command-line applications with a consistent common interface for handling
00013 //  compilation database and input files.
00014 //
00015 //  It provides a common subset of command-line options, common algorithm
00016 //  for locating a compilation database and source files, and help messages
00017 //  for the basic command-line interface.
00018 //
00019 //  It creates a CompilationDatabase and reads common command-line options.
00020 //
00021 //  This class uses the Clang Tooling infrastructure, see
00022 //    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
00023 //  for details on setting it up with LLVM source tree.
00024 //
00025 //===----------------------------------------------------------------------===//
00026 
00027 #include "llvm/Support/CommandLine.h"
00028 #include "clang/Tooling/ArgumentsAdjusters.h"
00029 #include "clang/Tooling/CommonOptionsParser.h"
00030 #include "clang/Tooling/Tooling.h"
00031 
00032 using namespace clang::tooling;
00033 using namespace llvm;
00034 
00035 const char *const CommonOptionsParser::HelpMessage =
00036     "\n"
00037     "-p <build-path> is used to read a compile command database.\n"
00038     "\n"
00039     "\tFor example, it can be a CMake build directory in which a file named\n"
00040     "\tcompile_commands.json exists (use -DCMAKE_EXPORT_COMPILE_COMMANDS=ON\n"
00041     "\tCMake option to get this output). When no build path is specified,\n"
00042     "\ta search for compile_commands.json will be attempted through all\n"
00043     "\tparent paths of the first input file . See:\n"
00044     "\thttp://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an\n"
00045     "\texample of setting up Clang Tooling on a source tree.\n"
00046     "\n"
00047     "<source0> ... specify the paths of source files. These paths are\n"
00048     "\tlooked up in the compile command database. If the path of a file is\n"
00049     "\tabsolute, it needs to point into CMake's source tree. If the path is\n"
00050     "\trelative, the current working directory needs to be in the CMake\n"
00051     "\tsource tree and the file must be in a subdirectory of the current\n"
00052     "\tworking directory. \"./\" prefixes in the relative files will be\n"
00053     "\tautomatically removed, but the rest of a relative path must be a\n"
00054     "\tsuffix of a path in the compile command database.\n"
00055     "\n";
00056 
00057 class ArgumentsAdjustingCompilations : public CompilationDatabase {
00058 public:
00059   ArgumentsAdjustingCompilations(
00060       std::unique_ptr<CompilationDatabase> Compilations)
00061       : Compilations(std::move(Compilations)) {}
00062 
00063   void appendArgumentsAdjuster(std::unique_ptr<ArgumentsAdjuster> Adjuster) {
00064     Adjusters.push_back(std::move(Adjuster));
00065   }
00066 
00067   std::vector<CompileCommand>
00068   getCompileCommands(StringRef FilePath) const override {
00069     return adjustCommands(Compilations->getCompileCommands(FilePath));
00070   }
00071 
00072   std::vector<std::string> getAllFiles() const override {
00073     return Compilations->getAllFiles();
00074   }
00075 
00076   std::vector<CompileCommand> getAllCompileCommands() const override {
00077     return adjustCommands(Compilations->getAllCompileCommands());
00078   }
00079 
00080 private:
00081   std::unique_ptr<CompilationDatabase> Compilations;
00082   std::vector<std::unique_ptr<ArgumentsAdjuster>> Adjusters;
00083 
00084   std::vector<CompileCommand>
00085   adjustCommands(std::vector<CompileCommand> Commands) const {
00086     for (CompileCommand &Command : Commands)
00087       for (const auto &Adjuster : Adjusters)
00088         Command.CommandLine = Adjuster->Adjust(Command.CommandLine);
00089     return Commands;
00090   }
00091 };
00092 
00093 CommonOptionsParser::CommonOptionsParser(int &argc, const char **argv,
00094                                          cl::OptionCategory &Category,
00095                                          const char *Overview) {
00096   static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
00097 
00098   static cl::opt<std::string> BuildPath("p", cl::desc("Build path"),
00099                                         cl::Optional, cl::cat(Category));
00100 
00101   static cl::list<std::string> SourcePaths(
00102       cl::Positional, cl::desc("<source0> [... <sourceN>]"), cl::OneOrMore,
00103       cl::cat(Category));
00104 
00105   static cl::list<std::string> ArgsAfter(
00106       "extra-arg",
00107       cl::desc("Additional argument to append to the compiler command line"),
00108       cl::cat(Category));
00109 
00110   static cl::list<std::string> ArgsBefore(
00111       "extra-arg-before",
00112       cl::desc("Additional argument to prepend to the compiler command line"),
00113       cl::cat(Category));
00114 
00115   // Hide unrelated options.
00116   StringMap<cl::Option*> Options;
00117   cl::getRegisteredOptions(Options);
00118   for (StringMap<cl::Option *>::iterator I = Options.begin(), E = Options.end();
00119        I != E; ++I) {
00120     if (I->second->Category != &Category && I->first() != "help" &&
00121         I->first() != "version")
00122       I->second->setHiddenFlag(cl::ReallyHidden);
00123   }
00124 
00125   Compilations.reset(FixedCompilationDatabase::loadFromCommandLine(argc,
00126                                                                    argv));
00127   cl::ParseCommandLineOptions(argc, argv, Overview);
00128   SourcePathList = SourcePaths;
00129   if (!Compilations) {
00130     std::string ErrorMessage;
00131     if (!BuildPath.empty()) {
00132       Compilations =
00133           CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage);
00134     } else {
00135       Compilations = CompilationDatabase::autoDetectFromSource(SourcePaths[0],
00136                                                                ErrorMessage);
00137     }
00138     if (!Compilations)
00139       llvm::report_fatal_error(ErrorMessage);
00140   }
00141   auto AdjustingCompilations =
00142       llvm::make_unique<ArgumentsAdjustingCompilations>(
00143           std::move(Compilations));
00144   AdjustingCompilations->appendArgumentsAdjuster(
00145       llvm::make_unique<InsertArgumentAdjuster>(ArgsBefore,
00146                                                 InsertArgumentAdjuster::BEGIN));
00147   AdjustingCompilations->appendArgumentsAdjuster(
00148       llvm::make_unique<InsertArgumentAdjuster>(ArgsAfter,
00149                                                 InsertArgumentAdjuster::END));
00150   Compilations = std::move(AdjustingCompilations);
00151 }