summaryrefslogtreecommitdiff
path: root/clang/tools
diff options
context:
space:
mode:
authorAlex Brachet <abrachet@google.com>2023-04-14 19:15:02 +0000
committerAlex Brachet <abrachet@google.com>2023-04-14 19:16:10 +0000
commit384fca554a5cd19f35b1bb0734eb1e67d525e330 (patch)
tree5b002eeb218b5124d5cd6e184696fd6962a47f1f /clang/tools
parent9b17f5ee0e43824e00aaf210a33956c95c445b40 (diff)
downloadllvm-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.txt7
-rw-r--r--clang/tools/clang-scan-deps/ClangScanDeps.cpp292
-rw-r--r--clang/tools/clang-scan-deps/Opts.td38
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