From 967fef30981a28a0a91c8f86db3d5b7b2bc2fb66 Mon Sep 17 00:00:00 2001 From: Klaus Aehlig Date: Fri, 2 Aug 2024 11:22:04 +0200 Subject: generic rule: add support for cwd --- doc/concepts/built-in-rules.md | 13 ++++++---- .../build_engine/target_map/built_in_rules.cpp | 28 +++++++++++++++++++++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/doc/concepts/built-in-rules.md b/doc/concepts/built-in-rules.md index 69df06dc..6c80ffb4 100644 --- a/doc/concepts/built-in-rules.md +++ b/doc/concepts/built-in-rules.md @@ -91,23 +91,26 @@ 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. -The fields `"cmds"`, `"sh -c"`, `"out_dirs"`, `"outs"`, and `"env"` +The fields `"cmds"`, `"cwd"`, `"sh -c"`, `"out_dirs"`, `"outs"`, and `"env"` are evaluated fields where `"cmds"`, `"out_dirs"`, and `"outs"` have to evaluate to a list of strings, `"sh -c"` has to evalute to -a list of strings or `null`, and `"env"` has to evaluate to a map -of strings. During their evaluation, the functions `"outs"` and +a list of strings or `null`, `"env"` has to evaluate to a map +of strings, and `"cwd"` has to evaluate to a single string naming a non-upwards +relative path. During their evaluation, the functions `"outs"` and `"runfiles"` can be used to access the logical paths of the artifacts and runfiles, respectively, of a target specified in `"deps"`. Here, `"env"` specifies the environment in which the action is carried out. `"out_dirs"` and `"outs"` define the output directories and -files, respectively, the action has to produce. Since some artifacts +files, respectively, the action has to produce; these path are read +relative to the action root. Since some artifacts are to be produced, at least one of `"out_dirs"` or `"outs"` must be a non-empty list of strings. It is an error if one or more paths are present in both the `"out_dirs"` and `"outs"`. Finally, the strings in `"cmds"` are extended by a newline character and joined, and command of the action is the result of evaluating the field `"sh -c"` (or `["sh", "-c"]` if `"sh -c"` evaluates to `null` or -`[]`) extended by this string. +`[]`) extended by this string; the command is executed in the +subdirectory of the execution root specified by `"cwd"`. The artifacts of this target are the outputs (as declared by `"out_dirs"` and `"outs"`) of this action. Runfiles and provider map are 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 e1cf9c7f..e3cfc028 100644 --- a/src/buildtool/build_engine/target_map/built_in_rules.cpp +++ b/src/buildtool/build_engine/target_map/built_in_rules.cpp @@ -42,6 +42,7 @@ namespace { auto const kGenericRuleFields = std::unordered_set{"arguments_config", "cmds", + "cwd", "deps", "env", "execution properties", @@ -1196,6 +1197,31 @@ void GenericRuleWithDeps( cmd_ss << x->String(); cmd_ss << "\n"; } + auto cwd_exp = + desc->ReadOptionalExpression("cwd", Expression::kEmptyString); + if (not cwd_exp) { + return; + } + auto cwd_value = cwd_exp.Evaluate( + param_config, string_fields_fcts, [&logger](auto const& msg) { + (*logger)(fmt::format("While evaluating cwd:\n{}", msg), true); + }); + if (not cwd_value) { + return; + } + if (not cwd_value->IsString()) { + (*logger)(fmt::format("cwd has to evaluate to a string, but found {}", + cwd_value->ToString()), + true); + return; + } + if (not PathIsNonUpwards(cwd_value->String())) { + (*logger)(fmt::format("cwd has to evalute to a non-upwards relative " + "path, but found {}", + cwd_value->ToString()), + true); + return; + } auto const& empty_map_exp = Expression::kEmptyMapExpr; auto env_exp = desc->ReadOptionalExpression("env", empty_map_exp); if (not env_exp) { @@ -1341,7 +1367,7 @@ void GenericRuleWithDeps( outs, out_dirs, argv, - "", + cwd_value->String(), env_val, std::nullopt, false, -- cgit v1.2.3