diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2023-08-23 14:29:33 +0200 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2023-08-23 16:01:52 +0200 |
commit | 62e9192e9b5d2164596d7dfaa21be37f223da92f (patch) | |
tree | a1641fb291c609aedef8c3569e02780c1ebc2cc6 /src/buildtool/main/main.cpp | |
parent | 9fab20246c23193b1a68387cf0b5f63236639a58 (diff) | |
download | justbuild-62e9192e9b5d2164596d7dfaa21be37f223da92f.tar.gz |
just: split main code
... by moving the diagnose and cli related code into to separate
libraries. In this way, we hopefully improve maintainability of
the code base.
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>, |