diff options
Diffstat (limited to 'src/buildtool/main/main.cpp')
-rw-r--r-- | src/buildtool/main/main.cpp | 513 |
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>, |