summaryrefslogtreecommitdiff
path: root/src/buildtool/common/action_description.hpp
diff options
context:
space:
mode:
authorKlaus Aehlig <klaus.aehlig@huawei.com>2022-02-22 17:03:21 +0100
committerKlaus Aehlig <klaus.aehlig@huawei.com>2022-02-22 17:03:21 +0100
commit619def44c1cca9f3cdf63544d5f24f2c7a7d9b77 (patch)
tree01868de723cb82c86842f33743fa7b14e24c1fa3 /src/buildtool/common/action_description.hpp
downloadjustbuild-619def44c1cca9f3cdf63544d5f24f2c7a7d9b77.tar.gz
Initial self-hosting commit
This is the initial version of our tool that is able to build itself. In can be bootstrapped by ./bin/bootstrap.py Co-authored-by: Oliver Reiche <oliver.reiche@huawei.com> Co-authored-by: Victor Moreno <victor.moreno1@huawei.com>
Diffstat (limited to 'src/buildtool/common/action_description.hpp')
-rw-r--r--src/buildtool/common/action_description.hpp200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/buildtool/common/action_description.hpp b/src/buildtool/common/action_description.hpp
new file mode 100644
index 00000000..9b3469c1
--- /dev/null
+++ b/src/buildtool/common/action_description.hpp
@@ -0,0 +1,200 @@
+#ifndef INCLUDED_SRC_BUILDTOOL_COMMON_ACTION_DESCRIPTION_HPP
+#define INCLUDED_SRC_BUILDTOOL_COMMON_ACTION_DESCRIPTION_HPP
+
+#include <map>
+#include <optional>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "nlohmann/json.hpp"
+#include "src/buildtool/common/action.hpp"
+#include "src/buildtool/common/artifact_description.hpp"
+
+class ActionDescription {
+ public:
+ using outputs_t = std::vector<std::string>;
+ using inputs_t = std::unordered_map<std::string, ArtifactDescription>;
+
+ ActionDescription(outputs_t output_files,
+ outputs_t output_dirs,
+ Action action,
+ inputs_t inputs)
+ : output_files_{std::move(output_files)},
+ output_dirs_{std::move(output_dirs)},
+ action_{std::move(action)},
+ inputs_{std::move(inputs)} {}
+
+ [[nodiscard]] static auto FromJson(std::string const& id,
+ nlohmann::json const& desc) noexcept
+ -> std::optional<ActionDescription> {
+ try {
+ auto outputs =
+ ExtractValueAs<std::vector<std::string>>(desc, "output");
+ auto output_dirs =
+ ExtractValueAs<std::vector<std::string>>(desc, "output_dirs");
+ auto command =
+ ExtractValueAs<std::vector<std::string>>(desc, "command");
+
+ if ((not outputs.has_value() or outputs->empty()) and
+ (not output_dirs.has_value() or output_dirs->empty())) {
+ Logger::Log(
+ LogLevel::Error,
+ "Action description for action \"{}\" incomplete: values "
+ "for either \"output\" or \"output_dir\" must be non-empty "
+ "array.",
+ id);
+ return std::nullopt;
+ }
+
+ if (not command.has_value() or command->empty()) {
+ Logger::Log(
+ LogLevel::Error,
+ "Action description for action \"{}\" incomplete: values "
+ "for \"command\" must be non-empty array.",
+ id);
+ return std::nullopt;
+ }
+
+ if (not outputs) {
+ outputs = std::vector<std::string>{};
+ }
+ if (not output_dirs) {
+ output_dirs = std::vector<std::string>{};
+ }
+
+ auto optional_key_value_reader =
+ [](nlohmann::json const& action_desc,
+ std::string const& key) -> nlohmann::json {
+ auto it = action_desc.find(key);
+ if (it == action_desc.end()) {
+ return nlohmann::json::object();
+ }
+ return *it;
+ };
+ auto const input = optional_key_value_reader(desc, "input");
+ auto const env = optional_key_value_reader(desc, "env");
+
+ if (not(input.is_object() and env.is_object())) {
+ Logger::Log(
+ LogLevel::Error,
+ "Action description for action \"{}\" type error: values "
+ "for \"input\" and \"env\" must be objects.",
+ id);
+ return std::nullopt;
+ }
+
+ inputs_t inputs{};
+ for (auto const& [path, input_desc] : input.items()) {
+ auto artifact = ArtifactDescription::FromJson(input_desc);
+ if (not artifact) {
+ return std::nullopt;
+ }
+ inputs.emplace(path, std::move(*artifact));
+ }
+ std::optional<std::string> may_fail{};
+ bool no_cache{};
+ auto may_fail_it = desc.find("may_fail");
+ if (may_fail_it != desc.end()) {
+ if (not may_fail_it->is_string()) {
+ Logger::Log(LogLevel::Error,
+ "may_fail has to be a boolean");
+ return std::nullopt;
+ }
+ may_fail = *may_fail_it;
+ }
+ auto no_cache_it = desc.find("no_cache");
+ if (no_cache_it != desc.end()) {
+ if (not no_cache_it->is_boolean()) {
+ Logger::Log(LogLevel::Error,
+ "no_cache has to be a boolean");
+ return std::nullopt;
+ }
+ no_cache = *no_cache_it;
+ }
+
+ return ActionDescription{
+ std::move(*outputs),
+ std::move(*output_dirs),
+ Action{id, std::move(*command), env, may_fail, no_cache},
+ inputs};
+ } catch (std::exception const& ex) {
+ Logger::Log(
+ LogLevel::Error,
+ "Failed to parse action description from JSON with error:\n{}",
+ ex.what());
+ }
+ return std::nullopt;
+ }
+
+ [[nodiscard]] auto Id() const noexcept -> ActionIdentifier {
+ return action_.Id();
+ }
+
+ [[nodiscard]] auto ToJson() const noexcept -> nlohmann::json {
+ auto json = nlohmann::json{{"command", action_.Command()}};
+ if (not output_files_.empty()) {
+ json["output"] = output_files_;
+ }
+ if (not output_dirs_.empty()) {
+ json["output_dirs"] = output_dirs_;
+ }
+ if (not inputs_.empty()) {
+ auto inputs = nlohmann::json::object();
+ for (auto const& [path, artifact] : inputs_) {
+ inputs[path] = artifact.ToJson();
+ }
+ json["input"] = inputs;
+ }
+ if (not action_.Env().empty()) {
+ json["env"] = action_.Env();
+ }
+ if (action_.MayFail()) {
+ json["may_fail"] = *action_.MayFail();
+ }
+ if (action_.NoCache()) {
+ json["no_cache"] = true;
+ }
+ return json;
+ }
+
+ [[nodiscard]] auto OutputFiles() const& noexcept -> outputs_t const& {
+ return output_files_;
+ }
+
+ [[nodiscard]] auto OutputFiles() && noexcept -> outputs_t {
+ return std::move(output_files_);
+ }
+
+ [[nodiscard]] auto OutputDirs() const& noexcept -> outputs_t const& {
+ return output_dirs_;
+ }
+
+ [[nodiscard]] auto OutputDirs() && noexcept -> outputs_t {
+ return std::move(output_dirs_);
+ }
+
+ [[nodiscard]] auto GraphAction() const& noexcept -> Action const& {
+ return action_;
+ }
+
+ [[nodiscard]] auto GraphAction() && noexcept -> Action {
+ return std::move(action_);
+ }
+
+ [[nodiscard]] auto Inputs() const& noexcept -> inputs_t const& {
+ return inputs_;
+ }
+
+ [[nodiscard]] auto Inputs() && noexcept -> inputs_t {
+ return std::move(inputs_);
+ }
+
+ private:
+ outputs_t output_files_;
+ outputs_t output_dirs_;
+ Action action_;
+ inputs_t inputs_;
+};
+
+#endif // INCLUDED_SRC_BUILDTOOL_COMMON_ACTION_DESCRIPTION_HPP