Skip to content

Commit 0d09b8a

Browse files
committed
fix: four defects the four-host scan found, in one round
The scan reached all four build hosts and produced six `mismatch` cells. The evidence capture added last commit paid for itself immediately — all six causes came out of one query. ⭐ THE MACHINE INTERFACE DID NOT ROUND-TRIP. `toolchain list --format json` reported `msvc@19.44.35228`, which is cl.exe's version, and `--toolchain msvc@19.44.35228` is refused by design — "names a COMPILER version, not a toolset". A consumer reads `family` and `version`, joins them, and hands the result back; scan.sh did exactly that and every msvc cell came back with mcpp rejecting its own output. A system toolset is `msvc@system`; the display number keeps a field of its own. e2e 296 now asserts the round-trip for every family on every host. ⚠️ A TARGET NO PAYLOAD HERE SERVES WAS STILL HAVING ITS PAYLOAD INSTALLED. `unservedTargetDiagnosis` is decided early and released late, deliberately — whether the graph supplies the system is not knowable until it is resolved — and the install sits between the two. On ubuntu-24.04-arm it failed first and hard: `xlings install of 'xim:x86_64-linux-musl-gcc@16.1.0' failed`, the cross-musl packages being published per host arch. Skipping the install leaves both later paths intact; attempting it cannot help either. ⚠️ AND I TRUNCATED MY OWN EVIDENCE. The `build-failed` line was cut at 160 characters, so the macOS cell read `precompiled file '/private/var/…/target/` and stopped exactly before the part worth reading. Three lines, whole lines. ⚠️ THE CELL COUNT WAS A FUNCTION OF CACHE STATE. Same ubuntu-24.04 runner: one run had gcc+llvm and scanned 40 cells, the next had gcc alone and scanned 20. The matrix now installs the toolchains its expected table names, and fails there if one cannot be installed, rather than reporting a screen of "never reached".
1 parent d9dd8d7 commit 0d09b8a

5 files changed

Lines changed: 112 additions & 5 deletions

File tree

.github/workflows/ci-target-matrix.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,40 @@ jobs:
217217
[ -n "$BUILT" ] || { echo "::error::mcpp did not build"; exit 1; }
218218
echo "MCPP_UNDER_TEST=$(cd "$(dirname "$BUILT")" && pwd)/$(basename "$BUILT")" >> "$GITHUB_ENV"
219219
220+
# ⚠️⚠️ 格数不能是缓存状态的函数。
221+
#
222+
# 实测:同一台 ubuntu-24.04,一轮装了 gcc+llvm(扫 40 格),下一轮只有 gcc
223+
# (扫 20 格)。`expected.tsv` 声明的是前者,于是后者会把所有 llvm 行报成
224+
# 「期望表说有而扫描没跑到」—— 而那句报错是对的,问题在于覆盖面**漂移**了。
225+
#
226+
# ⭐ 矩阵要声明它扫哪些工具链,并把它们装上。装不上就红在这里,而不是
227+
# 变成一屏「没跑到」。
228+
- name: Install the toolchains this matrix declares
229+
run: |
230+
set -uo pipefail
231+
export MCPP="$MCPP_UNDER_TEST"
232+
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
233+
want="$(awk -F'\t' -v h='${{ matrix.host }}' \
234+
'NF>=11 && $2==h {print $4}' tests/matrix/expected.tsv \
235+
| sort -u)"
236+
if [ -z "$want" ]; then
237+
echo " ? ${{ matrix.host }} 尚无期望行 —— 扫描它现有的工具链"
238+
exit 0
239+
fi
240+
fail=0
241+
for spec in $want; do
242+
fam="${spec%@*}"; ver="${spec#*@}"
243+
# `msvc@system` 是在机器上被找到的,不是装出来的。
244+
[ "$ver" = system ] && { echo " ok $spec (system)"; continue; }
245+
if "$MCPP" toolchain install "$fam" "$ver" >/dev/null 2>&1; then
246+
echo " ok $spec"
247+
else
248+
echo "::error::$spec 装不上,而期望表声明了它"
249+
fail=1
250+
fi
251+
done
252+
[ "$fail" = 0 ] || exit 1
253+
220254
- name: Scan both systems
221255
run: |
222256
set -euo pipefail

src/build/prepare.cppm

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1895,13 +1895,44 @@ prepare_build(bool print_fingerprint,
18951895
}
18961896
auto pkg = mcpp::toolchain::to_xim_package(*spec);
18971897

1898+
// ⚠️⚠️ AND NOT INSTALLED WHEN NO PAYLOAD HERE COULD SERVE THE TARGET.
1899+
//
1900+
// `unservedTargetDiagnosis` is decided a thousand lines above and
1901+
// released a thousand lines below — deliberately, because whether the
1902+
// dependency GRAPH supplies the target's system is not knowable until
1903+
// it is resolved. This install sits between the two, and it does not
1904+
// need to wait: if no payload here serves the target, then either the
1905+
// graph supplies the system (and this payload is not wanted) or the
1906+
// build refuses later (and it is not wanted then either).
1907+
//
1908+
// ⚠️ Measured on ubuntu-24.04-arm, `--target x86_64-linux-musl`:
1909+
//
1910+
// error: toolchain 'gcc@16.1.0': xlings install of
1911+
// 'xim:x86_64-linux-musl-gcc@16.1.0' failed …
1912+
//
1913+
// — the cross-musl packages are published per host arch and that one is
1914+
// x86_64-only. The refusal that names this correctly never ran, because
1915+
// the install failed first and failed hard.
1916+
//
1917+
// ⭐ Skipping leaves BOTH later paths intact; attempting cannot help
1918+
// either of them.
1919+
const bool targetPayloadUnservable =
1920+
!unservedTargetDiagnosis.empty() && !spec->target.empty();
1921+
18981922
auto cfg = get_cfg();
18991923
if (!cfg) return std::unexpected(cfg.error());
19001924
mcpp::fetcher::Fetcher fetcher(**cfg);
19011925

19021926
mcpp::ui::info("Resolving", "toolchain");
19031927
mcpp::fetcher::InstallProgressHandler progress;
1904-
auto payload = fetcher.resolve_xpkg_path(pkg.target(), /*autoInstall=*/true, &progress);
1928+
auto payload = fetcher.resolve_xpkg_path(
1929+
pkg.target(), /*autoInstall=*/!targetPayloadUnservable, &progress);
1930+
if (!payload && targetPayloadUnservable) {
1931+
// The held diagnosis is already the right words for this; releasing
1932+
// it here rather than at its usual site keeps one sentence per cause.
1933+
refusal::record(refusal::Code::HostCannotServe);
1934+
return std::unexpected(unservedTargetDiagnosis);
1935+
}
19051936
if (!payload) {
19061937
// `windows = "msvc@19.44"` in a manifest is the retired
19071938
// cl-version spelling; saying "no such xim package" would send

src/toolchain/lifecycle.cppm

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,9 +542,25 @@ export int toolchain_list(const mcpp::config::GlobalConfig& cfg,
542542
// second array.
543543
if (mcpp::platform::is_windows && json) {
544544
if (auto inst = mcpp::toolchain::msvc::detect_installation())
545+
// ⚠️⚠️ `version` MUST BE WHAT `--toolchain` ACCEPTS, AND THIS EMITTED
546+
// WHAT cl.exe REPORTS.
547+
//
548+
// A system Visual Studio is selected as `msvc@system`; its COMPILER
549+
// version is `19.44.35228`, which `parse_toolchain_spec` rejects by
550+
// design — it "names a COMPILER version, not a toolset".
551+
//
552+
// ⭐ THE MACHINE INTERFACE HAS TO ROUND-TRIP. A consumer reads
553+
// `family` and `version`, joins them, and hands the result back;
554+
// `tests/matrix/scan.sh` did exactly that and every msvc cell came
555+
// back `build-failed` with mcpp refusing its own output. Measured on
556+
// windows-2022, both modes.
557+
//
558+
// The human-facing number keeps a field of its own, so nothing is
559+
// lost — it simply stops pretending to be a spec.
545560
jsonToolchains.push_back({
546-
{"family", "msvc"},
547-
{"version", inst->display_version()},
561+
{"family", "msvc"},
562+
{"version", "system"},
563+
{"displayVersion", inst->display_version()},
548564
{"default", defSpec
549565
&& defSpec->family == mcpp::toolchain::Family::Msvc},
550566
{"source", "system"},

tests/e2e/296_what_the_report_names_is_what_the_link_line_uses.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,29 @@ c_abi_line() { printf '%s\n' "$report" | grep -E '^\s+c-abi\s' | head -1; }
7474

7575
fail=0; checked=0
7676

77+
# ── Relation zero: the machine interface must round-trip ──────────────────
78+
#
79+
# ⭐⭐ A CONSUMER READS `family` AND `version`, JOINS THEM, AND HANDS THE RESULT
80+
# BACK. That has to work, and for one entry it did not.
81+
#
82+
# ⚠️ Measured on windows-2022: `toolchain list --format json` reported
83+
# `msvc@19.44.35228` — cl.exe's version — and `--toolchain msvc@19.44.35228` is
84+
# refused by design ("names a COMPILER version, not a toolset"). Every msvc cell
85+
# in the target matrix came back `build-failed`, with mcpp rejecting its own
86+
# output. A system toolset is selected as `msvc@system`.
87+
#
88+
# This is cheap and catches the whole class, on every host, for every family.
89+
for spec in $("$MCPP" toolchain list --format json 2>/dev/null \
90+
| jq -r '.data.toolchains[] | .family + "@" + .version'); do
91+
if "$MCPP" why toolchain --toolchain "$spec" --format json >/dev/null 2>&1; then
92+
echo " ok $spec round-trips through --toolchain"
93+
checked=$((checked+1))
94+
else
95+
echo "FAIL: toolchain list emitted '$spec' and --toolchain refuses it"
96+
fail=1
97+
fi
98+
done
99+
77100
# ── Relation one: a payload C library must be on the link line ─────────────
78101
for tc in gcc llvm; do
79102
# ⭐ From the machine interface: `grep -oP` does not exist on macOS, and its

tests/matrix/scan.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,11 @@ for tc in $(compilers); do
193193
# ⚠️ 与查询失败同型:`build-failed` 是对的分类,而没有证据说明为什么。
194194
# macOS 上 20 格一模一样的红、日志里找不到原因,就是把输出丢掉的代价。
195195
# 这里只留错误行,不倒整份构建日志 —— 40 格 × 一份完整日志读不动。
196-
echo "scan: $t × $tc 构建失败: $(grep -m2 -iE '^error|error:' "$work/b.out" \
197-
| tr '\n' ' ' | cut -c1-160)" >&2
196+
# ⚠️ 三行,**整行**。前一版 `cut -c1-160` 把真正的错误砍在半路 ——
197+
# macOS 那格只留下 `precompiled file '/private/var/…/target/` 就没了,
198+
# 而要看的正是后半截。判据的单位是一整行输出。
199+
echo "scan: $t × $tc 构建失败:" >&2
200+
grep -m3 -iE '^error|error:' "$work/b.out" | sed 's/^/ /' >&2
198201
emit "$MODE" "$HOST" "$t" "$tc" "$tri" "$clib" "$cabi" "$cxxabi" "$okpkg" \
199202
mismatch build-failed
200203
fi

0 commit comments

Comments
 (0)