Skip to content

Commit 793c43e

Browse files
committed
${mcpp.bin_dir} in an action a workspace member's build program declares is that member's product directory
The validation project's cross-verification against this pull request stopped at mcpp pack: its build script stages ${mcpp.bin_dir}/<target>.pdb, and the placeholder expanded to the plan's bin/, where a member's binaries are not. e2e 838 A4 states it; docs/30 (both languages) state the expansion.
1 parent 982fc73 commit 793c43e

6 files changed

Lines changed: 38 additions & 6 deletions

File tree

‎.agents/docs/2026-09-29-workspace-build-graph-design.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ read from the member, or made a value of the plan:
560560
| the shared libraries of a member's closure | only those the member's units link were placed | every graph-built shared library of the closure, with its aliases, as §15 states | e2e 835 L3 |
561561
| the runtime files of a program shipped through `artifacts` (2026.9.29.3) | its link waited for the plan's deploy set, which a workspace plan does not place; its own runtime files were not in the member's directory | the link waits for no plan-level file; a member's runtime set includes the closures its `artifacts` edges reach | e2e 833 G9 |
562562
| the link line of a program shipped through `artifacts` (2026.9.29.4) | the plan's line, which pools the dependencies' flags and not a member's, so a library its package's build program states was missing | a link group of its own closure that places nothing (`LinkGroup::linkOnly`) | e2e 838 |
563+
| `${mcpp.bin_dir}` in a member's action (2026.9.29.4) | the plan's `bin/` | the declaring member's product directory | e2e 838 A4 |
563564

564565
Each criterion fails on 2026.9.29.1 and passes on 2026.9.29.2. The resource
565566
case also showed a defect of every build: a quoted `#include` in a script was

‎CHANGELOG.md‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
## [2026.9.29.4] - 2026-09-29
88

99
This release links a program that a workspace member ships through
10-
`artifacts` with the link line of its own package's closure. The validation
11-
project's post-release build of 2026.9.29.3 found it.
10+
`artifacts` with the link line of its own package's closure, and expands
11+
`${mcpp.bin_dir}` to where the declaring member's binaries land. The validation
12+
project's post-release build of 2026.9.29.3 found the first, and its
13+
cross-verification against this release's pull request the second.
1214

1315
### Fixed
1416

@@ -20,6 +22,10 @@ project's post-release build of 2026.9.29.3 found it.
2022
program now has a link group of its own that holds its closure's line and
2123
runtime contract and places nothing, since the members that ship the program
2224
place it.
25+
- **`${mcpp.bin_dir}` in an action a workspace member's build program declares
26+
is that member's product directory.** It was the plan's `bin/`, where a
27+
member's binaries are not, so an action that named a file beside the
28+
member's program (a `.pdb`, say) read or wrote the wrong place (e2e 838 A4).
2329

2430
## [2026.9.29.3] - 2026-09-29
2531

