diff options
author | Alex Brachet <abrachet@google.com> | 2023-04-14 19:15:02 +0000 |
---|---|---|
committer | Alex Brachet <abrachet@google.com> | 2023-04-14 19:16:10 +0000 |
commit | 384fca554a5cd19f35b1bb0734eb1e67d525e330 (patch) | |
tree | 5b002eeb218b5124d5cd6e184696fd6962a47f1f /clang/tools | |
parent | 9b17f5ee0e43824e00aaf210a33956c95c445b40 (diff) | |
download | llvm-384fca554a5cd19f35b1bb0734eb1e67d525e330.tar.gz |
Reland "[clang-scan-deps] Migrate to OptTable"
Differential Revision: https://reviews.llvm.org/D139949
Diffstat (limited to 'clang/tools')
-rw-r--r-- | clang/tools/clang-scan-deps/CMakeLists.txt | 7 | ||||
-rw-r--r-- | clang/tools/clang-scan-deps/ClangScanDeps.cpp | 292 | ||||
-rw-r--r-- | clang/tools/clang-scan-deps/Opts.td | 38 |
3 files changed, 219 insertions, 118 deletions
diff --git a/clang/tools/clang-scan-deps/CMakeLists.txt b/clang/tools/clang-scan-deps/CMakeLists.txt index 4db565314c06..8a4543ae4c77 100644 --- a/clang/tools/clang-scan-deps/CMakeLists.txt +++ b/clang/tools/clang-scan-deps/CMakeLists.txt @@ -5,8 +5,15 @@ set(LLVM_LINK_COMPONENTS TargetParser ) +set(LLVM_TARGET_DEFINITIONS Opts.td) +tablegen(LLVM Opts.inc -gen-opt-parser-defs) +add_public_tablegen_target(ScanDepsOptsTableGen) + add_clang_tool(clang-scan-deps ClangScanDeps.cpp + + DEPENDS + ScanDepsOptsTableGen ) set(CLANG_SCAN_DEPS_LIB_DEPS diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index 2f0c4858c4c9..17d062092f07 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -30,11 +30,184 @@ #include <optional> #include <thread> +#include "Opts.inc" + using namespace clang; using namespace tooling::dependencies; namespace { +using namespace llvm::opt; +enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + OPT_##ID, +#include "Opts.inc" +#undef OPTION +}; + +#define PREFIX(NAME, VALUE) \ + constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ + constexpr llvm::ArrayRef<llvm::StringLiteral> NAME( \ + NAME##_init, std::size(NAME##_init) - 1); +#include "Opts.inc" +#undef PREFIX + +const llvm::opt::OptTable::Info InfoTable[] = { +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + {PREFIX, NAME, HELPTEXT, \ + METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, \ + OPT_##ALIAS, ALIASARGS, VALUES}, +#include "Opts.inc" +#undef OPTION +}; + +class ScanDepsOptTable : public llvm::opt::GenericOptTable { +public: + ScanDepsOptTable() : GenericOptTable(InfoTable) { + setGroupedShortOptions(true); + } +}; + +enum ResourceDirRecipeKind { + RDRK_ModifyCompilerPath, + RDRK_InvokeCompiler, +}; + +static ScanningMode ScanMode = ScanningMode::DependencyDirectivesScan; +static ScanningOutputFormat Format = ScanningOutputFormat::Make; +static std::string ModuleFilesDir; +static bool OptimizeArgs; +static bool EagerLoadModules; +static unsigned NumThreads = 0; +static std::string CompilationDB; +static std::string ModuleName; +static std::vector<std::string> ModuleDepTargets; +static bool DeprecatedDriverCommand; +static ResourceDirRecipeKind ResourceDirRecipe; +static bool Verbose; +static std::vector<const char *> CommandLine; + +#ifndef NDEBUG +static constexpr bool DoRoundTripDefault = true; +#else +static constexpr bool DoRoundTripDefault = false; +#endif + +static bool RoundTripArgs = DoRoundTripDefault; + +static void ParseArgs(int argc, char **argv) { + ScanDepsOptTable Tbl; + llvm::StringRef ToolName = argv[0]; + llvm::BumpPtrAllocator A; + llvm::StringSaver Saver{A}; + llvm::opt::InputArgList Args = + Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { + llvm::errs() << Msg << '\n'; + std::exit(1); + }); + + if (Args.hasArg(OPT_help)) { + Tbl.printHelp(llvm::outs(), "clang-scan-deps [options]", "clang-scan-deps"); + std::exit(0); + } + if (Args.hasArg(OPT_version)) { + llvm::outs() << ToolName << '\n'; + llvm::cl::PrintVersionMessage(); + std::exit(0); + } + if (const llvm::opt::Arg *A = Args.getLastArg(OPT_mode_EQ)) { + auto ModeType = + llvm::StringSwitch<std::optional<ScanningMode>>(A->getValue()) + .Case("preprocess-dependency-directives", + ScanningMode::DependencyDirectivesScan) + .Case("preprocess", ScanningMode::CanonicalPreprocessing) + .Default(std::nullopt); + if (!ModeType) { + llvm::errs() << ToolName + << ": for the --mode option: Cannot find option named '" + << A->getValue() << "'\n"; + std::exit(1); + } + ScanMode = *ModeType; + } + + if (const llvm::opt::Arg *A = Args.getLastArg(OPT_format_EQ)) { + auto FormatType = + llvm::StringSwitch<std::optional<ScanningOutputFormat>>(A->getValue()) + .Case("make", ScanningOutputFormat::Make) + .Case("p1689", ScanningOutputFormat::P1689) + .Case("experimental-full", ScanningOutputFormat::Full) + .Default(std::nullopt); + if (!FormatType) { + llvm::errs() << ToolName + << ": for the --format option: Cannot find option named '" + << A->getValue() << "'\n"; + std::exit(1); + } + Format = *FormatType; + } + + if (const llvm::opt::Arg *A = Args.getLastArg(OPT_module_files_dir_EQ)) + ModuleFilesDir = A->getValue(); + + OptimizeArgs = Args.hasArg(OPT_optimize_args); + EagerLoadModules = Args.hasArg(OPT_eager_load_pcm); + + if (const llvm::opt::Arg *A = Args.getLastArg(OPT_j)) { + StringRef S{A->getValue()}; + if (!llvm::to_integer(S, NumThreads, 0)) { + llvm::errs() << ToolName << ": for the -j option: '" << S + << "' value invalid for uint argument!\n"; + std::exit(1); + } + } + + if (const llvm::opt::Arg *A = Args.getLastArg(OPT_compilation_database_EQ)) { + CompilationDB = A->getValue(); + } else if (Format != ScanningOutputFormat::P1689) { + llvm::errs() << ToolName + << ": for the --compiilation-database option: must be " + "specified at least once!"; + std::exit(1); + } + + if (const llvm::opt::Arg *A = Args.getLastArg(OPT_module_name_EQ)) + ModuleName = A->getValue(); + + for (const llvm::opt::Arg *A : Args.filtered(OPT_dependency_target_EQ)) + ModuleDepTargets.emplace_back(A->getValue()); + + DeprecatedDriverCommand = Args.hasArg(OPT_deprecated_driver_command); + + if (const llvm::opt::Arg *A = Args.getLastArg(OPT_resource_dir_recipe_EQ)) { + auto Kind = + llvm::StringSwitch<std::optional<ResourceDirRecipeKind>>(A->getValue()) + .Case("modify-compiler-path", RDRK_ModifyCompilerPath) + .Case("invoke-compiler", RDRK_InvokeCompiler) + .Default(std::nullopt); + if (!Kind) { + llvm::errs() << ToolName + << ": for the --resource-dir-recipe option: Cannot find " + "option named '" + << A->getValue() << "'\n"; + std::exit(1); + } + ResourceDirRecipe = *Kind; + } + + Verbose = Args.hasArg(OPT_verbose); + + RoundTripArgs = Args.hasArg(OPT_round_trip_args); + + if (auto *A = Args.getLastArgNoClaim(OPT_DASH_DASH)) + CommandLine.insert(CommandLine.end(), A->getValues().begin(), + A->getValues().end()); +} + class SharedStream { public: SharedStream(raw_ostream &OS) : OS(OS) {} @@ -112,120 +285,6 @@ private: std::mutex CacheLock; }; -llvm::cl::opt<bool> Help("h", llvm::cl::desc("Alias for -help"), - llvm::cl::Hidden); - -llvm::cl::OptionCategory DependencyScannerCategory("Tool options"); - -static llvm::cl::opt<ScanningMode> ScanMode( - "mode", - llvm::cl::desc("The preprocessing mode used to compute the dependencies"), - llvm::cl::values( - clEnumValN(ScanningMode::DependencyDirectivesScan, - "preprocess-dependency-directives", - "The set of dependencies is computed by preprocessing with " - "special lexing after scanning the source files to get the " - "directives that might affect the dependencies"), - clEnumValN(ScanningMode::CanonicalPreprocessing, "preprocess", - "The set of dependencies is computed by preprocessing the " - "source files")), - llvm::cl::init(ScanningMode::DependencyDirectivesScan), - llvm::cl::cat(DependencyScannerCategory)); - -static llvm::cl::opt<ScanningOutputFormat> Format( - "format", llvm::cl::desc("The output format for the dependencies"), - llvm::cl::values( - clEnumValN(ScanningOutputFormat::Make, "make", - "Makefile compatible dep file"), - clEnumValN(ScanningOutputFormat::P1689, "p1689", - "Generate standard c++ modules dependency P1689 format"), - clEnumValN(ScanningOutputFormat::Full, "experimental-full", - "Full dependency graph suitable" - " for explicitly building modules. This format " - "is experimental and will change.")), - llvm::cl::init(ScanningOutputFormat::Make), - llvm::cl::cat(DependencyScannerCategory)); - -static llvm::cl::opt<std::string> ModuleFilesDir( - "module-files-dir", - llvm::cl::desc( - "The build directory for modules. Defaults to the value of " - "'-fmodules-cache-path=' from command lines for implicit modules."), - llvm::cl::cat(DependencyScannerCategory)); - -static llvm::cl::opt<bool> OptimizeArgs( - "optimize-args", - llvm::cl::desc("Whether to optimize command-line arguments of modules."), - llvm::cl::init(false), llvm::cl::cat(DependencyScannerCategory)); - -static llvm::cl::opt<bool> EagerLoadModules( - "eager-load-pcm", - llvm::cl::desc("Load PCM files eagerly (instead of lazily on import)."), - llvm::cl::init(false), llvm::cl::cat(DependencyScannerCategory)); - -llvm::cl::opt<unsigned> - NumThreads("j", llvm::cl::Optional, - llvm::cl::desc("Number of worker threads to use (default: use " - "all concurrent threads)"), - llvm::cl::init(0), llvm::cl::cat(DependencyScannerCategory)); - -llvm::cl::opt<std::string> - CompilationDB("compilation-database", - llvm::cl::desc("Compilation database"), llvm::cl::Optional, - llvm::cl::cat(DependencyScannerCategory)); - -llvm::cl::opt<std::string> P1689TargettedCommand( - llvm::cl::Positional, llvm::cl::ZeroOrMore, - llvm::cl::desc("The command line flags for the target of which " - "the dependencies are to be computed.")); - -llvm::cl::opt<std::string> ModuleName( - "module-name", llvm::cl::Optional, - llvm::cl::desc("the module of which the dependencies are to be computed"), - llvm::cl::cat(DependencyScannerCategory)); - -llvm::cl::list<std::string> ModuleDepTargets( - "dependency-target", - llvm::cl::desc("The names of dependency targets for the dependency file"), - llvm::cl::cat(DependencyScannerCategory)); - -enum ResourceDirRecipeKind { - RDRK_ModifyCompilerPath, - RDRK_InvokeCompiler, -}; - -static llvm::cl::opt<ResourceDirRecipeKind> ResourceDirRecipe( - "resource-dir-recipe", - llvm::cl::desc("How to produce missing '-resource-dir' argument"), - llvm::cl::values( - clEnumValN(RDRK_ModifyCompilerPath, "modify-compiler-path", - "Construct the resource directory from the compiler path in " - "the compilation database. This assumes it's part of the " - "same toolchain as this clang-scan-deps. (default)"), - clEnumValN(RDRK_InvokeCompiler, "invoke-compiler", - "Invoke the compiler with '-print-resource-dir' and use the " - "reported path as the resource directory. (deprecated)")), - llvm::cl::init(RDRK_ModifyCompilerPath), - llvm::cl::cat(DependencyScannerCategory)); - -#ifndef NDEBUG -static constexpr bool DoRoundTripDefault = true; -#else -static constexpr bool DoRoundTripDefault = false; -#endif - -llvm::cl::opt<bool> - RoundTripArgs("round-trip-args", llvm::cl::Optional, - llvm::cl::desc("verify that command-line arguments are " - "canonical by parsing and re-serializing"), - llvm::cl::init(DoRoundTripDefault), - llvm::cl::cat(DependencyScannerCategory)); - -llvm::cl::opt<bool> Verbose("v", llvm::cl::Optional, - llvm::cl::desc("Use verbose output."), - llvm::cl::init(false), - llvm::cl::cat(DependencyScannerCategory)); - } // end anonymous namespace /// Takes the result of a dependency scan and prints error / dependency files @@ -600,9 +659,7 @@ static std::string getModuleCachePath(ArrayRef<std::string> Args) { static std::unique_ptr<tooling::CompilationDatabase> getCompilationDataBase(int argc, const char **argv, std::string &ErrorMessage) { llvm::InitLLVM X(argc, argv); - llvm::cl::HideUnrelatedOptions(DependencyScannerCategory); - if (!llvm::cl::ParseCommandLineOptions(argc, argv)) - return nullptr; + ParseArgs(argc, const_cast<char **>(argv)); if (!CompilationDB.empty()) return tooling::JSONCompilationDatabase::loadFromFile( @@ -623,7 +680,6 @@ getCompilationDataBase(int argc, const char **argv, std::string &ErrorMessage) { "P1689 per file mode."; return nullptr; } - std::vector<const char *> CommandLine(DoubleDash + 1, argv + argc); llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions); diff --git a/clang/tools/clang-scan-deps/Opts.td b/clang/tools/clang-scan-deps/Opts.td new file mode 100644 index 000000000000..0d121ed7f4f5 --- /dev/null +++ b/clang/tools/clang-scan-deps/Opts.td @@ -0,0 +1,38 @@ +include "llvm/Option/OptParser.td" + +class F<string name, string help> : Flag<["-"], name>, HelpText<help>; +class Arg<string name, string help> : Separate<["-"], name>, HelpText<help>; + +multiclass Eq<string name, string help> { + def NAME #_EQ : Joined<["-", "--"], name #"=">, HelpText<help>; + def : Separate<["-", "--"], name>, Alias<!cast<Joined>(NAME #_EQ)>; +} + +def help : Flag<["--"], "help">, HelpText<"Display this help">; +def version : Flag<["--"], "version">, HelpText<"Display the version">; + +defm mode : Eq<"mode", "The preprocessing mode used to compute the dependencies">; + +defm format : Eq<"format", "The output format for the dependencies">; + +defm module_files_dir : Eq<"module-files-dir", + "The build directory for modules. Defaults to the value of '-fmodules-cache-path=' from command lines for implicit modules">; + +def optimize_args : F<"optimize-args", "Whether to optimize command-line arguments of modules">; +def eager_load_pcm : F<"eager-load-pcm", "Load PCM files eagerly (instead of lazily on import)">; + +def j : Arg<"j", "Number of worker threads to use (default: use all concurrent threads)">; + +defm compilation_database : Eq<"compilation-database", "Compilation database">; +defm module_name : Eq<"module-name", "the module of which the dependencies are to be computed">; +defm dependency_target : Eq<"dependency-target", "The names of dependency targets for the dependency file">; + +def deprecated_driver_command : F<"deprecated-driver-command", "use a single driver command to build the tu (deprecated)">; + +defm resource_dir_recipe : Eq<"resource-dir-recipe", "How to produce missing '-resource-dir' argument">; + +def verbose : F<"v", "Use verbose output">; + +def round_trip_args : F<"round-trip-args", "verify that command-line arguments are canonical by parsing and re-serializing">; + +def DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>;
\ No newline at end of file |