diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/main/TARGETS | 26 | ||||
-rw-r--r-- | src/buildtool/main/describe.cpp | 235 | ||||
-rw-r--r-- | src/buildtool/main/describe.hpp | 17 | ||||
-rw-r--r-- | src/buildtool/main/exit_codes.hpp (renamed from src/buildtool/main/main.hpp) | 4 | ||||
-rw-r--r-- | src/buildtool/main/main.cpp | 222 |
5 files changed, 281 insertions, 223 deletions
diff --git a/src/buildtool/main/TARGETS b/src/buildtool/main/TARGETS index d09975ae..2ae81d86 100644 --- a/src/buildtool/main/TARGETS +++ b/src/buildtool/main/TARGETS @@ -3,7 +3,6 @@ , "arguments_config": ["BUILD_STATIC_BINARY"] , "name": ["just"] , "srcs": ["main.cpp"] - , "private-hdrs": ["main.hpp"] , "deps": [ ["src/buildtool/common", "cli"] , ["src/buildtool/common", "config"] @@ -19,8 +18,10 @@ , ["src/buildtool/build_engine/target_map", "target_cache"] , ["src/utils/cpp", "concepts"] , ["src/utils/cpp", "json"] + , "common" , "version" , "install_cas" + , "describe" ] , "stage": ["src", "buildtool", "main"] , "link external": @@ -29,6 +30,29 @@ , "then": ["-static"] } } +, "describe": + { "type": ["@", "rules", "CC", "library"] + , "name": ["describe"] + , "hdrs": ["describe.hpp"] + , "srcs": ["describe.cpp"] + , "deps": + [ ["src/buildtool/build_engine/base_maps", "entity_name"] + , ["src/buildtool/build_engine/base_maps", "rule_map"] + , ["src/buildtool/build_engine/base_maps", "targets_file_map"] + , ["src/buildtool/build_engine/target_map", "target_map"] + , ["src/buildtool/build_engine/target_map", "configured_target"] + , ["src/buildtool/logging", "logging"] + , ["@", "json", "", "json"] + , "common" + ] + , "stage": ["src", "buildtool", "main"] + } +, "common": + { "type": ["@", "rules", "CC", "library"] + , "name": ["common"] + , "hdrs": ["exit_codes.hpp"] + , "stage": ["src", "buildtool", "main"] + } , "install_cas": { "type": ["@", "rules", "CC", "library"] , "name": ["install_cas"] diff --git a/src/buildtool/main/describe.cpp b/src/buildtool/main/describe.cpp new file mode 100644 index 00000000..a8c64677 --- /dev/null +++ b/src/buildtool/main/describe.cpp @@ -0,0 +1,235 @@ +#include "src/buildtool/main/describe.hpp" + +#include <iostream> + +#include <nlohmann/json.hpp> + +#include "src/buildtool/build_engine/base_maps/rule_map.hpp" +#include "src/buildtool/build_engine/base_maps/targets_file_map.hpp" +#include "src/buildtool/build_engine/target_map/target_map.hpp" +#include "src/buildtool/logging/logger.hpp" +#include "src/buildtool/main/exit_codes.hpp" + +namespace { + +namespace Base = BuildMaps::Base; + +void PrintDoc(const nlohmann::json& doc, const std::string& indent) { + if (not doc.is_array()) { + return; + } + for (auto const& line : doc) { + if (line.is_string()) { + std::cout << indent << line.get<std::string>() << "\n"; + } + } +} + +void PrintFields(nlohmann::json const& fields, + const nlohmann::json& fdoc, + const std::string& indent_field, + const std::string& indent_field_doc) { + for (auto const& f : fields) { + std::cout << indent_field << f << "\n"; + auto doc = fdoc.find(f); + if (doc != fdoc.end()) { + PrintDoc(*doc, indent_field_doc); + } + } +} + +void PrettyPrintRule(nlohmann::json const& rdesc) { + auto doc = rdesc.find("doc"); + if (doc != rdesc.end()) { + PrintDoc(*doc, " | "); + } + auto field_doc = nlohmann::json::object(); + auto field_doc_it = rdesc.find("field_doc"); + if (field_doc_it != rdesc.end() and field_doc_it->is_object()) { + field_doc = *field_doc_it; + } + auto string_fields = rdesc.find("string_fields"); + if (string_fields != rdesc.end() and (not string_fields->empty())) { + std::cout << " String fields\n"; + PrintFields(*string_fields, field_doc, " - ", " | "); + } + auto target_fields = rdesc.find("target_fields"); + if (target_fields != rdesc.end() and (not target_fields->empty())) { + std::cout << " Target fields\n"; + PrintFields(*target_fields, field_doc, " - ", " | "); + } + auto config_fields = rdesc.find("config_fields"); + if (config_fields != rdesc.end() and (not config_fields->empty())) { + std::cout << " Config fields\n"; + PrintFields(*config_fields, field_doc, " - ", " | "); + } + auto config_doc = nlohmann::json::object(); + auto config_doc_it = rdesc.find("config_doc"); + if (config_doc_it != rdesc.end() and config_doc_it->is_object()) { + config_doc = *config_doc_it; + } + auto config_vars = rdesc.find("config_vars"); + if (config_vars != rdesc.end() and (not config_vars->empty())) { + std::cout << " Variables taken from the configuration\n"; + PrintFields(*config_vars, config_doc, " - ", " | "); + } + std::cout << " Result\n"; + std::cout << " - Artifacts\n"; + auto artifacts_doc = rdesc.find("artifacts_doc"); + if (artifacts_doc != rdesc.end()) { + PrintDoc(*artifacts_doc, " | "); + } + std::cout << " - Runfiles\n"; + auto runfiles_doc = rdesc.find("runfiles_doc"); + if (runfiles_doc != rdesc.end()) { + PrintDoc(*runfiles_doc, " | "); + } + auto provides_doc = rdesc.find("provides_doc"); + if (provides_doc != rdesc.end()) { + std::cout << " - Documented providers\n"; + for (auto& el : provides_doc->items()) { + std::cout << " - " << el.key() << "\n"; + PrintDoc(el.value(), " | "); + } + } + std::cout << std::endl; +} + +// fields relevant for describing a rule +auto const kRuleDescriptionFields = std::vector<std::string>{"config_fields", + "string_fields", + "target_fields", + "config_vars", + "doc", + "field_doc", + "config_doc", + "artifacts_doc", + "runfiles_doc", + "provides_doc"}; + +} // namespace + +auto DescribeUserDefinedRule(BuildMaps::Base::EntityName const& rule_name, + std::size_t jobs, + bool print_json) -> 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()}, + [&rules_file](auto values) { rules_file = *values[0]; }, + [&failed](auto const& msg, bool fatal) { + Logger::Log(fatal ? LogLevel::Error : LogLevel::Warning, + "While searching for rule definition:\n{}", + msg); + failed = failed or fatal; + }); + } + if (failed) { + return kExitFailure; + } + 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()); + return kExitFailure; + } + if (print_json) { + auto json = nlohmann::ordered_json({{"type", rule_name.ToJson()}}); + for (auto const& f : kRuleDescriptionFields) { + if (ruledesc_it->contains(f)) { + json[f] = ruledesc_it->at(f); + } + } + std::cout << json.dump(2) << std::endl; + return kExitSuccess; + } + PrettyPrintRule(*ruledesc_it); + return kExitSuccess; +} + +auto DescribeTarget(BuildMaps::Target::ConfiguredTarget const& id, + std::size_t jobs, + bool print_json) -> 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)) { + if (print_json) { + std::cout << nlohmann::json({{"type", *rule_it}}).dump(2) + << std::endl; + return kExitSuccess; + } + 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; + } + if (not print_json) { + std::cout << id.ToString() << " is defined by user-defined rule " + << rule_name->ToString() << ".\n\n"; + } + return DescribeUserDefinedRule(*rule_name, jobs, print_json); +} diff --git a/src/buildtool/main/describe.hpp b/src/buildtool/main/describe.hpp new file mode 100644 index 00000000..db2de709 --- /dev/null +++ b/src/buildtool/main/describe.hpp @@ -0,0 +1,17 @@ + +#ifndef INCLUDED_SRC_BUILDTOOL_MAIN_DESCRIBE_HPP +#define INCLUDED_SRC_BUILDTOOL_MAIN_DESCRIBE_HPP + +#include "src/buildtool/build_engine/base_maps/entity_name.hpp" +#include "src/buildtool/build_engine/target_map/configured_target.hpp" + +[[nodiscard]] auto DescribeTarget(BuildMaps::Target::ConfiguredTarget const& id, + std::size_t jobs, + bool print_json) -> int; + +[[nodiscard]] auto DescribeUserDefinedRule( + BuildMaps::Base::EntityName const& rule_name, + std::size_t jobs, + bool print_json) -> int; + +#endif // INCLUDED_SRC_BUILDTOOL_MAIN_DESCRIBE_HPP diff --git a/src/buildtool/main/main.hpp b/src/buildtool/main/exit_codes.hpp index 988331e4..69121dd5 100644 --- a/src/buildtool/main/main.hpp +++ b/src/buildtool/main/exit_codes.hpp @@ -1,5 +1,5 @@ -#ifndef INCLUDED_SRC_BUILDTOOL_MAIN_MAIN_HPP -#define INCLUDED_SRC_BUILDTOOL_MAIN_MAIN_HPP +#ifndef INCLUDED_SRC_BUILDTOOL_MAIN_EXIT_CODES_HPP +#define INCLUDED_SRC_BUILDTOOL_MAIN_EXIT_CODES_HPP enum ExitCodes { kExitSuccess = 0, diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp index af4d044f..5f40f698 100644 --- a/src/buildtool/main/main.cpp +++ b/src/buildtool/main/main.cpp @@ -1,5 +1,3 @@ -#include "src/buildtool/main/main.hpp" - #include <algorithm> #include <cstdlib> #include <filesystem> @@ -23,6 +21,8 @@ #include "src/buildtool/common/cli.hpp" #include "src/buildtool/common/repository_config.hpp" #include "src/buildtool/compatibility/compatibility.hpp" +#include "src/buildtool/main/describe.hpp" +#include "src/buildtool/main/exit_codes.hpp" #include "src/buildtool/main/install_cas.hpp" #ifndef BOOTSTRAP_BUILD_TOOL #include "src/buildtool/graph_traverser/graph_traverser.hpp" @@ -1165,30 +1165,6 @@ void ReportTaintedness(const AnalysisResult& result) { Logger::Log(LogLevel::Info, "Target tainted {}.", tainted.dump()); } -void PrintDoc(const nlohmann::json& doc, const std::string& indent) { - if (not doc.is_array()) { - return; - } - for (auto const& line : doc) { - if (line.is_string()) { - std::cout << indent << line.get<std::string>() << "\n"; - } - } -} - -void PrintFields(nlohmann::json const& fields, - const nlohmann::json& fdoc, - const std::string& indent_field, - const std::string& indent_field_doc) { - for (auto const& f : fields) { - std::cout << indent_field << f << "\n"; - auto doc = fdoc.find(f); - if (doc != fdoc.end()) { - PrintDoc(*doc, indent_field_doc); - } - } -} - auto DetermineNonExplicitTarget( std::string const& main_repo, std::optional<std::filesystem::path> const& main_ws_root, @@ -1207,200 +1183,6 @@ auto DetermineNonExplicitTarget( } } -void PrettyPrintRule(nlohmann::json const& rdesc) { - auto doc = rdesc.find("doc"); - if (doc != rdesc.end()) { - PrintDoc(*doc, " | "); - } - auto field_doc = nlohmann::json::object(); - auto field_doc_it = rdesc.find("field_doc"); - if (field_doc_it != rdesc.end() and field_doc_it->is_object()) { - field_doc = *field_doc_it; - } - auto string_fields = rdesc.find("string_fields"); - if (string_fields != rdesc.end() and (not string_fields->empty())) { - std::cout << " String fields\n"; - PrintFields(*string_fields, field_doc, " - ", " | "); - } - auto target_fields = rdesc.find("target_fields"); - if (target_fields != rdesc.end() and (not target_fields->empty())) { - std::cout << " Target fields\n"; - PrintFields(*target_fields, field_doc, " - ", " | "); - } - auto config_fields = rdesc.find("config_fields"); - if (config_fields != rdesc.end() and (not config_fields->empty())) { - std::cout << " Config fields\n"; - PrintFields(*config_fields, field_doc, " - ", " | "); - } - auto config_doc = nlohmann::json::object(); - auto config_doc_it = rdesc.find("config_doc"); - if (config_doc_it != rdesc.end() and config_doc_it->is_object()) { - config_doc = *config_doc_it; - } - auto config_vars = rdesc.find("config_vars"); - if (config_vars != rdesc.end() and (not config_vars->empty())) { - std::cout << " Variables taken from the configuration\n"; - PrintFields(*config_vars, config_doc, " - ", " | "); - } - std::cout << " Result\n"; - std::cout << " - Artifacts\n"; - auto artifacts_doc = rdesc.find("artifacts_doc"); - if (artifacts_doc != rdesc.end()) { - PrintDoc(*artifacts_doc, " | "); - } - std::cout << " - Runfiles\n"; - auto runfiles_doc = rdesc.find("runfiles_doc"); - if (runfiles_doc != rdesc.end()) { - PrintDoc(*runfiles_doc, " | "); - } - auto provides_doc = rdesc.find("provides_doc"); - if (provides_doc != rdesc.end()) { - std::cout << " - Documented providers\n"; - for (auto& el : provides_doc->items()) { - std::cout << " - " << el.key() << "\n"; - PrintDoc(el.value(), " | "); - } - } - std::cout << std::endl; -} - -// fields relevant for describing a rule -auto const kRuleDescriptionFields = std::vector<std::string>{"config_fields", - "string_fields", - "target_fields", - "config_vars", - "doc", - "field_doc", - "config_doc", - "artifacts_doc", - "runfiles_doc", - "provides_doc"}; - -auto DescribeUserDefinedRule(BuildMaps::Base::EntityName const& rule_name, - std::size_t jobs, - bool print_json) -> 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()}, - [&rules_file](auto values) { rules_file = *values[0]; }, - [&failed](auto const& msg, bool fatal) { - Logger::Log(fatal ? LogLevel::Error : LogLevel::Warning, - "While searching for rule definition:\n{}", - msg); - failed = failed or fatal; - }); - } - if (failed) { - return kExitFailure; - } - 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()); - return kExitFailure; - } - if (print_json) { - auto json = nlohmann::ordered_json({{"type", rule_name.ToJson()}}); - for (auto const& f : kRuleDescriptionFields) { - if (ruledesc_it->contains(f)) { - json[f] = ruledesc_it->at(f); - } - } - std::cout << json.dump(2) << std::endl; - return kExitSuccess; - } - PrettyPrintRule(*ruledesc_it); - return kExitSuccess; -} - -auto DescribeTarget(BuildMaps::Target::ConfiguredTarget const& id, - std::size_t jobs, - bool print_json) -> 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)) { - if (print_json) { - std::cout << nlohmann::json({{"type", *rule_it}}).dump(2) - << std::endl; - return kExitSuccess; - } - 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; - } - if (not print_json) { - std::cout << id.ToString() << " is defined by user-defined rule " - << rule_name->ToString() << ".\n\n"; - } - return DescribeUserDefinedRule(*rule_name, jobs, print_json); -} - void DumpArtifactsToBuild( std::map<std::string, ArtifactDescription> const& artifacts, std::map<std::string, ArtifactDescription> const& runfiles, |