summaryrefslogtreecommitdiff
path: root/src/buildtool/main/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildtool/main/main.cpp')
-rw-r--r--src/buildtool/main/main.cpp513
1 files changed, 2 insertions, 511 deletions
diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp
index 8d2d4d2e..e362b7ef 100644
--- a/src/buildtool/main/main.cpp
+++ b/src/buildtool/main/main.cpp
@@ -26,13 +26,14 @@
#include "src/buildtool/build_engine/expression/expression.hpp"
#include "src/buildtool/build_engine/target_map/target_map.hpp"
#include "src/buildtool/common/artifact_description.hpp"
-#include "src/buildtool/common/cli.hpp"
#include "src/buildtool/common/repository_config.hpp"
#include "src/buildtool/compatibility/compatibility.hpp"
#include "src/buildtool/execution_api/local/config.hpp"
#include "src/buildtool/main/analyse.hpp"
+#include "src/buildtool/main/cli.hpp"
#include "src/buildtool/main/constants.hpp"
#include "src/buildtool/main/describe.hpp"
+#include "src/buildtool/main/diagnose.hpp"
#include "src/buildtool/main/exit_codes.hpp"
#include "src/buildtool/main/install_cas.hpp"
#include "src/buildtool/storage/config.hpp"
@@ -63,226 +64,6 @@ namespace {
namespace Base = BuildMaps::Base;
namespace Target = BuildMaps::Target;
-enum class SubCommand {
- kUnknown,
- kVersion,
- kDescribe,
- kAnalyse,
- kBuild,
- kInstall,
- kRebuild,
- kInstallCas,
- kTraverse,
- kGc,
- kExecute
-};
-
-struct CommandLineArguments {
- SubCommand cmd{SubCommand::kUnknown};
- CommonArguments common;
- LogArguments log;
- AnalysisArguments analysis;
- DescribeArguments describe;
- DiagnosticArguments diagnose;
- EndpointArguments endpoint;
- BuildArguments build;
- StageArguments stage;
- RebuildArguments rebuild;
- FetchArguments fetch;
- GraphArguments graph;
- CommonAuthArguments auth;
- ClientAuthArguments cauth;
- ServerAuthArguments sauth;
- ExecutionServiceArguments es;
-};
-
-/// \brief Setup arguments for sub command "just describe".
-auto SetupDescribeCommandArguments(
- gsl::not_null<CLI::App*> const& app,
- gsl::not_null<CommandLineArguments*> const& clargs) {
- 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".
-auto SetupAnalyseCommandArguments(
- gsl::not_null<CLI::App*> const& app,
- gsl::not_null<CommandLineArguments*> const& clargs) {
- SetupCommonArguments(app, &clargs->common);
- SetupLogArguments(app, &clargs->log);
- SetupAnalysisArguments(app, &clargs->analysis);
- SetupCacheArguments(app, &clargs->endpoint);
- SetupEndpointArguments(app, &clargs->endpoint);
- SetupDiagnosticArguments(app, &clargs->diagnose);
- SetupCompatibilityArguments(app);
-}
-
-/// \brief Setup arguments for sub command "just build".
-auto SetupBuildCommandArguments(
- gsl::not_null<CLI::App*> const& app,
- gsl::not_null<CommandLineArguments*> const& clargs) {
- SetupCommonArguments(app, &clargs->common);
- SetupLogArguments(app, &clargs->log);
- SetupAnalysisArguments(app, &clargs->analysis);
- SetupCacheArguments(app, &clargs->endpoint);
- SetupEndpointArguments(app, &clargs->endpoint);
- SetupCommonAuthArguments(app, &clargs->auth);
- SetupClientAuthArguments(app, &clargs->cauth);
- SetupCommonBuildArguments(app, &clargs->build);
- SetupBuildArguments(app, &clargs->build);
- SetupCompatibilityArguments(app);
-}
-
-/// \brief Setup arguments for sub command "just install".
-auto SetupInstallCommandArguments(
- gsl::not_null<CLI::App*> const& app,
- gsl::not_null<CommandLineArguments*> const& clargs) {
- SetupBuildCommandArguments(app, clargs); // same as build
- SetupStageArguments(app, &clargs->stage); // plus stage
-}
-
-/// \brief Setup arguments for sub command "just rebuild".
-auto SetupRebuildCommandArguments(
- gsl::not_null<CLI::App*> const& app,
- gsl::not_null<CommandLineArguments*> const& clargs) {
- SetupBuildCommandArguments(app, clargs); // same as build
- SetupRebuildArguments(app, &clargs->rebuild); // plus rebuild
-}
-
-/// \brief Setup arguments for sub command "just install-cas".
-auto SetupInstallCasCommandArguments(
- gsl::not_null<CLI::App*> const& app,
- gsl::not_null<CommandLineArguments*> const& clargs) {
- SetupCompatibilityArguments(app);
- SetupCacheArguments(app, &clargs->endpoint);
- SetupEndpointArguments(app, &clargs->endpoint);
- SetupCommonAuthArguments(app, &clargs->auth);
- SetupClientAuthArguments(app, &clargs->cauth);
- SetupFetchArguments(app, &clargs->fetch);
- SetupLogArguments(app, &clargs->log);
-}
-
-/// \brief Setup arguments for sub command "just traverse".
-auto SetupTraverseCommandArguments(
- gsl::not_null<CLI::App*> const& app,
- gsl::not_null<CommandLineArguments*> const& clargs) {
- SetupCommonArguments(app, &clargs->common);
- SetupLogArguments(app, &clargs->log);
- SetupCacheArguments(app, &clargs->endpoint);
- SetupEndpointArguments(app, &clargs->endpoint);
- SetupCommonAuthArguments(app, &clargs->auth);
- SetupClientAuthArguments(app, &clargs->cauth);
- SetupGraphArguments(app, &clargs->graph); // instead of analysis
- SetupCommonBuildArguments(app, &clargs->build);
- SetupBuildArguments(app, &clargs->build);
- SetupStageArguments(app, &clargs->stage);
- SetupCompatibilityArguments(app);
-}
-
-/// \brief Setup arguments for sub command "just gc".
-auto SetupGcCommandArguments(
- gsl::not_null<CLI::App*> const& app,
- gsl::not_null<CommandLineArguments*> const& clargs) {
- SetupLogArguments(app, &clargs->log);
- SetupCacheArguments(app, &clargs->endpoint);
-}
-
-/// \brief Setup arguments for sub command "just execute".
-auto SetupExecutionServiceCommandArguments(
- gsl::not_null<CLI::App*> const& app,
- gsl::not_null<CommandLineArguments*> const& clargs) {
- SetupCompatibilityArguments(app);
- SetupCommonBuildArguments(app, &clargs->build);
- SetupCacheArguments(app, &clargs->endpoint);
- SetupExecutionServiceArguments(app, &clargs->es);
- SetupLogArguments(app, &clargs->log);
- SetupCommonAuthArguments(app, &clargs->auth);
- SetupServerAuthArguments(app, &clargs->sauth);
-}
-
-auto ParseCommandLineArguments(int argc, char const* const* argv)
- -> CommandLineArguments {
- CLI::App app("just, a generic build tool");
- app.option_defaults()->take_last();
-
- auto* cmd_version = app.add_subcommand(
- "version", "Print version information in JSON format.");
- auto* cmd_describe = app.add_subcommand(
- "describe", "Describe the rule generating a target.");
- auto* cmd_analyse =
- app.add_subcommand("analyse", "Analyse specified targets.");
- auto* cmd_build = app.add_subcommand("build", "Build specified targets.");
- auto* cmd_install =
- app.add_subcommand("install", "Build and stage specified targets.");
- auto* cmd_rebuild = app.add_subcommand(
- "rebuild", "Rebuild and compare artifacts to cached build.");
- auto* cmd_install_cas =
- app.add_subcommand("install-cas", "Fetch and stage artifact from CAS.");
- auto* cmd_gc =
- app.add_subcommand("gc", "Trigger garbage collection of local cache.");
- auto* cmd_execution = app.add_subcommand(
- "execute", "Start single node execution service on this machine.");
- auto* cmd_traverse =
- app.group("") // group for creating hidden options
- ->add_subcommand("traverse",
- "Build and stage artifacts from graph file.");
- app.require_subcommand(1);
-
- CommandLineArguments clargs;
- SetupDescribeCommandArguments(cmd_describe, &clargs);
- SetupAnalyseCommandArguments(cmd_analyse, &clargs);
- SetupBuildCommandArguments(cmd_build, &clargs);
- SetupInstallCommandArguments(cmd_install, &clargs);
- SetupRebuildCommandArguments(cmd_rebuild, &clargs);
- SetupInstallCasCommandArguments(cmd_install_cas, &clargs);
- SetupTraverseCommandArguments(cmd_traverse, &clargs);
- SetupGcCommandArguments(cmd_gc, &clargs);
- SetupExecutionServiceCommandArguments(cmd_execution, &clargs);
- try {
- app.parse(argc, argv);
- } catch (CLI::Error& e) {
- std::exit(app.exit(e));
- } catch (std::exception const& ex) {
- Logger::Log(LogLevel::Error, "Command line parse error: {}", ex.what());
- std::exit(kExitFailure);
- }
-
- if (*cmd_version) {
- clargs.cmd = SubCommand::kVersion;
- }
- else if (*cmd_describe) {
- clargs.cmd = SubCommand::kDescribe;
- }
- else if (*cmd_analyse) {
- clargs.cmd = SubCommand::kAnalyse;
- }
- else if (*cmd_build) {
- clargs.cmd = SubCommand::kBuild;
- }
- else if (*cmd_install) {
- clargs.cmd = SubCommand::kInstall;
- }
- else if (*cmd_rebuild) {
- clargs.cmd = SubCommand::kRebuild;
- }
- else if (*cmd_install_cas) {
- clargs.cmd = SubCommand::kInstallCas;
- }
- else if (*cmd_traverse) {
- clargs.cmd = SubCommand::kTraverse;
- }
- else if (*cmd_gc) {
- clargs.cmd = SubCommand::kGc;
- }
- else if (*cmd_execution) {
- clargs.cmd = SubCommand::kExecute;
- }
-
- return clargs;
-}
-
void SetupDefaultLogging() {
LogConfig::SetLogLimit(kDefaultLogLevel);
LogConfig::SetSinks({LogSinkCmdLine::CreateFactory()});
@@ -911,296 +692,6 @@ auto DetermineRoots(CommonArguments const& cargs,
return {main_repo, main_ws_root};
}
-[[nodiscard]] auto ResultToJson(TargetResult const& result) -> nlohmann::json {
- return nlohmann::ordered_json{
- {"artifacts",
- result.artifact_stage->ToJson(
- Expression::JsonMode::SerializeAllButNodes)},
- {"runfiles",
- result.runfiles->ToJson(Expression::JsonMode::SerializeAllButNodes)},
- {"provides",
- result.provides->ToJson(Expression::JsonMode::SerializeAllButNodes)}};
-}
-
-[[nodiscard]] auto TargetActionsToJson(AnalysedTargetPtr const& target)
- -> nlohmann::json {
- auto actions = nlohmann::json::array();
- std::for_each(target->Actions().begin(),
- target->Actions().end(),
- [&actions](auto const& action) {
- actions.push_back(action->ToJson());
- });
- return actions;
-}
-
-[[nodiscard]] auto TreesToJson(AnalysedTargetPtr const& target)
- -> nlohmann::json {
- auto trees = nlohmann::json::object();
- std::for_each(
- target->Trees().begin(),
- target->Trees().end(),
- [&trees](auto const& tree) { trees[tree->Id()] = tree->ToJson(); });
-
- return trees;
-}
-
-void DumpActions(std::string const& file_path, AnalysisResult const& result) {
- auto const dump_string =
- IndentListsOnlyUntilDepth(TargetActionsToJson(result.target), 2, 1);
- if (file_path == "-") {
- Logger::Log(
- LogLevel::Info, "Actions for target {}:", result.id.ToString());
- std::cout << dump_string << std::endl;
- }
- else {
- Logger::Log(LogLevel::Info,
- "Dumping actions for target {} to file '{}'.",
- result.id.ToString(),
- file_path);
- std::ofstream os(file_path);
- os << dump_string << std::endl;
- }
-}
-
-void DumpBlobs(std::string const& file_path, AnalysisResult const& result) {
- auto blobs = nlohmann::json::array();
- for (auto const& s : result.target->Blobs()) {
- blobs.push_back(s);
- }
- auto const dump_string = blobs.dump(2);
- if (file_path == "-") {
- Logger::Log(
- LogLevel::Info, "Blobs for target {}:", result.id.ToString());
- std::cout << dump_string << std::endl;
- }
- else {
- Logger::Log(LogLevel::Info,
- "Dumping blobs for target {} to file '{}'.",
- result.id.ToString(),
- file_path);
- std::ofstream os(file_path);
- os << dump_string << std::endl;
- }
-}
-
-void DumpVars(std::string const& file_path, AnalysisResult const& result) {
- auto vars = std::vector<std::string>{};
- vars.reserve(result.target->Vars().size());
- for (auto const& x : result.target->Vars()) {
- vars.push_back(x);
- }
- std::sort(vars.begin(), vars.end());
- auto const dump_string = nlohmann::json(vars).dump();
- if (file_path == "-") {
- Logger::Log(
- LogLevel::Info, "Variables for target {}:", result.id.ToString());
- std::cout << dump_string << std::endl;
- }
- else {
- Logger::Log(LogLevel::Info,
- "Dumping varables for target {} to file '{}'.",
- result.id.ToString(),
- file_path);
- std::ofstream os(file_path);
- os << dump_string << std::endl;
- }
-}
-
-void DumpTrees(std::string const& file_path, AnalysisResult const& result) {
- auto const dump_string = TreesToJson(result.target).dump(2);
- if (file_path == "-") {
- Logger::Log(
- LogLevel::Info, "Trees for target {}:", result.id.ToString());
- std::cout << dump_string << std::endl;
- }
- else {
- Logger::Log(LogLevel::Info,
- "Dumping trees for target {} to file '{}'.",
- result.id.ToString(),
- file_path);
- std::ofstream os(file_path);
- os << dump_string << std::endl;
- }
-}
-
-void DumpTargets(std::string const& file_path,
- std::vector<Target::ConfiguredTarget> const& target_ids,
- std::string const& target_qualifier = "") {
- auto repo_map = nlohmann::json::object();
- auto conf_list =
- [&repo_map](Base::EntityName const& ref) -> nlohmann::json& {
- if (ref.IsAnonymousTarget()) {
- auto const& anon = ref.GetAnonymousTarget();
- auto& anon_map = repo_map[Base::EntityName::kAnonymousMarker];
- auto& rule_map = anon_map[anon.rule_map.ToIdentifier()];
- return rule_map[anon.target_node.ToIdentifier()];
- }
- auto const& named = ref.GetNamedTarget();
- auto& location_map = repo_map[Base::EntityName::kLocationMarker];
- auto& module_map = location_map[named.repository];
- auto& target_map = module_map[named.module];
- return target_map[named.name];
- };
- std::for_each(
- target_ids.begin(), target_ids.end(), [&conf_list](auto const& id) {
- if ((not id.target.IsNamedTarget()) or
- id.target.GetNamedTarget().reference_t ==
- BuildMaps::Base::ReferenceType::kTarget) {
- conf_list(id.target).push_back(id.config.ToJson());
- }
- });
- auto const dump_string = IndentListsOnlyUntilDepth(repo_map, 2);
- if (file_path == "-") {
- Logger::Log(
- LogLevel::Info, "List of analysed {}targets:", target_qualifier);
- std::cout << dump_string << std::endl;
- }
- else {
- Logger::Log(LogLevel::Info,
- "Dumping list of analysed {}targets to file '{}'.",
- target_qualifier,
- file_path);
- std::ofstream os(file_path);
- os << dump_string << std::endl;
- }
-}
-
-auto DumpExpressionToMap(gsl::not_null<nlohmann::json*> const& map,
- ExpressionPtr const& expr) -> bool {
- auto const& id = expr->ToIdentifier();
- if (not map->contains(id)) {
- (*map)[id] = expr->ToJson();
- return true;
- }
- return false;
-}
-
-// NOLINTNEXTLINE(misc-no-recursion)
-void DumpNodesInExpressionToMap(gsl::not_null<nlohmann::json*> const& map,
- ExpressionPtr const& expr) {
- if (expr->IsNode()) {
- if (DumpExpressionToMap(map, expr)) {
- auto const& node = expr->Node();
- if (node.IsAbstract()) {
- DumpNodesInExpressionToMap(map,
- node.GetAbstract().target_fields);
- }
- else if (node.IsValue()) {
- DumpNodesInExpressionToMap(map, node.GetValue());
- }
- }
- }
- else if (expr->IsList()) {
- for (auto const& entry : expr->List()) {
- DumpNodesInExpressionToMap(map, entry);
- }
- }
- else if (expr->IsMap()) {
- for (auto const& [_, value] : expr->Map()) {
- DumpNodesInExpressionToMap(map, value);
- }
- }
- else if (expr->IsResult()) {
- DumpNodesInExpressionToMap(map, expr->Result().provides);
- }
-}
-
-void DumpAnonymous(std::string const& file_path,
- std::vector<Target::ConfiguredTarget> const& target_ids) {
- auto anon_map = nlohmann::json{{"nodes", nlohmann::json::object()},
- {"rule_maps", nlohmann::json::object()}};
- std::for_each(
- target_ids.begin(), target_ids.end(), [&anon_map](auto const& id) {
- if (id.target.IsAnonymousTarget()) {
- auto const& anon_t = id.target.GetAnonymousTarget();
- DumpExpressionToMap(&anon_map["rule_maps"], anon_t.rule_map);
- DumpNodesInExpressionToMap(&anon_map["nodes"],
- anon_t.target_node);
- }
- });
- auto const dump_string = IndentListsOnlyUntilDepth(anon_map, 2);
- if (file_path == "-") {
- Logger::Log(LogLevel::Info, "List of anonymous target data:");
- std::cout << dump_string << std::endl;
- }
- else {
- Logger::Log(LogLevel::Info,
- "Dumping list of anonymous target data to file '{}'.",
- file_path);
- std::ofstream os(file_path);
- os << dump_string << std::endl;
- }
-}
-
-void DumpNodes(std::string const& file_path, AnalysisResult const& result) {
- auto node_map = nlohmann::json::object();
- DumpNodesInExpressionToMap(&node_map, result.target->Provides());
- auto const dump_string = IndentListsOnlyUntilDepth(node_map, 2);
- if (file_path == "-") {
- Logger::Log(
- LogLevel::Info, "Target nodes of target {}:", result.id.ToString());
- std::cout << dump_string << std::endl;
- }
- else {
- Logger::Log(LogLevel::Info,
- "Dumping target nodes of target {} to file '{}'.",
- result.id.ToString(),
- file_path);
- std::ofstream os(file_path);
- os << dump_string << std::endl;
- }
-}
-
-[[nodiscard]] auto DiagnoseResults(AnalysisResult const& result,
- Target::ResultTargetMap const& result_map,
- DiagnosticArguments const& clargs) {
- Logger::Log(
- LogLevel::Info,
- "Result of{} target {}: {}",
- result.modified
- ? fmt::format(" input of action {} of", *result.modified)
- : "",
- result.id.ToString(),
- IndentOnlyUntilDepth(
- ResultToJson(result.target->Result()),
- 2,
- 2,
- std::unordered_map<std::string, std::size_t>{{"/provides", 3}}));
- if (clargs.dump_actions) {
- DumpActions(*clargs.dump_actions, result);
- }
- if (clargs.dump_blobs) {
- DumpBlobs(*clargs.dump_blobs, result);
- }
- if (clargs.dump_trees) {
- DumpTrees(*clargs.dump_trees, result);
- }
- if (clargs.dump_vars) {
- DumpVars(*clargs.dump_vars, result);
- }
- if (clargs.dump_targets) {
- DumpTargets(*clargs.dump_targets, result_map.ConfiguredTargets());
- }
- if (clargs.dump_export_targets) {
- DumpTargets(
- *clargs.dump_export_targets, result_map.ExportTargets(), "export ");
- }
- if (clargs.dump_targets_graph) {
- auto graph = result_map.ConfiguredTargetsGraph().dump(2);
- Logger::Log(LogLevel::Info,
- "Dumping graph of configured-targets to file {}.",
- *clargs.dump_targets_graph);
- std::ofstream os(*clargs.dump_targets_graph);
- os << graph << std::endl;
- }
- if (clargs.dump_anonymous) {
- DumpAnonymous(*clargs.dump_anonymous, result_map.ConfiguredTargets());
- }
- if (clargs.dump_nodes) {
- DumpNodes(*clargs.dump_nodes, result);
- }
-}
-
// Return disjoint maps for artifacts and runfiles
[[nodiscard]] auto ReadOutputArtifacts(AnalysedTargetPtr const& target)
-> std::pair<std::map<std::string, ArtifactDescription>,