summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--doc/concepts/built-in-rules.md10
-rw-r--r--src/buildtool/build_engine/target_map/built_in_rules.cpp9
3 files changed, 19 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c3e776e..b7a15b8a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
Bug fixes on top of `1.4.2`.
+### Fixes
+
+- The "generic" rule now properly detects staging conflicts.
+
## Release `1.4.2` (2025-01-13)
Bug fixes on top of `1.4.1`.
diff --git a/doc/concepts/built-in-rules.md b/doc/concepts/built-in-rules.md
index 6c80ffb4..e7a5e2e3 100644
--- a/doc/concepts/built-in-rules.md
+++ b/doc/concepts/built-in-rules.md
@@ -86,10 +86,12 @@ choice.
The `"deps"` argument is evaluated and has to evaluate to a list of
target names. The runfiles and artifacts of these targets form the
-inputs of the action. Conflicts are not an error and resolved by giving
-precedence to the artifacts over the runfiles; conflicts within
-artifacts or runfiles are resolved in a latest-wins fashion using the
-order of the targets in the evaluated `"deps"` argument.
+inputs of the action. Conflicting definitions for individual paths
+are not an error and resolved by giving precedence to the artifacts
+over the runfiles; conflicts within artifacts or runfiles are
+resolved in a latest-wins fashion using the order of the targets in
+the evaluated `"deps"` argument. However, the input stage obtained
+by those resolution rules has to be free of semantic conflicts.
The fields `"cmds"`, `"cwd"`, `"sh -c"`, `"out_dirs"`, `"outs"`, and `"env"`
are evaluated fields where `"cmds"`, `"out_dirs"`, and `"outs"`
diff --git a/src/buildtool/build_engine/target_map/built_in_rules.cpp b/src/buildtool/build_engine/target_map/built_in_rules.cpp
index 9623f816..a227c30b 100644
--- a/src/buildtool/build_engine/target_map/built_in_rules.cpp
+++ b/src/buildtool/build_engine/target_map/built_in_rules.cpp
@@ -1351,9 +1351,18 @@ void GenericRuleWithDeps(
for (auto const& dep : dependency_values) {
inputs = ExpressionPtr{Expression::map_t{inputs, (*dep)->RunFiles()}};
}
+ auto inputs_conflict = BuildMaps::Target::Utils::tree_conflict(inputs);
for (auto const& dep : dependency_values) {
inputs = ExpressionPtr{Expression::map_t{inputs, (*dep)->Artifacts()}};
}
+ // While syntactical conflicts are resolved in a latest wins (with artifacts
+ // after runfiles), semantic path conclicts are an error.
+ if (inputs_conflict) {
+ (*logger)(fmt::format("Input artifacts have staging conflict on {}",
+ nlohmann::json(*inputs_conflict).dump()),
+ /*fatal=*/true);
+ return;
+ }
std::vector<Tree::Ptr> trees{};
inputs = BuildMaps::Target::Utils::add_dir_for(
cwd_value->String(), inputs, &trees);