Skip to content

Commit 2420a1f

Browse files
committed
stage --list: generic spellings, and a refusal that names its entries; two prepare steps split under the size gate (#734)
- The placement list is written with forward slashes on every host, which is its stated format; on Windows the unit test read `bin\msvcp140.dll`. - A refusal from `mcpp stage --list` names the failing group's entries as the list writes them. With one edge for the whole list, ninja's echo of the command no longer shows which files were involved (e2e 646 on Windows). - step13_serve_workspace_members (E1) and host_module_units are split out of step13_dependency_cache and step6_host_module_registration, which the function-size gate reported over 400 lines. `workspace_member_of` is one function shared by E1 and W3. - The design record states three further plugin departures.
1 parent af81f62 commit 2420a1f

7 files changed

Lines changed: 395 additions & 353 deletions

File tree

‎.agents/docs/2026-09-28-build-cost-foreign-toolsets-and-library-surface-design.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,5 +1262,23 @@ Departures from §6:
12621262
check reads it.
12631263
5. **Each deps-cmake toolset statement has its own build directory,** because
12641264
CMake refuses a cache made with another generator or instance.
1265+
6. **The Linux GCC row keeps the foreign system's detection under `resolved`.**
1266+
§6.2 named every non-MSVC toolset through `chain`. The plugins' CI measured
1267+
that the GCC payload's driver is not a complete handover: mcpp runs it with a
1268+
sysroot, a binutils directory and a link model that only its own command
1269+
lines carry, and vcpkg's compiler detection failed with the driver alone.
1270+
The clang payloads are complete through their `.cfg` files. On the GCC row
1271+
the host compiler's libstdc++ is the program's C++ library, so
1272+
`mcpp.plugins.toolset` answers `detected` there and states why.
1273+
7. **The MSBuild refusal matches the call stack.** A read inside a function
1274+
reports the caller's list file to a `variable_watch` callback, so a match on
1275+
the current file never fired (measured on the masked row: MSBuild failed
1276+
with "no such file or directory" and no reason). The stack names the
1277+
helper's defining file.
1278+
8. **E2 has no "tool flags" accessor.** Deviation 6 is where one would be
1279+
read. The engine states `toolchain_sysroot()` and
1280+
`toolchain_binutils_dir()` already, but not the link model; handing a
1281+
foreign system the GCC payload completely is left to a later design with its
1282+
own criterion (a port that builds and runs a host tool).
12651283
12661284
**mcpp-index, validation.** Recorded below as they land.

‎src/build/ninja_backend.cppm‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3045,7 +3045,7 @@ std::string emit_ninja_string(const BuildPlan& plan, std::string* placements) {
30453045
outs += " " + escape_ninja_path(d.dest);
30463046
for (auto const& s : d.sources) {
30473047
ins += " " + escape_ninja_path(s);
3048-
list += std::format("{}\t{}\n", s.string(), d.dest.string());
3048+
list += std::format("{}\t{}\n", s.generic_string(), d.dest.generic_string());
30493049
}
30503050
}
30513051
append(std::format("build{} : stage_list{} | placements.list\n count = {}\n",

‎src/build/prepare/features.cpp‎

Lines changed: 162 additions & 154 deletions
Large diffs are not rendered by default.

‎src/build/prepare/plan.cpp‎

Lines changed: 199 additions & 180 deletions
Large diffs are not rendered by default.

‎src/build/prepare/scan.cpp‎

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -911,25 +911,10 @@ static void step11_public_module_check(PrepareState& state) {
911911
// A member of the root's own workspace is built from source together with
912912
// the root, whichever form it is published in, so the packed-form
913913
// consequence W3 states does not arise for it (SPEC-008 §4).
914-
auto sameWorkspace = [&](const std::filesystem::path& root) {
915-
if (!state.wsManifest || state.runtimeWorkspaceRoot.empty()) return false;
916-
const auto rel = root.lexically_normal()
917-
.lexically_relative(state.runtimeWorkspaceRoot.lexically_normal())
918-
.generic_string();
919-
if (rel.empty() || rel == "." || rel.starts_with("..")) return false;
920-
for (auto const& m : state.wsManifest->workspace.members) {
921-
if (m == rel) return true;
922-
if (m.ends_with("/*") && rel.starts_with(m.substr(0, m.size() - 1))
923-
&& rel.find('/', m.size() - 1) == std::string::npos)
924-
return true;
925-
}
926-
return false;
927-
};
928-
929914
std::map<std::string, std::set<std::string>> publicOf;
930915
for (std::size_t i = 1; i < state.packages.size(); ++i) {
931916
auto const& pr = state.packages[i];
932-
if (sameWorkspace(pr.root)) continue;
917+
if (!workspace_member_of(state, pr.root).empty()) continue;
933918
const auto rootFile = (pr.root / mcpp::manifest::resolve_lib_root_path(pr.manifest, pr.root))
934919
.lexically_normal();
935920
std::error_code ec;

‎src/build/prepare/state.cppm‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,10 @@ struct PrepareState {
502502
// static would give each definition internal linkage, invisible outside
503503
// its own file.
504504
std::expected<void, std::string> phase0_manifest_and_workspace(PrepareState& state);
505+
506+
// plan.cpp: the member path of a package root within the workspace this build
507+
// runs in, or empty (#734 E1, W3).
508+
std::string workspace_member_of(const PrepareState& state, const std::filesystem::path& root);
505509
std::expected<void, std::string> phase1_toolchain_spec_and_axes(PrepareState& state);
506510
std::expected<void, std::string> phase2_define_toolchain_resolver(PrepareState& state);
507511
std::expected<void, std::string> phase3_xlings_before_graph(PrepareState& state);

‎src/cli/cmd_build.cppm‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,7 @@ export int cmd_stage(const mcpplibs::cmdline::ParsedArgs& parsed) {
978978
return 1;
979979
}
980980
std::vector<std::pair<std::string, std::vector<std::filesystem::path>>> groups;
981+
std::vector<std::vector<std::string>> spelled; // each group's sources as the list writes them
981982
std::map<std::string, std::size_t> index;
982983
std::string line;
983984
while (std::getline(in, line)) {
@@ -990,15 +991,22 @@ export int cmd_stage(const mcpplibs::cmdline::ParsedArgs& parsed) {
990991
}
991992
std::string src = line.substr(0, tab), dst = line.substr(tab + 1);
992993
auto [it, fresh] = index.emplace(dst, groups.size());
993-
if (fresh) groups.push_back({dst, {}});
994+
if (fresh) { groups.push_back({dst, {}}); spelled.emplace_back(); }
994995
groups[it->second].second.push_back(
995996
mcpp::platform::fs::extended_length(std::filesystem::path{src}));
997+
spelled[it->second].push_back(src);
996998
}
997-
for (auto const& [dst, srcs] : groups) {
999+
for (std::size_t g = 0; g < groups.size(); ++g) {
1000+
auto const& [dst, srcs] = groups[g];
9981001
auto r = mcpp::build::stage::stage_files(
9991002
srcs, mcpp::platform::fs::extended_length(std::filesystem::path{dst}), opts);
10001003
if (!r) {
1004+
// One edge places the whole list, so ninja's echo of the
1005+
// command no longer shows which files were involved; the
1006+
// entries are named here as the list writes them.
10011007
std::println(stderr, "error: {}", r.error().message);
1008+
std::println(stderr, " placement list entries ({}):", listFile);
1009+
for (auto const& src : spelled[g]) std::println(stderr, " {} -> {}", src, dst);
10021010
return 1;
10031011
}
10041012
}

0 commit comments

Comments
 (0)