diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/common/cli.hpp | 19 | ||||
-rw-r--r-- | src/buildtool/execution_api/remote/config.hpp | 118 | ||||
-rw-r--r-- | src/buildtool/graph_traverser/graph_traverser.hpp | 39 | ||||
-rw-r--r-- | src/buildtool/main/main.cpp | 37 |
4 files changed, 133 insertions, 80 deletions
diff --git a/src/buildtool/common/cli.hpp b/src/buildtool/common/cli.hpp index ab4a7ff1..adfa3445 100644 --- a/src/buildtool/common/cli.hpp +++ b/src/buildtool/common/cli.hpp @@ -62,7 +62,7 @@ struct EndpointArguments { /// \brief Arguments required for building. struct BuildArguments { std::optional<std::vector<std::string>> local_launcher{std::nullopt}; - std::map<std::string, std::string> platform_properties; + std::vector<std::string> platform_properties; std::chrono::milliseconds timeout{kDefaultTimeout}; std::size_t build_jobs{}; std::optional<std::string> dump_artifacts{std::nullopt}; @@ -262,25 +262,14 @@ static inline auto SetupBuildArguments( ->type_name("JSON") ->default_val(nlohmann::json{"env", "--"}.dump()); - app->add_option_function<std::string>( + app->add_option( "--remote-execution-property", - [clargs](auto const& property) { - std::istringstream pss(property); - std::string key; - std::string val; - if (not std::getline(pss, key, ':') or - not std::getline(pss, val, ':')) { - throw CLI::ConversionError{property, - "--remote-execution-property"}; - } - clargs->platform_properties[std::move(key)] = std::move(val); - }, + clargs->platform_properties, "Property for remote execution as key-value pair. Specifying this " "option multiple times will accumulate pairs (latest wins).") ->type_name("KEY:VAL") ->allow_extra_args(false) - ->expected(1, 1) - ->trigger_on_parse(true); // call this everytime the option is parsed + ->expected(1, 1); app->add_option_function<unsigned int>( "--action-timeout", diff --git a/src/buildtool/execution_api/remote/config.hpp b/src/buildtool/execution_api/remote/config.hpp index e29b8aa7..14995b89 100644 --- a/src/buildtool/execution_api/remote/config.hpp +++ b/src/buildtool/execution_api/remote/config.hpp @@ -15,8 +15,72 @@ class RemoteExecutionConfig { public: + struct ServerAddress { + std::string host{}; + int port{}; + }; + + // Obtain global instance + [[nodiscard]] static auto Instance() noexcept -> RemoteExecutionConfig& { + static RemoteExecutionConfig config; + return config; + } + + // Set remote execution and cache address, unsets if parsing `address` fails + [[nodiscard]] static auto SetRemoteAddress( + std::string const& address) noexcept -> bool { + auto& inst = Instance(); + return static_cast<bool>(inst.remote_address_ = inst.cache_address_ = + ParseAddress(address)); + } + + // Set specific cache address, unsets if parsing `address` fails + [[nodiscard]] static auto SetCacheAddress( + std::string const& address) noexcept -> bool { + return static_cast<bool>(Instance().cache_address_ = + ParseAddress(address)); + } + + // Add platform property from string of form "key:val" + [[nodiscard]] static auto AddPlatformProperty( + std::string const& property) noexcept -> bool { + if (auto pair = ParseProperty(property)) { + Instance().platform_properties_[std::move(pair->first)] = + std::move(pair->second); + return true; + } + return false; + } + + // Remote execution address, if set + [[nodiscard]] static auto RemoteAddress() noexcept + -> std::optional<ServerAddress> { + return Instance().remote_address_; + } + + // Cache address, if set + [[nodiscard]] static auto CacheAddress() noexcept + -> std::optional<ServerAddress> { + return Instance().cache_address_; + } + + [[nodiscard]] static auto PlatformProperties() noexcept + -> std::map<std::string, std::string> { + return Instance().platform_properties_; + } + + private: + // Server address of remote execution. + std::optional<ServerAddress> remote_address_{}; + + // Server address of cache endpoint for rebuild. + std::optional<ServerAddress> cache_address_{}; + + // Platform properies for execution. + std::map<std::string, std::string> platform_properties_{}; + [[nodiscard]] static auto ParseAddress(std::string const& address) noexcept - -> std::optional<std::pair<std::string, int>> { + -> std::optional<ServerAddress> { std::istringstream iss(address); std::string host; std::string port; @@ -25,48 +89,34 @@ class RemoteExecutionConfig { return std::nullopt; } try { - return std::make_pair(host, std::stoi(port)); + static constexpr int kMaxPortNumber{ + std::numeric_limits<uint16_t>::max()}; + auto port_num = std::stoi(port); + if (not host.empty() and port_num >= 0 and + port_num <= kMaxPortNumber) { + return ServerAddress{std::move(host), port_num}; + } } catch (std::out_of_range const& e) { Logger::Log(LogLevel::Error, "Port raised out_of_range exception."); - return std::nullopt; } catch (std::invalid_argument const& e) { Logger::Log(LogLevel::Error, "Port raised invalid_argument exception."); - return std::nullopt; } + return std::nullopt; } - // Obtain global instance - [[nodiscard]] static auto Instance() noexcept -> RemoteExecutionConfig& { - static RemoteExecutionConfig config; - return config; - } - - [[nodiscard]] auto IsValidAddress() const noexcept -> bool { - return valid_; - } - - [[nodiscard]] auto SetAddress(std::string const& address) noexcept -> bool { - auto pair = ParseAddress(address); - return pair and SetAddress(pair->first, pair->second); - } - - [[nodiscard]] auto SetAddress(std::string const& host, int port) noexcept - -> bool { - host_ = host; - port_ = port, - valid_ = (not host.empty() and port >= 0 and port <= kMaxPortNumber); - return valid_; + [[nodiscard]] static auto ParseProperty( + std::string const& property) noexcept + -> std::optional<std::pair<std::string, std::string>> { + std::istringstream pss(property); + std::string key; + std::string val; + if (not std::getline(pss, key, ':') or + not std::getline(pss, val, ':')) { + return std::nullopt; + } + return std::make_pair(key, val); } - - [[nodiscard]] auto Host() const noexcept -> std::string { return host_; } - [[nodiscard]] auto Port() const noexcept -> int { return port_; } - - private: - static constexpr int kMaxPortNumber{std::numeric_limits<uint16_t>::max()}; - std::string host_{}; - int port_{}; - bool valid_{false}; }; #endif // INCLUDED_SRC_BUILDTOOL_EXECUTION_API_REMOTE_CONFIG_HPP diff --git a/src/buildtool/graph_traverser/graph_traverser.hpp b/src/buildtool/graph_traverser/graph_traverser.hpp index 5169e61e..53e5eb20 100644 --- a/src/buildtool/graph_traverser/graph_traverser.hpp +++ b/src/buildtool/graph_traverser/graph_traverser.hpp @@ -36,7 +36,6 @@ class GraphTraverser { public: struct CommandLineArguments { std::size_t jobs; - EndpointArguments endpoint; BuildArguments build; std::optional<StageArguments> stage; std::optional<RebuildArguments> rebuild; @@ -50,13 +49,13 @@ class GraphTraverser { explicit GraphTraverser(CommandLineArguments clargs) : clargs_{std::move(clargs)}, - api_{CreateExecutionApi(clargs_.endpoint)}, + api_{CreateExecutionApi(RemoteExecutionConfig::RemoteAddress())}, reporter_{[](auto done, auto cv) {}} {} explicit GraphTraverser(CommandLineArguments clargs, progress_reporter_t reporter) : clargs_{std::move(clargs)}, - api_{CreateExecutionApi(clargs_.endpoint)}, + api_{CreateExecutionApi(RemoteExecutionConfig::RemoteAddress())}, reporter_{std::move(reporter)} {} /// \brief Parses actions and blobs into graph, traverses it and retrieves @@ -214,21 +213,14 @@ class GraphTraverser { } [[nodiscard]] static auto CreateExecutionApi( - EndpointArguments const& clargs) -> gsl::not_null<IExecutionApi::Ptr> { - if (clargs.remote_execution_address) { - auto remote = RemoteExecutionConfig{}; - if (not remote.SetAddress(*clargs.remote_execution_address)) { - Logger::Log(LogLevel::Error, - "parsing remote execution address '{}' failed.", - *clargs.remote_execution_address); - std::exit(EXIT_FAILURE); - } - + std::optional<RemoteExecutionConfig::ServerAddress> const& address) + -> gsl::not_null<IExecutionApi::Ptr> { + if (address) { ExecutionConfiguration config; config.skip_cache_lookup = false; return std::make_unique<BazelApi>( - "remote-execution", remote.Host(), remote.Port(), config); + "remote-execution", address->host, address->port, config); } return std::make_unique<LocalApi>(); } @@ -299,8 +291,9 @@ class GraphTraverser { [[nodiscard]] auto Traverse( DependencyGraph const& g, std::vector<ArtifactIdentifier> const& artifact_ids) const -> bool { - Executor executor{ - &(*api_), clargs_.build.platform_properties, clargs_.build.timeout}; + Executor executor{&(*api_), + RemoteExecutionConfig::PlatformProperties(), + clargs_.build.timeout}; bool result{}; std::atomic<bool> done = false; std::condition_variable cv{}; @@ -320,20 +313,12 @@ class GraphTraverser { [[nodiscard]] auto TraverseRebuild( DependencyGraph const& g, std::vector<ArtifactIdentifier> const& artifact_ids) const -> bool { - // create second configuration for cache endpoint - auto cache_args = clargs_.endpoint; - if (not clargs_.rebuild->cache_endpoint.value_or("").empty()) { - cache_args.remote_execution_address = - *clargs_.rebuild->cache_endpoint == "local" - ? std::nullopt // disable - : clargs_.rebuild->cache_endpoint; // set endpoint - } - // setup rebuilder with api for cache endpoint - auto api_cached = CreateExecutionApi(cache_args); + auto api_cached = + CreateExecutionApi(RemoteExecutionConfig::CacheAddress()); Rebuilder executor{&(*api_), &(*api_cached), - clargs_.build.platform_properties, + RemoteExecutionConfig::PlatformProperties(), clargs_.build.timeout}; bool success{false}; { diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp index b41d7a11..23ea7b8e 100644 --- a/src/buildtool/main/main.cpp +++ b/src/buildtool/main/main.cpp @@ -205,15 +205,44 @@ void SetupLogging(CommonArguments const& clargs) { } #ifndef BOOTSTRAP_BUILD_TOOL -void SetupLocalExecution(EndpointArguments const& eargs, - BuildArguments const& bargs) { +void SetupExecutionConfig(EndpointArguments const& eargs, + BuildArguments const& bargs, + RebuildArguments const& rargs) { using LocalConfig = LocalExecutionConfig; + using RemoteConfig = RemoteExecutionConfig; if (not LocalConfig::SetKeepBuildDir(bargs.persistent_build_dir) or not(not eargs.local_root or (LocalConfig::SetBuildRoot(*eargs.local_root))) or not(not bargs.local_launcher or LocalConfig::SetLauncher(*bargs.local_launcher))) { Logger::Log(LogLevel::Error, "failed to configure local execution."); + std::exit(kExitFailure); + } + for (auto const& property : bargs.platform_properties) { + if (not RemoteConfig::AddPlatformProperty(property)) { + Logger::Log(LogLevel::Error, + "addding platform property '{}' failed.", + property); + std::exit(kExitFailure); + } + } + if (eargs.remote_execution_address) { + if (not RemoteConfig::SetRemoteAddress( + *eargs.remote_execution_address)) { + Logger::Log(LogLevel::Error, + "setting remote execution address '{}' failed.", + *eargs.remote_execution_address); + std::exit(kExitFailure); + } + } + if (rargs.cache_endpoint) { + if (not(RemoteConfig::SetCacheAddress(*rargs.cache_endpoint) == + (*rargs.cache_endpoint != "local"))) { + Logger::Log(LogLevel::Error, + "setting cache endpoint address '{}' failed.", + *rargs.cache_endpoint); + std::exit(kExitFailure); + } } } @@ -1251,7 +1280,8 @@ auto main(int argc, char* argv[]) -> int { SetupLogging(arguments.common); #ifndef BOOTSTRAP_BUILD_TOOL SetupHashGenerator(); - SetupLocalExecution(arguments.endpoint, arguments.build); + SetupExecutionConfig( + arguments.endpoint, arguments.build, arguments.rebuild); #endif auto jobs = arguments.build.build_jobs > 0 ? arguments.build.build_jobs @@ -1270,7 +1300,6 @@ auto main(int argc, char* argv[]) -> int { #ifndef BOOTSTRAP_BUILD_TOOL GraphTraverser const traverser{{jobs, - std::move(arguments.endpoint), std::move(arguments.build), std::move(stage_args), std::move(rebuild_args)}, |