summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/common/cli.hpp13
-rw-r--r--src/buildtool/main/main.cpp189
2 files changed, 119 insertions, 83 deletions
diff --git a/src/buildtool/common/cli.hpp b/src/buildtool/common/cli.hpp
index a95cac5f..7bc0317a 100644
--- a/src/buildtool/common/cli.hpp
+++ b/src/buildtool/common/cli.hpp
@@ -49,6 +49,11 @@ struct AnalysisArguments {
std::optional<std::filesystem::path> artifacts_to_build_file{};
};
+/// \brief Arguments required for describing targets/rules.
+struct DescribeArguments {
+ bool describe_rule{};
+};
+
/// \brief Arguments required for running diagnostics.
struct DiagnosticArguments {
std::optional<std::string> dump_actions{std::nullopt};
@@ -217,6 +222,14 @@ static inline auto SetupAnalysisArguments(
}
}
+static inline auto SetupDescribeArguments(
+ gsl::not_null<CLI::App*> const& app,
+ gsl::not_null<DescribeArguments*> const& clargs) {
+ app->add_flag("--rule",
+ clargs->describe_rule,
+ "Positional arguments refer to rule instead of target.");
+}
+
static inline auto SetupDiagnosticArguments(
gsl::not_null<CLI::App*> const& app,
gsl::not_null<DiagnosticArguments*> const& clargs) {
diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp
index e9f2d72c..997fcd2f 100644
--- a/src/buildtool/main/main.cpp
+++ b/src/buildtool/main/main.cpp
@@ -58,6 +58,7 @@ struct CommandLineArguments {
CommonArguments common;
LogArguments log;
AnalysisArguments analysis;
+ DescribeArguments describe;
DiagnosticArguments diagnose;
EndpointArguments endpoint;
BuildArguments build;
@@ -74,6 +75,7 @@ auto SetupDescribeCommandArguments(
SetupCommonArguments(app, &clargs->common);
SetupAnalysisArguments(app, &clargs->analysis, false);
SetupLogArguments(app, &clargs->log);
+ SetupDescribeArguments(app, &clargs->describe);
}
/// \brief Setup arguments for sub command "just analyse".
@@ -1221,89 +1223,34 @@ void PrintFields(nlohmann::json const& fields,
}
}
-auto DescribeTarget(std::string const& main_repo,
- std::optional<std::filesystem::path> const& main_ws_root,
- std::size_t jobs,
- AnalysisArguments const& clargs) -> int {
+auto DetermineNonExplicitTarget(
+ std::string const& main_repo,
+ std::optional<std::filesystem::path> const& main_ws_root,
+ AnalysisArguments const& clargs)
+ -> std::optional<BuildMaps::Target::ConfiguredTarget> {
auto id = ReadConfiguredTarget(clargs, main_repo, main_ws_root);
- if (id.target.GetNamedTarget().reference_t == Base::ReferenceType::kFile) {
- std::cout << id.ToString() << " is a source file." << std::endl;
- return kExitSuccess;
- }
- auto targets_file_map = Base::CreateTargetsFileMap(jobs);
- nlohmann::json targets_file{};
- bool failed{false};
- {
- TaskSystem ts{jobs};
- targets_file_map.ConsumeAfterKeysReady(
- &ts,
- {id.target.ToModule()},
- [&targets_file](auto values) { targets_file = *values[0]; },
- [&failed](auto const& msg, bool fatal) {
- Logger::Log(fatal ? LogLevel::Error : LogLevel::Warning,
- "While searching for target description:\n{}",
- msg);
- failed = failed or fatal;
- });
- }
- if (failed) {
- return kExitFailure;
- }
- auto desc_it = targets_file.find(id.target.GetNamedTarget().name);
- if (desc_it == targets_file.end()) {
- std::cout << id.ToString() << " is implicitly a source file."
- << std::endl;
- return kExitSuccess;
- }
- nlohmann::json desc = *desc_it;
- auto rule_it = desc.find("type");
- if (rule_it == desc.end()) {
- Logger::Log(LogLevel::Error,
- "{} is a target without specified type.",
- id.ToString());
- return kExitFailure;
- }
- if (BuildMaps::Target::IsBuiltInRule(*rule_it)) {
- std::cout << id.ToString() << " is defined by built-in rule "
- << rule_it->dump() << "." << std::endl;
- if (*rule_it == "export") {
- // export targets may have doc fields of their own.
- auto doc = desc.find("doc");
- if (doc != desc.end()) {
- PrintDoc(*doc, " | ");
- }
- auto config_doc = nlohmann::json::object();
- auto config_doc_it = desc.find("config_doc");
- if (config_doc_it != desc.end() and config_doc_it->is_object()) {
- config_doc = *config_doc_it;
- }
- auto flexible_config = desc.find("flexible_config");
- if (flexible_config != desc.end() and
- (not flexible_config->empty())) {
- std::cout << " Flexible configuration variables\n";
- PrintFields(*flexible_config, config_doc, " - ", " | ");
- }
- }
- return kExitSuccess;
- }
- auto rule_name = BuildMaps::Base::ParseEntityNameFromJson(
- *rule_it, id.target, [&rule_it, &id](std::string const& parse_err) {
- Logger::Log(LogLevel::Error,
- "Parsing rule name {} for target {} failed with:\n{}.",
- rule_it->dump(),
- id.ToString(),
- parse_err);
- });
- if (not rule_name) {
- return kExitFailure;
+ switch (id.target.GetNamedTarget().reference_t) {
+ case Base::ReferenceType::kFile:
+ std::cout << id.ToString() << " is a source file." << std::endl;
+ return std::nullopt;
+ case Base::ReferenceType::kTree:
+ std::cout << id.ToString() << " is a tree." << std::endl;
+ return std::nullopt;
+ case Base::ReferenceType::kTarget:
+ return id;
}
+}
+
+auto DescribeUserDefinedRule(BuildMaps::Base::EntityName const& rule_name,
+ std::size_t jobs) -> int {
+ bool failed{};
auto rule_file_map = Base::CreateRuleFileMap(jobs);
nlohmann::json rules_file;
{
TaskSystem ts{jobs};
rule_file_map.ConsumeAfterKeysReady(
&ts,
- {rule_name->ToModule()},
+ {rule_name.ToModule()},
[&rules_file](auto values) { rules_file = *values[0]; },
[&failed](auto const& msg, bool fatal) {
Logger::Log(fatal ? LogLevel::Error : LogLevel::Warning,
@@ -1315,15 +1262,13 @@ auto DescribeTarget(std::string const& main_repo,
if (failed) {
return kExitFailure;
}
- auto ruledesc_it = rules_file.find(rule_name->GetNamedTarget().name);
+ auto ruledesc_it = rules_file.find(rule_name.GetNamedTarget().name);
if (ruledesc_it == rules_file.end()) {
Logger::Log(LogLevel::Error,
"Rule definition of {} is missing",
- rule_name->ToString());
+ rule_name.ToString());
return kExitFailure;
}
- std::cout << id.ToString() << " is defined by user-defined rule "
- << rule_name->ToString() << ".\n\n";
auto const& rdesc = *ruledesc_it;
auto doc = rdesc.find("doc");
if (doc != rdesc.end()) {
@@ -1383,6 +1328,80 @@ auto DescribeTarget(std::string const& main_repo,
return kExitSuccess;
}
+auto DescribeTarget(BuildMaps::Target::ConfiguredTarget const& id,
+ std::size_t jobs) -> int {
+ auto targets_file_map = Base::CreateTargetsFileMap(jobs);
+ nlohmann::json targets_file{};
+ bool failed{false};
+ {
+ TaskSystem ts{jobs};
+ targets_file_map.ConsumeAfterKeysReady(
+ &ts,
+ {id.target.ToModule()},
+ [&targets_file](auto values) { targets_file = *values[0]; },
+ [&failed](auto const& msg, bool fatal) {
+ Logger::Log(fatal ? LogLevel::Error : LogLevel::Warning,
+ "While searching for target description:\n{}",
+ msg);
+ failed = failed or fatal;
+ });
+ }
+ if (failed) {
+ return kExitFailure;
+ }
+ auto desc_it = targets_file.find(id.target.GetNamedTarget().name);
+ if (desc_it == targets_file.end()) {
+ std::cout << id.ToString() << " is implicitly a source file."
+ << std::endl;
+ return kExitSuccess;
+ }
+ nlohmann::json desc = *desc_it;
+ auto rule_it = desc.find("type");
+ if (rule_it == desc.end()) {
+ Logger::Log(LogLevel::Error,
+ "{} is a target without specified type.",
+ id.ToString());
+ return kExitFailure;
+ }
+ if (BuildMaps::Target::IsBuiltInRule(*rule_it)) {
+ std::cout << id.ToString() << " is defined by built-in rule "
+ << rule_it->dump() << "." << std::endl;
+ if (*rule_it == "export") {
+ // export targets may have doc fields of their own.
+ auto doc = desc.find("doc");
+ if (doc != desc.end()) {
+ PrintDoc(*doc, " | ");
+ }
+ auto config_doc = nlohmann::json::object();
+ auto config_doc_it = desc.find("config_doc");
+ if (config_doc_it != desc.end() and config_doc_it->is_object()) {
+ config_doc = *config_doc_it;
+ }
+ auto flexible_config = desc.find("flexible_config");
+ if (flexible_config != desc.end() and
+ (not flexible_config->empty())) {
+ std::cout << " Flexible configuration variables\n";
+ PrintFields(*flexible_config, config_doc, " - ", " | ");
+ }
+ }
+ return kExitSuccess;
+ }
+ auto rule_name = BuildMaps::Base::ParseEntityNameFromJson(
+ *rule_it, id.target, [&rule_it, &id](std::string const& parse_err) {
+ Logger::Log(LogLevel::Error,
+ "Parsing rule name {} for target {} failed with:\n{}.",
+ rule_it->dump(),
+ id.ToString(),
+ parse_err);
+ });
+ if (not rule_name) {
+ return kExitFailure;
+ }
+ std::cout << id.ToString() << " is defined by user-defined rule "
+ << rule_name->ToString() << ".\n\n";
+ return DescribeUserDefinedRule(*rule_name, jobs);
+}
+
void DumpArtifactsToBuild(
std::map<std::string, ArtifactDescription> const& artifacts,
std::map<std::string, ArtifactDescription> const& runfiles,
@@ -1517,10 +1536,14 @@ auto main(int argc, char* argv[]) -> int {
}
}
else if (arguments.cmd == SubCommand::kDescribe) {
- return DescribeTarget(main_repo,
- main_ws_root,
- arguments.common.jobs,
- arguments.analysis);
+ if (auto id = DetermineNonExplicitTarget(
+ main_repo, main_ws_root, arguments.analysis)) {
+ return arguments.describe.describe_rule
+ ? DescribeUserDefinedRule(id->target,
+ arguments.common.jobs)
+ : DescribeTarget(*id, arguments.common.jobs);
+ }
+ return kExitFailure;
}
else {