Skip to content

Commit f61b466

Browse files
authored
2026.9.26.1: paths in UTF-8, a C standard per package, a graph link without the host, and the level that was declared (#698)
* 2026.9.26.1: paths in UTF-8, a C standard per package, a graph link without the host, and the level that was declared #693. mcpp held paths in the Windows ANSI code page, and the JSON it writes holds UTF-8 only, so every build under a non-ASCII project directory or home failed with an internal JSON exception, including names the code page can spell; a Latin-1 directory name fails the same way on Linux. mcpp.exe now declares the UTF-8 code page (res/mcpp.rc), build programs are linked with the same manifest, host tools default to it, and the new target key `windows_code_page` states it for a project's own executables. A path with no UTF-8 spelling is refused (project directory, MCPP_HOME), skipped and reported (a name inside a project), or refused by key (a build.mcpp directive), never an internal exception. The response files of the msvc dialect begin with a byte order mark, which cl.exe, link.exe and lib.exe need to read UTF-8 (measured), and Ninja's own encoding is checked when build.ninja is not ASCII. #695. `[build] c_standard` reached every C unit of the graph through the file-level $cflags, and a dependency's own value was not applied. Each package's C units now compile at that package's standard; an undeclared package at c11. #696. A link over a graph-supplied C library searched the host's library directories, so `-lm` linked glibc objects into a musl image. Such a link on ELF now carries --sysroot naming an empty directory, the hermetic check holds every -L to the store, the build directory and the graph's packages, and an unanswered -l fails with a note naming openkal-musl 0.19.2. #694. The musl -Og workaround is removed; the compile and the Finished line read one realised optimization level. Plan and measurements: .agents/docs/2026-09-25-issues-693-696-triage-and-repair-plan.md * xlings 2026.9.26.2, the key rule a test still stated, and the graph link measured on four legs - kXlingsVersion and every xlings pin in .github move to 2026.9.26.2 (openxlings/xlings#613): xlings.exe declares the UTF-8 code page and its main has an exception boundary, so a working directory or an MCPP_HOME outside the ANSI code page no longer ends it with 0xC0000409 and no output. - test_cache_key stated the old rule, that a package's `c_standard = "c11"` is keyed; a package that spells the default and one that says nothing compile identically and now share a key. CI run 1 failed that test on every platform, and nothing else in the unit suites. - e2e 778 pins each leg to the openkal-musl and openkal-llvm-runtime pair that belongs together (the runtime pins openkal-musl exactly, and a root that pins another is refused as irreconcilable), and adds the report's aarch64 case under qemu-aarch64 and a host `-L` refused by the hermetic check. The openkal job asserts each leg ran. - docs: a macOS file name is UTF-8; `allow_host_libs` lifts the graph-link refusal rather than turning it into a warning. - The plan's implementation record carries CI run 1: every Windows row of the regression job passes, and the two xcode-27 legs fail as on main (#669). * SPEC-002 rule three: a link over a graph-supplied C library searches no host directory (v1.1) --------- Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
1 parent 82867ad commit f61b466

57 files changed

Lines changed: 3892 additions & 142 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/docs/2026-09-25-issue-690-workspace-build-inheritance-consistency.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ The decisions below are derived from these rules. Each rule names its source in
6767
| `dialect_cxxflags`, `c_standard`, `linkage`, `target`, `cxx_runtime`, `dependency_linkage`, `macos_deployment_target` | root manifest only | graph-wide | n/a | consistent |
6868
| `ios_deployment_target` | parsed and inherited | **refused** | n/a | **F3** |
6969

70+
**Correction (2026-09-26, mcpp#695).** The row above classifies `c_standard` as read from the root manifest only and calls that consistent. For C the classification is wrong. A C translation unit produces no BMI, so nothing requires one C standard across the graph, and the package's own cache key and fingerprint already recorded the value as the package's. The root's value reached every dependency's C units through the file-level `$cflags` line, and a dependency's own declaration was not applied. From mcpp 2026.9.26.1 each package's C units compile at that package's own standard (docs/04, "`c_standard` applies to the package that declares it"); the plan is `2026-09-25-issues-693-696-triage-and-repair-plan.md`.
71+
7072
### 3.2 Inheritance placement: F1, F2, F8
7173

7274
**F1 (measured): `defines` are lost for a member reached as a `path` dependency.** On the dependency branch, `fold_build_defines_into_flags(dep_manifest->buildConfig)` (`src/build/prepare.cppm:8235`) folds and clears `defines`. `makePackageRoot` (`prepare.cppm:6709`) then calls `inherit_workspace_build`, which prepends the workspace `defines` to the folded manifest. It copies `cflags`/`cxxflags` into `privateBuild` without folding again. The failure is silent unless the source guards the macro. Workspace-wide defines are typically layout- or ABI-affecting (`_ITERATOR_DEBUG_LEVEL`, `_WIN32_WINNT`, `UNICODE`, `FMT_HEADER_ONLY`, `SPDLOG_ACTIVE_LEVEL`), so a member compiled without them is an ODR violation against members compiled with them.

‎.agents/docs/2026-09-25-issues-693-696-triage-and-repair-plan.md‎

Lines changed: 1308 additions & 0 deletions
Large diffs are not rendered by default.

‎.agents/docs/README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ superseded_by: 2026-09-07-....md # when status is superseded
1818
---
1919
```
2020

21-
309 records.
21+
310 records.
2222

2323
## By subject
2424

@@ -30,6 +30,7 @@ Records that declare one. Everything else is listed by date below.
3030

3131
### design
3232

33+
- [Issues #693 to #696: triage against mcpp's contracts, and one repair plan](2026-09-25-issues-693-696-triage-and-repair-plan.md) — active
3334
- [Workspace inheritance, flag scoping and the published form: a unified repair plan (#690)](2026-09-25-issue-690-workspace-build-inheritance-consistency.md) — landed
3435
- [MSVC toolset 的选择、#685、#687 与工具链管理规范:总体设计](2026-09-24-toolchain-selection-and-payload-trust-design.md) — active
3536
- [openkal 生态:能力的时刻模型,以及 C 环境方案空间的划分](2026-09-20-openkal-c-environment-ecosystem-design.md) — active
@@ -100,6 +101,7 @@ Records that declare one. Everything else is listed by date below.
100101

101102
### 2026-09
102103

104+
- [Issues #693 to #696: triage against mcpp's contracts, and one repair plan](2026-09-25-issues-693-696-triage-and-repair-plan.md) — active
103105
- [Workspace inheritance, flag scoping and the published form: a unified repair plan (#690)](2026-09-25-issue-690-workspace-build-inheritance-consistency.md) — landed
104106
- [#690: self-review before release, engine and ecosystem](2026-09-25-issue-690-self-review.md) — landed
105107
- [#690: implementation plan](2026-09-25-issue-690-implementation-plan.md) — landed

‎.github/actions/bootstrap-mcpp/action.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ inputs:
2525
# `package.name`, so one of the two was simply unreachable — and which one
2626
# depended on the machine, which is why CI failed on `compat:lua` on
2727
# Windows and `mcpplibs.capi:lua` on Linux. Never pin below that.
28-
default: '2026.9.20.1'
28+
default: '2026.9.26.2'
2929
cache-target:
3030
description: also restore/save target/ (build artifacts + BMIs)
3131
required: false

‎.github/actions/setup-macos-llvm/action.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ inputs:
1515
# Floor imposed by the index, not a routine bump — see
1616
# .github/actions/bootstrap-mcpp/action.yml for why 0.4.69 is required
1717
# (two packages named `lua` in one repo need openxlings/xlings#381).
18-
default: '2026.9.20.1'
18+
default: '2026.9.26.2'
1919
image:
2020
description: >
2121
The runner label the job runs on (macos-15, xcode-27). It is part of the
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#!/usr/bin/env bash
2+
# check_unicode_paths.sh: mcpp#693 on Windows: a project in a directory whose
3+
# name is not ASCII builds and runs on every toolchain row, and the files mcpp
4+
# writes for other tools hold that name in UTF-8.
5+
#
6+
# THE SHAPE OF THE FAILURE THIS GUARDS. Up to mcpp 2026.9.25.1 mcpp held paths in
7+
# the process ANSI code page. A name that page could spell (U+00E9 on code page
8+
# 1252, every Chinese name on code page 936) reached compile_commands.json as
9+
# ANSI bytes and failed every build with
10+
# error: internal: unhandled exception: [json.exception.type_error.316]
11+
# and a name it could not spell failed with a narrowing exception. mcpp.exe now
12+
# declares the UTF-8 code page, build programs are linked with the same
13+
# declaration, and the response files of the MSVC tools begin with a byte order
14+
# mark. Each of those is a separate way back to the failure, which is why every
15+
# row runs in every directory.
16+
#
17+
# Rows: llvm (clang++, the Windows default), msvc (cl.exe) and mingw (gcc@16.1.0
18+
# for x86_64-windows-gnu), each in an ASCII directory, a directory named
19+
# `caf` + U+00E9 (inside code page 1252) and one named U+6D4B U+8BD5 (outside
20+
# it). One more project runs a build.mcpp that reads its own directory from the
21+
# environment and prints it back as an include directory: the round trip of a
22+
# path through a build program. Names are built from bytes, so this file stays
23+
# ASCII.
24+
#
25+
# Usage: MCPP=<mcpp.exe> bash .github/tools/check_unicode_paths.sh
26+
set -uo pipefail
27+
28+
: "${MCPP:?set MCPP to the mcpp.exe under test}"
29+
ROOT=$(mktemp -d)
30+
CAFE="caf$(printf '\xc3\xa9')"
31+
CJK="$(printf '\xe6\xb5\x8b\xe8\xaf\x95')"
32+
CAFE_ANSI="caf$(printf '\xe9')"
33+
failed=0
34+
35+
ok() { echo " ok $*"; }
36+
bad() { echo " FAIL $*"; failed=1; }
37+
38+
# write_project DIR TOOLCHAIN_LINES
39+
write_project() {
40+
mkdir -p "$1/src"
41+
printf '[package]\nname = "unicodeprobe"\nversion = "0.1.0"\n\n%b\n' "$2" > "$1/mcpp.toml"
42+
cat > "$1/src/main.cpp" <<'EOF'
43+
import std;
44+
int main() {
45+
std::println("unicode probe");
46+
return 0;
47+
}
48+
EOF
49+
}
50+
51+
# The generated file holds the directory name in UTF-8, and never in the ANSI
52+
# code page.
53+
check_bytes() {
54+
local file=$1 name=$2 row=$3
55+
[ -f "$file" ] || { bad "$row: no $(basename "$file")"; return; }
56+
if ! LC_ALL=C grep -qF "$name" "$file"; then
57+
bad "$row: $(basename "$file") does not hold the directory name in UTF-8"
58+
fi
59+
if [ "$name" = "$CAFE" ] && LC_ALL=C grep -qF "$CAFE_ANSI" "$file"; then
60+
bad "$row: $(basename "$file") holds the ANSI spelling of the directory name"
61+
fi
62+
}
63+
64+
rows=(
65+
'llvm|[toolchain]\nwindows = "llvm@20.1.7"|'
66+
'msvc|[toolchain]\nwindows = "msvc@system"|'
67+
'mingw|[toolchain]\ndefault = "gcc@16.1.0"|--target x86_64-windows-gnu'
68+
)
69+
70+
for name in ascii "$CAFE" "$CJK"; do
71+
for row in "${rows[@]}"; do
72+
IFS='|' read -r rid tc args <<<"$row"
73+
dir="$ROOT/$name/$rid"
74+
label="$rid in '$name'"
75+
write_project "$dir" "$tc"
76+
cd "$dir" || { bad "$label: cannot enter the directory"; continue; }
77+
# shellcheck disable=SC2086
78+
if ! "$MCPP" build $args > build.log 2>&1; then
79+
bad "$label: the build failed"; tail -15 build.log | sed 's/^/ /'; continue
80+
fi
81+
# shellcheck disable=SC2086
82+
out=$("$MCPP" run $args 2>&1)
83+
if ! grep -q 'unicode probe' <<<"$out"; then
84+
bad "$label: the program did not run"; printf '%s\n' "$out" | tail -5 | sed 's/^/ /'
85+
continue
86+
fi
87+
if [ "$name" != ascii ]; then
88+
ninja=$(find target -name build.ninja -newer mcpp.toml | head -1)
89+
check_bytes "$ninja" "$name" "$label"
90+
check_bytes compile_commands.json "$name" "$label"
91+
fi
92+
ok "$label"
93+
done
94+
done
95+
96+
# A path through a build program: MCPP_MANIFEST_DIR in, `mcpp:include-dir` out,
97+
# and the header found at the directory the program printed.
98+
dir="$ROOT/$CJK/buildprogram"
99+
mkdir -p "$dir/src" "$dir/inc"
100+
printf '[package]\nname = "unicodebp"\nversion = "0.1.0"\n\n[toolchain]\nwindows = "llvm@20.1.7"\n' > "$dir/mcpp.toml"
101+
printf '#define UNICODE_BP 42\n' > "$dir/inc/unicode_bp.h"
102+
cat > "$dir/build.mcpp" <<'EOF'
103+
#include <cstdio>
104+
#include <cstdlib>
105+
int main() {
106+
const char* here = std::getenv("MCPP_MANIFEST_DIR");
107+
if (!here) return 1;
108+
std::printf("mcpp:include-dir=%s/inc\n", here);
109+
return 0;
110+
}
111+
EOF
112+
cat > "$dir/src/main.cpp" <<'EOF'
113+
#include "unicode_bp.h"
114+
import std;
115+
int main() {
116+
std::println("build program {}", UNICODE_BP);
117+
return 0;
118+
}
119+
EOF
120+
cd "$dir"
121+
if "$MCPP" build > build.log 2>&1 && "$MCPP" run 2>&1 | grep -q 'build program 42'; then
122+
ok "a path through build.mcpp in '$CJK'"
123+
else
124+
bad "a path through build.mcpp in '$CJK'"; tail -15 build.log | sed 's/^/ /'
125+
fi
126+
127+
cd / && rm -rf "$ROOT"
128+
[ "$failed" = 0 ] && echo "OK: every row builds in every directory" && exit 0
129+
echo "FAIL: at least one row did not build in a directory whose name is not ASCII"
130+
exit 1

‎.github/workflows/bootstrap-macos.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
# Dormant (workflow_dispatch only), but kept in step with the rest —
1818
# check_version_pins.sh holds it there. Floor: 0.4.69, below which the
1919
# index cannot resolve two packages that share a short name.
20-
XLINGS_VERSION: '2026.9.20.1'
20+
XLINGS_VERSION: '2026.9.26.2'
2121
steps:
2222
- uses: actions/checkout@v4
2323

‎.github/workflows/ci-fresh-install.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ jobs:
152152
env:
153153
XLINGS_NON_INTERACTIVE: '1'
154154
run: |
155-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.20.1
155+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
156156
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
157157
158158
- name: Install mcpp and config mirror
@@ -312,7 +312,7 @@ jobs:
312312

313313
- name: Install xlings + mcpp
314314
run: |
315-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.20.1
315+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
316316
# Deliberately NOT writing to $GITHUB_PATH here. On container
317317
# images that declare no PATH in their config (opensuse/
318318
# tumbleweed), appending a single dir to GITHUB_PATH makes the
@@ -403,7 +403,7 @@ jobs:
403403
# (older ones carry minos=15 and refuse to start).
404404
# v0.4.51+: in-process sha256 — this image has no sha256sum
405405
# binary, so pinned fetches failed before it.
406-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.20.1
406+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
407407
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
408408
409409
- name: Install mcpp and config mirror

‎.github/workflows/ci-linux-e2e.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ jobs:
384384
385385
- name: Bootstrap xlings + released mcpp
386386
run: |
387-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.20.1
387+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
388388
export PATH="$HOME/.xlings/subos/current/bin:$PATH"
389389
xlings update
390390
xlings install mcpp -y -g

‎.github/workflows/ci-windows.yml‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,17 @@ jobs:
405405
# restore the LLVM default for the remaining steps
406406
"$MCPP_SELF" toolchain default llvm@20.1.7
407407
408+
# mcpp#693: a project in a directory whose name is not ASCII, inside the
409+
# runner's code page 1252 and outside it, on the llvm, MSVC and MinGW rows,
410+
# plus a path carried through build.mcpp. Each row reaches a different
411+
# consumer of mcpp's text: Ninja's build file, the MSVC response files,
412+
# and the MinGW driver.
413+
- name: "Paths: non-ASCII project directories on every toolchain row (mcpp#693)"
414+
shell: bash
415+
run: |
416+
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
417+
MCPP="$MCPP_SELF" bash .github/tools/check_unicode_paths.sh
418+
408419
409420
# GRAPHICS ON THIS HOST, BUILD ONLY, AND THAT IS THE WHOLE CLAIM.
410421
#

0 commit comments

Comments
 (0)