summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/man/just.1.md4
-rw-r--r--src/buildtool/common/cli.hpp4
-rw-r--r--src/buildtool/main/TARGETS1
-rw-r--r--src/buildtool/main/main.cpp71
-rw-r--r--src/buildtool/profile/TARGETS9
-rw-r--r--src/buildtool/profile/profile.cpp35
-rw-r--r--src/buildtool/profile/profile.hpp40
7 files changed, 149 insertions, 15 deletions
diff --git a/share/man/just.1.md b/share/man/just.1.md
index de59455f..1ace1bd3 100644
--- a/share/man/just.1.md
+++ b/share/man/just.1.md
@@ -434,6 +434,10 @@ type, size) as value. Each artifact is guaranteed to be *`KNOWN`* in
CAS. Therefore, this option cannot be used with **`analyse`**.
Supported by: build|install|rebuild|traverse.
+**`--profile`** *`PATH`*
+Write a profile to the specified path.
+Supported by: analyse|build|install|rebuild|traverse.
+
**`--dump-graph`** *`PATH`*
File path for writing the action graph description to. See
**`just-graph-file`**(5) for more details.
diff --git a/src/buildtool/common/cli.hpp b/src/buildtool/common/cli.hpp
index a8acea87..26b284d9 100644
--- a/src/buildtool/common/cli.hpp
+++ b/src/buildtool/common/cli.hpp
@@ -77,6 +77,7 @@ struct AnalysisArguments {
std::vector<std::filesystem::path> graph_file_plain;
std::optional<std::filesystem::path> artifacts_to_build_file;
std::optional<std::filesystem::path> serve_errors_file;
+ std::optional<std::string> profile;
};
/// \brief Arguments required for describing targets/rules.
@@ -345,6 +346,9 @@ static inline auto SetupAnalysisArguments(
"File path for dumping the blob identifiers of serve "
"errors as json.")
->type_name("PATH");
+ app->add_option(
+ "--profile", clargs->profile, "Location to write the profile to.")
+ ->type_name("PATH");
if (with_graph) {
app->add_option_function<std::string>(
"--dump-graph",
diff --git a/src/buildtool/main/TARGETS b/src/buildtool/main/TARGETS
index 756e275a..0d2cd0ef 100644
--- a/src/buildtool/main/TARGETS
+++ b/src/buildtool/main/TARGETS
@@ -57,6 +57,7 @@
, ["src/buildtool/logging", "log_level"]
, ["src/buildtool/logging", "logging"]
, ["src/buildtool/multithreading", "task_system"]
+ , ["src/buildtool/profile", "profile"]
, ["src/buildtool/progress_reporting", "progress"]
, ["src/buildtool/progress_reporting", "progress_reporter"]
, ["src/buildtool/serve_api/remote", "config"]
diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp
index b8579b55..2f41ca72 100644
--- a/src/buildtool/main/main.cpp
+++ b/src/buildtool/main/main.cpp
@@ -68,6 +68,7 @@
#include "src/buildtool/main/install_cas.hpp"
#include "src/buildtool/main/version.hpp"
#include "src/buildtool/multithreading/task_system.hpp"
+#include "src/buildtool/profile/profile.hpp"
#include "src/buildtool/progress_reporting/progress.hpp"
#include "src/buildtool/serve_api/remote/serve_api.hpp"
#include "src/buildtool/storage/config.hpp"
@@ -720,6 +721,7 @@ void DumpArtifactsToBuild(
} // namespace
auto main(int argc, char* argv[]) -> int {
+ std::optional<gsl::not_null<Profile*>> profile{};
SetupDefaultLogging();
try {
auto arguments = ParseCommandLineArguments(argc, argv);
@@ -910,6 +912,12 @@ auto main(int argc, char* argv[]) -> int {
return kExitFailure;
}
+ // Setup profile logging, if requested
+ Profile profile_data(arguments.analysis.profile);
+ if (arguments.analysis.profile) {
+ profile = &profile_data;
+ }
+
// If no execution endpoint was given, the client should default to the
// serve endpoint, if given.
if (not arguments.endpoint.remote_execution_address.has_value() and
@@ -927,6 +935,9 @@ auto main(int argc, char* argv[]) -> int {
auto remote_exec_config =
CreateRemoteExecutionConfig(arguments.endpoint, arguments.rebuild);
if (not remote_exec_config) {
+ if (profile) {
+ (*profile)->Write(kExitFailure);
+ }
return kExitFailure;
}
@@ -946,6 +957,9 @@ auto main(int argc, char* argv[]) -> int {
arguments.endpoint, arguments.protocol.hash_type);
#endif // BOOTSTRAP_BUILD_TOOL
if (not storage_config) {
+ if (profile) {
+ (*profile)->Write(kExitFailure);
+ }
return kExitFailure;
}
auto const storage = Storage::Create(&*storage_config);
@@ -1031,6 +1045,9 @@ auto main(int argc, char* argv[]) -> int {
traverse_args,
&exec_context,
eval_root_jobs)) {
+ if (profile) {
+ (*profile)->Write(kExitFailure);
+ }
return kExitFailure;
}
#else
@@ -1040,6 +1057,9 @@ auto main(int argc, char* argv[]) -> int {
#ifndef BOOTSTRAP_BUILD_TOOL
auto lock = GarbageCollector::SharedLock(*storage_config);
if (not lock) {
+ if (profile) {
+ (*profile)->Write(kExitFailure);
+ }
return kExitFailure;
}
@@ -1072,18 +1092,25 @@ auto main(int argc, char* argv[]) -> int {
main_ws_root,
&repo_config,
arguments.analysis)) {
- return arguments.describe.describe_rule
- ? DescribeUserDefinedRule(
- id->target,
- &repo_config,
- arguments.common.jobs,
- arguments.describe.print_json)
- : DescribeTarget(*id,
- &repo_config,
- serve,
- main_apis,
- arguments.common.jobs,
- arguments.describe.print_json);
+ auto result =
+ arguments.describe.describe_rule
+ ? DescribeUserDefinedRule(id->target,
+ &repo_config,
+ arguments.common.jobs,
+ arguments.describe.print_json)
+ : DescribeTarget(*id,
+ &repo_config,
+ serve,
+ main_apis,
+ arguments.common.jobs,
+ arguments.describe.print_json);
+ if (profile) {
+ (*profile)->Write(result);
+ }
+ return result;
+ }
+ if (profile) {
+ (*profile)->Write(kExitFailure);
}
return kExitFailure;
}
@@ -1091,6 +1118,10 @@ auto main(int argc, char* argv[]) -> int {
#endif // BOOTSTRAP_BUILD_TOOL
auto id = ReadConfiguredTarget(
main_repo, main_ws_root, &repo_config, arguments.analysis);
+ if (profile) {
+ (*profile)->SetTarget(id.target.ToJson());
+ (*profile)->SetConfiguration(id.config.ToJson());
+ }
auto serve_errors = nlohmann::json::array();
std::mutex serve_errors_access{};
BuildMaps::Target::ServeFailureLogReporter collect_serve_errors =
@@ -1170,6 +1201,9 @@ auto main(int argc, char* argv[]) -> int {
TaskSystem ts{arguments.common.jobs};
analyse_result->result_map.Clear(&ts);
}
+ if (profile) {
+ (*profile)->Write(kExitSuccess);
+ }
return kExitSuccess;
}
#ifndef BOOTSTRAP_BUILD_TOOL
@@ -1225,9 +1259,13 @@ auto main(int argc, char* argv[]) -> int {
Logger::Log(LogLevel::Warning,
"Build result contains failed artifacts.");
}
- return build_result->failed_artifacts
- ? kExitSuccessFailedArtifacts
- : kExitSuccess;
+ auto result = build_result->failed_artifacts
+ ? kExitSuccessFailedArtifacts
+ : kExitSuccess;
+ if (profile) {
+ (*profile)->Write(result);
+ }
+ return result;
}
#endif // BOOTSTRAP_BUILD_TOOL
}
@@ -1235,5 +1273,8 @@ auto main(int argc, char* argv[]) -> int {
Logger::Log(
LogLevel::Error, "Caught exception with message: {}", ex.what());
}
+ if (profile) {
+ (*profile)->Write(kExitFailure);
+ }
return kExitFailure;
}
diff --git a/src/buildtool/profile/TARGETS b/src/buildtool/profile/TARGETS
new file mode 100644
index 00000000..c2bde05e
--- /dev/null
+++ b/src/buildtool/profile/TARGETS
@@ -0,0 +1,9 @@
+{ "profile":
+ { "type": ["@", "rules", "CC", "library"]
+ , "name": ["profile"]
+ , "hdrs": ["profile.hpp"]
+ , "srcs": ["profile.cpp"]
+ , "deps": [["@", "json", "", "json"]]
+ , "stage": ["src", "buildtool", "profile"]
+ }
+}
diff --git a/src/buildtool/profile/profile.cpp b/src/buildtool/profile/profile.cpp
new file mode 100644
index 00000000..543cd681
--- /dev/null
+++ b/src/buildtool/profile/profile.cpp
@@ -0,0 +1,35 @@
+// Copyright 2025 Huawei Cloud Computing Technology Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/buildtool/profile/profile.hpp"
+
+#include <fstream>
+
+void Profile::Write(int exit_code) {
+ if (not output_file_) {
+ return;
+ }
+ profile_["exit code"] = exit_code;
+
+ std::ofstream os(*output_file_);
+ os << profile_.dump(2) << std::endl;
+}
+
+void Profile::SetTarget(nlohmann::json target) {
+ profile_["target"] = std::move(target);
+}
+
+void Profile::SetConfiguration(nlohmann::json configuration) {
+ profile_["configuration"] = std::move(configuration);
+}
diff --git a/src/buildtool/profile/profile.hpp b/src/buildtool/profile/profile.hpp
new file mode 100644
index 00000000..0d4e14b6
--- /dev/null
+++ b/src/buildtool/profile/profile.hpp
@@ -0,0 +1,40 @@
+// Copyright 2025 Huawei Cloud Computing Technology Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef INCLUDED_SRC_BUILDTOOL_PROFILE_PROFILE_HPP
+#define INCLUDED_SRC_BUILDTOOL_PROFILE_PROFILE_HPP
+
+#include <optional>
+#include <string>
+#include <utility>
+
+#include "nlohmann/json.hpp"
+
+class Profile {
+ public:
+ explicit Profile(std::optional<std::string> output_file)
+ : output_file_{std::move(output_file)} {
+ profile_ = nlohmann::json::object();
+ }
+
+ void Write(int exit_code);
+ void SetTarget(nlohmann::json target);
+ void SetConfiguration(nlohmann::json configuration);
+
+ private:
+ std::optional<std::string> output_file_;
+ nlohmann::json profile_;
+};
+
+#endif