‎docs/30-build-mcpp.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ none to rely on), and the only interpolations are a closed set:
10031003
| Variable | Value |
10041004
|---|---|
10051005
| `${mcpp.out_dir}` | the build output directory |
1006-
| `${mcpp.bin_dir}` | where produced binaries land |
1006+
| `${mcpp.bin_dir}` | where produced binaries land: `bin/`, or, for an action a workspace member's build program declares, that member's product directory (2026.9.29.4+) |
10071007
| `${mcpp.compile_db}` | path to `compile_commands.json` (what clang-tidy's `-p` wants) |
10081008
| `${mcpp.target_file:<name>}` | the built file of target `<name>` |
10091009
| `${mcpp.stage_dir}` *(2026.9.11.1+)* | the tree `mcpp pack` staged, absolute. `artifact` role only, and only under `mcpp pack --format <name>` |

‎docs/zh/30-build-mcpp.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ mcpp 会写出 `<暂存树>.stage-manifest` —— 一个兄弟文件,永不
848848
| 变量 | 含义 |
849849
|---|---|
850850
| `${mcpp.out_dir}` | 构建输出目录 |
851-
| `${mcpp.bin_dir}` | 产出的二进制所在目录 |
851+
| `${mcpp.bin_dir}` | 产出的二进制所在目录:`bin/`;工作区成员的构建程序声明的 action 中为该成员的产物目录(2026.9.29.4+) |
852852
| `${mcpp.compile_db}` | `compile_commands.json` 的路径(clang-tidy 的 `-p` 要的就是它) |
853853
| `${mcpp.target_file:<name>}` | target `<name>` 构建出的文件 |
854854
| `${mcpp.stage_dir}` *(2026.9.11.1+)* | `mcpp pack` 暂存出的那棵树,绝对路径。仅 `artifact` role 可用,且仅在 `mcpp pack --format <name>` 下可用 |

‎src/build/prepare/plan.cpp‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,11 @@ static std::expected<void, std::string> step13_build_graph_actions(PrepareState&
932932
// NAMES ids and a collision there costs a duplicate line, not a wrong
933933
// edge.
934934
bool thisActionUsesStageDir = false;
935+
// Where the declaring package's binaries land: `bin/`, or in a
936+
// workspace plan the product directory of the member that declared
937+
// the action (§15 of the 2026-09-29 workspace design). Set per
938+
// package by `collect`.
939+
std::filesystem::path binDir = ctx.plan.outputDir / "bin";
935940
const bool stagePass = !state.overrides.pack_stage_dir.empty();
936941
auto substitute = [&](std::string s, const char* actionId,
937942
mcpp::manifest::BuildAction::Role role) {
@@ -940,7 +945,7 @@ static std::expected<void, std::string> step13_build_graph_actions(PrepareState&
940945
s.replace(p, what.size(), with);
941946
};
942947
rep("${mcpp.out_dir}", ctx.plan.outputDir.string());
943-
rep("${mcpp.bin_dir}", (ctx.plan.outputDir / "bin").string());
948+
rep("${mcpp.bin_dir}", binDir.string());
944949
rep("${mcpp.compile_db}", ctx.plan.compileDbPath.string());
945950
// The engine's own executable, absolute (2026.9.13.1+). An action
946951
// whose command is an argv with no shell has no portable way to
@@ -1024,6 +1029,9 @@ static std::expected<void, std::string> step13_build_graph_actions(PrepareState&
10241029
// program has no idea which package the engine loaded it for.
10251030
// mcpp#534's ordering edge is scoped to this name.
10261031
auto owner = mcpp::build::qualified_package_name(mm);
1032+
binDir = ctx.plan.outputDir / "bin";
1033+
for (auto const& g : ctx.plan.linkGroups)
1034+
if (!g.linkOnly && g.member == owner) binDir = ctx.plan.outputDir / g.productDir;
10271035
for (auto a : mm.buildConfig.actions) {
10281036
thisActionUsesStageDir = false;
10291037
const auto sub = [&](std::string v) {

‎tests/e2e/838_a_program_shipped_through_artifacts_links_its_own_closure.sh‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
#
1212
# A1 `mcpp build --workspace` links the program shipped through `artifacts`;
1313
# A2 the program in the shipping member's product directory runs;
14-
# A3 the program as its own member's product runs too.
14+
# A3 the program as its own member's product runs too;
15+
# A4 `${mcpp.bin_dir}` in an action the helper's build program declares is
16+
# the helper's product directory, where its binaries land (2026.9.29.3
17+
# expanded it to the plan's `bin/`, so a file named after the program
18+
# was looked for where the program is not).
1519
set -e
1620

1721
TMP=$(mktemp -d)
@@ -57,6 +61,15 @@ import mcpp;
5761
int main() {
5862
mcpp::link_search("vendor/lib");
5963
mcpp::link_lib("vend");
64+
mcpp::action a;
65+
a.id = "copy-helper";
66+
a.role = mcpp::roles::artifact;
67+
a.arg("${mcpp.self}").arg("stage").arg("--verify").arg("content")
68+
.arg("--output").arg("${mcpp.bin_dir}/helper.copy")
69+
.arg("${mcpp.target_file:helper}")
70+
.input("${mcpp.target_file:helper}")
71+
.output("${mcpp.bin_dir}/helper.copy")
72+
.submit();
6073
return 0;
6174
}
6275
EOF
@@ -87,4 +100,8 @@ own=$(find target -path '*/bin/helper/helper' -type f | head -1)
87100
[ -n "$own" ] || fail "A3: bin/helper/helper is missing" b.log
88101
"$own" || fail "A3: bin/helper/helper did not run"
89102

103+
# A4
104+
[ -f "$(dirname "$own")/helper.copy" ] \
105+
|| { find target -name 'helper.copy'; fail "A4: \${mcpp.bin_dir} is not the helper's product directory" b.log; }
106+
90107
echo "PASS: 838_a_program_shipped_through_artifacts_links_its_own_closure"

0 commit comments

Comments
 (0)