Skip to content

Commit b165218

Browse files
authored
2026.10.8.1: LLVM 23.1.3 line, native Linux ARM64, the 32-bit MSVC coroutine note and no host system headers (#781)
Moves the LLVM line to 23.1.3, makes native Linux aarch64 select LLVM 23.1.3 with the GNU target, and closes the review findings of Part 3. LLVM line and defaults - kKnownTargets' llvm rows, the macOS and Windows-with-MSVC first-run defaults and the self-hosting manifest move to llvm@23.1.3 (the first release with the macOS 27 arm64e.x1 linker fix). Linux x86_64 keeps gcc@16.1.0. Existing user declarations and the musl rows are unchanged. - Native Linux aarch64 defaults to llvm@23.1.3 on the managed glibc; aarch64-linux-gnu is preview until the released engine is consumed on a clean ARM64 host. xlings is pinned to 2026.10.8.1. - A declared toolchain for a graph-supplied target is installed even when no payload here serves the target; an engine-chosen one still releases the held diagnosis (#782). - AArch64 std modules and programs share compiler-rt settings; a self-contained ELF that embeds libunwind.a links with --unwindlib=none. Part 3 - clang 23 does not predefine __cpp_impl_coroutine for i686-pc-windows-msvc. mcpp follows the compiler and appends a note to the two failures that follow (the C++23 std module inside <generator>, and code that uses coroutines): C++20 first, llvm@22.1.8 for that target as an option. The std module case is decided from its command; the ninja and fast paths from the output. Measured on probe PR #788; e2e 892. - No host system header directory is searched on a managed C library: clang carries -nostdlibinc, GCC without a usable subos takes -isysroot <C library payload>. A project that needs a host header writes -idirafter (e2e 891). - The graph C library note fires only when the C library is the graph's, on the plan path and the fast path (.mcpp-graph-c-library). Tests and documents - tests/e2e/_toolchain_env.sh is the one place an e2e learns a toolchain version; the four-host target matrix (244 rows) is declared; ARM64 native admission, openkal cross and hosted-thread checks run in CI. - docs/20 and docs/21 (en/zh), READMEs, SPEC-006 v0.7 (§3.8), SPEC-009 v0.6 (§6.4), CHANGELOG. Closes #780 Closes #783 Refs: #784, #786
1 parent de9c290 commit b165218

150 files changed

Lines changed: 4945 additions & 961 deletions

File tree

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-10-07-llvm-2313-unified-default-cross-repo-design.md‎

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

‎.agents/docs/2026-10-08-llvm-2313-linux-aarch64-ecosystem-part2-design.md‎

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

‎.agents/docs/README.md‎

Lines changed: 8 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-
327 records.
21+
329 records.
2222

2323
## By subject
2424

@@ -95,6 +95,11 @@ Records that declare one. Everything else is listed by date below.
9595
- [SDK toolchains, the payload/engine seam, and openkal across iOS, Android and Web](2026-09-11-sdk-toolchains-and-ios-local-verification.md) — landed
9696
- [Where a platform's knowledge belongs: iOS, Android and Web across the engine, the index and the plugins](2026-09-11-platform-targets-design-review.md) — active
9797

98+
### toolchain
99+
100+
- [LLVM 23.1.3 Part 2:Linux aarch64 默认工具链与 glibc 生态闭环](2026-10-08-llvm-2313-linux-aarch64-ecosystem-part2-design.md) — active
101+
- [LLVM 23.1.3 全平台统一默认:跨仓库联动方案(mcpp × xim-pkgindex)](2026-10-07-llvm-2313-unified-default-cross-repo-design.md) — active
102+
98103
### triage
99104

100105
- [Eight reports after 2026.9.27.1: what each one is, where it belongs, and one optimisation plan](2026-09-27-eight-reports-by-home-and-one-optimisation-plan.md) — active
@@ -118,6 +123,8 @@ Records that declare one. Everything else is listed by date below.
118123

119124
### 2026-10
120125

126+
- [LLVM 23.1.3 Part 2:Linux aarch64 默认工具链与 glibc 生态闭环](2026-10-08-llvm-2313-linux-aarch64-ecosystem-part2-design.md) — active
127+
- [LLVM 23.1.3 全平台统一默认:跨仓库联动方案(mcpp × xim-pkgindex)](2026-10-07-llvm-2313-unified-default-cross-repo-design.md) — active
121128
- [2026.10.5.3 发布方案:32 位 x86 的架构词汇、资源编译器的识别与增量(#776 后续)](2026-10-06-windows-x86-arch-vocabulary-and-rc-follow-ups-design.md) — active
122129
- [下一个版本的发布方案:标准库模块、原生 MSVC LTO 与导出发现、共享库的链接配置、Windows 参数引号(#768 后续、#770、#771)](2026-10-05-std-module-pair-msvc-lto-and-export-discovery-design.md) — active
123130
- [`mcpp run` hands the terminal to the program, and the follow-ups of #761, #763 and #765 (#766)](2026-10-05-run-terminal-handoff-and-766-follow-ups-design.md) — landed

‎.gitattributes‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# The cross-host admission compares the exact source bytes compiled by each host.
2+
tests/fixtures/openkal-hosted-threads/src/main.cpp.in text eol=lf

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ inputs:
3333
# `package.name`, so one of the two was simply unreachable — and which one
3434
# depended on the machine, which is why CI failed on `compat:lua` on
3535
# Windows and `mcpplibs.capi:lua` on Linux. Never pin below that.
36-
default: '2026.9.30.1'
36+
default: '2026.10.8.1'
3737

3838
outputs:
3939
sandbox-key:

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

Lines changed: 2 additions & 2 deletions
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.30.1'
18+
default: '2026.10.8.1'
1919
image:
2020
description: >
2121
The runner label the job runs on (macos-15, xcode-27). It is part of the
@@ -72,7 +72,7 @@ runs:
7272
# latest-first: test binaries now link the toolchain's own libc++
7373
# (A1 root fix in flags.cppm), so new llvm releases are
7474
# self-consistent — the macOS job is the proof for each new default.
75-
xlings install llvm -y || xlings install llvm@20.1.7 -y
75+
xlings install llvm@23.1.3 -y || xlings install llvm -y
7676
LLVM_ROOT=$(find "$HOME/.xlings" -path "*/xpkgs/xim-x-llvm/*/bin/clang++" | head -1 | xargs dirname | xargs dirname)
7777
ls "$LLVM_ROOT/bin/clang++"
7878
"$LLVM_ROOT/bin/clang++" --version

‎.github/actions/use-built-mcpp/use.sh‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ fi
2929
# The toolchain mcpp.toml names for this host is the one the build used, so it
3030
# is the one whose payloads hold the binary's runtime.
3131
manifest_toolchain() {
32+
# Native ARM64 overrides the platform-wide GCC pin. Consumers must install
33+
# the same payload used by build.yml, including the first launch's runtime.
34+
if [ "$host" = linux-aarch64 ]; then
35+
local native
36+
native="$(awk '
37+
/^\[/ { in_tc = ($0 == "[target.aarch64-linux-gnu]"); next }
38+
in_tc && $1 == "toolchain" { gsub(/"/, "", $3); print $3; exit }
39+
' mcpp.toml)"
40+
if [ -n "$native" ]; then
41+
printf '%s\n' "$native"
42+
return
43+
fi
44+
fi
3245
local key
3346
case "$host" in
3447
macos-*) key=macos ;;

‎.github/tools/build_examples.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ BUILD=(
3030
# Built here for one reason worth the cost: it is the only example whose
3131
# CPU-only configuration exercises `cfg(accelerator = "none")` and two rule
3232
# packages in one build program, and both of those are engine paths that a
33-
# description cannot cover. Its `[toolchain] default = "llvm@22.1.8"` means
33+
# description cannot cover. Its `[toolchain] default = "llvm@23.1.3"` means
3434
# this job installs an LLVM payload it otherwise would not -- the CUDA leg
3535
# takes the clang route, because the nvcc route on the 12.9 line is refused
3636
# by nvcc's own front end and the 13.x line raises the driver floor to r580.

‎.github/tools/check_aarch64_llvm_deferral.sh‎

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
#!/usr/bin/env bash
2+
# Positive admission for the native Linux ARM64 LLVM payload.
3+
set -euo pipefail
4+
[[ "$(uname -s)" == Linux && "$(uname -m)" == aarch64 ]] || {
5+
echo 'FAIL: this gate requires a native Linux aarch64 host'; exit 1;
6+
}
7+
MCPP="${MCPP:-mcpp}"
8+
index_seed="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/seed_native_xim_index.py"
9+
seed_candidate() {
10+
[[ -n "${MCPP_NATIVE_XIM_INDEX:-}" ]] || return 0
11+
python3 "$index_seed" "${MCPP_HOME:-$HOME/.mcpp}" "$MCPP_NATIVE_XIM_INDEX"
12+
}
13+
verify_candidate() {
14+
[[ -n "${MCPP_NATIVE_XIM_INDEX:-}" ]] || return 0
15+
python3 "$index_seed" --verify "${MCPP_HOME:-$HOME/.mcpp}" "$MCPP_NATIVE_XIM_INDEX"
16+
}
17+
# Optional only for manual cross-repository admission; normal CI keeps main.
18+
seed_candidate
19+
"$MCPP" toolchain install llvm 23.1.3
20+
verify_candidate
21+
MCPP_E2E_LLVM_VERSION=23.1.3 source tests/e2e/_toolchain_env.sh
22+
[[ -x "$LLVM_ROOT/bin/clang++" ]] || { echo 'FAIL: LLVM frontend missing'; exit 1; }
23+
file -L "$LLVM_ROOT/bin/clang++" | grep -q 'ARM aarch64' || {
24+
echo 'FAIL: LLVM frontend is not native ARM64'; exit 1;
25+
}
26+
"$LLVM_ROOT/bin/clang++" --version
27+
work="$(mktemp -d)"
28+
report="${MCPP_NATIVE_REPORT_DIR:-${RUNNER_TEMP:-$work}/native-llvm-arm64}"
29+
mkdir -p "$report"
30+
trap 'rm -rf "$work"' EXIT
31+
export MCPP_HOME="$work/mcpp-home"
32+
seed_candidate
33+
"$MCPP" self config --mirror "${MCPP_E2E_MIRROR:-GLOBAL}"
34+
"$MCPP" self env --format json | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d["data"]["defaultToolchain"] == "llvm@23.1.3", d'
35+
verify_candidate
36+
(cd "$work" && "$MCPP" new native-probe)
37+
mkdir -p "$work/nativeabi/src"
38+
cat > "$work/nativeabi/mcpp.toml" <<'TOML'
39+
[package]
40+
name = "nativeabi"
41+
version = "0.1.0"
42+
[build]
43+
sources = ["src/*.c"]
44+
[targets.nativeabi]
45+
kind = "shared"
46+
soname = "libnativeabi.so.1"
47+
TOML
48+
printf 'int native_answer(int x) { return x + 1; }\n' > "$work/nativeabi/src/answer.c"
49+
cd "$work/native-probe"
50+
cat >> mcpp.toml <<'TOML'
51+
52+
[dependencies]
53+
nativeabi = { path = "../nativeabi" }
54+
TOML
55+
cat > src/main.cpp <<'CPP'
56+
import std;
57+
import std.compat;
58+
extern "C" int native_answer(int);
59+
int native_headers();
60+
struct alignas(16) Pair { unsigned long a, b; };
61+
static_assert(sizeof(Pair) == 16);
62+
int main() {
63+
auto memory = std::make_unique<int>(41);
64+
int value = 0;
65+
std::thread worker([&] { value = native_answer(*memory); });
66+
worker.join();
67+
bool caught = false;
68+
try { throw std::runtime_error("native"); }
69+
catch (const std::runtime_error&) { caught = true; }
70+
std::atomic<Pair> atom;
71+
atom.store(Pair{0, 0});
72+
Pair expected{0, 0};
73+
bool exchanged = atom.compare_exchange_strong(expected, Pair{42, 7});
74+
auto result = atom.load();
75+
void* raw = ::malloc(32);
76+
bool allocated = raw != nullptr;
77+
::free(raw);
78+
bool ok = value == 42 && caught && exchanged && result.a == 42
79+
&& result.b == 7 && allocated && native_headers() == 1;
80+
::printf("native-stdlib-cabi=%s\n", ok ? "ok" : "failed");
81+
return ok ? 0 : 1;
82+
}
83+
CPP
84+
cat > src/headers.cpp <<'CPP'
85+
#include <features.h>
86+
#include <stddef.h>
87+
#include <unistd.h>
88+
#include <pthread.h>
89+
int native_headers() { return 1; }
90+
CPP
91+
"$MCPP" build
92+
"$MCPP" run | tee "$report/runtime.log"
93+
grep -qF 'native-stdlib-cabi=ok' "$report/runtime.log"
94+
binary="$(find target/aarch64-linux-gnu -type f -path '*/bin/native-probe' | head -1)"
95+
[[ -n "$binary" ]] || { echo 'FAIL: default did not produce a native GNU artifact'; exit 1; }
96+
readelf -l "$binary" > "$report/program-headers.txt"
97+
readelf -d "$binary" > "$report/dynamic.txt"
98+
grep -q 'ld-linux-aarch64.so.1' "$report/program-headers.txt" || {
99+
echo 'FAIL: native default is not glibc-linked'; exit 1;
100+
}
101+
interpreter="$(sed -n 's/.*Requesting program interpreter: \(.*\)]/\1/p' "$report/program-headers.txt")"
102+
case "$interpreter" in
103+
"$MCPP_HOME"/registry/data/xpkgs/xim-x-glibc/*/lib*/ld-linux-aarch64.so.1) ;;
104+
*) echo "FAIL: GNU default uses an ambient loader: $interpreter"; exit 1 ;;
105+
esac
106+
"$interpreter" --list "$binary" > "$report/loader-resolution.txt"
107+
python3 - "$report/loader-resolution.txt" <<'PYLOADER'
108+
import pathlib, re, sys
109+
text = pathlib.Path(sys.argv[1]).read_text()
110+
assert not re.search(r'=> /(?:usr/lib|lib64?|usr/local/lib)/', text), text
111+
print('PASS: the native loader resolves no ambient system library')
112+
PYLOADER
113+
grep -q 'libnativeabi.so.1' "$report/dynamic.txt" || {
114+
echo 'FAIL: the C ABI consumer does not depend on the shared library'; exit 1;
115+
}
116+
# Replay the engine's effective header compile as a preprocess trace. The trace
117+
# must resolve libc headers through the payload, without an ambient /usr tree.
118+
python3 - "$report" <<'PYTRACE'
119+
import json, os, pathlib, re, shlex, subprocess, sys
120+
report = pathlib.Path(sys.argv[1])
121+
cdb = next(pathlib.Path('target/aarch64-linux-gnu').rglob('compile_commands.json'))
122+
entries = json.loads(cdb.read_text())
123+
entry = next(e for e in entries if e['file'].endswith('/headers.cpp'))
124+
args = entry.get('arguments') or shlex.split(entry['command'])
125+
# The driver named by the cold project's CDB must itself have a managed
126+
# ARM64 loader and dependency closure, independently of the program it emits.
127+
store = (pathlib.Path(os.environ['MCPP_HOME']) / 'registry/data/xpkgs').resolve()
128+
compiler = pathlib.Path(args[0]).resolve()
129+
relative = compiler.relative_to(store)
130+
assert relative.parts[:2] == ('xim-x-llvm', '23.1.3'), compiler
131+
132+
driver_env = dict(os.environ)
133+
driver_env.pop('LD_LIBRARY_PATH', None)
134+
driver_env.pop('LD_PRELOAD', None)
135+
136+
def capture(name, command):
137+
result = subprocess.run(command, text=True, capture_output=True, env=driver_env)
138+
text = result.stdout + result.stderr
139+
(report / name).write_text(text)
140+
assert result.returncode == 0, (command, text)
141+
return text
142+
143+
header = capture('compiler-elf-header.txt', ['readelf', '-hW', str(compiler)])
144+
assert re.search(r'Machine:\s+AArch64', header), header
145+
version = capture('compiler-version.txt', [str(compiler), '--version'])
146+
assert re.search(r'clang version 23\.1\.3(?:\s|$)', version), version
147+
program_headers = capture('compiler-program-headers.txt', ['readelf', '-lW', str(compiler)])
148+
match = re.search(r'Requesting program interpreter: ([^\]]+)', program_headers)
149+
assert match, program_headers
150+
loader = pathlib.Path(match.group(1)).resolve()
151+
loader_relative = loader.relative_to(store)
152+
assert loader_relative.parts[0] == 'xim-x-glibc', loader
153+
assert loader.name == 'ld-linux-aarch64.so.1', loader
154+
closure = capture('compiler-loader-resolution.txt', [str(loader), '--list', str(compiler)])
155+
assert not re.search(r'=> /(?:usr/lib|lib64?|usr/local/lib)/', closure), closure
156+
for path in re.findall(r'=> (/\S+)', closure):
157+
pathlib.Path(path).resolve().relative_to(store)
158+
print('PASS: cold LLVM frontend has native ARM64 managed loader and libraries')
159+
clean = []
160+
i = 0
161+
while i < len(args):
162+
arg = args[i]
163+
if arg in ('-o', '-MF', '-MT', '-MQ'):
164+
i += 2
165+
continue
166+
if arg in ('-c', '-MMD', '-MD', '-MP'):
167+
i += 1
168+
continue
169+
clean.append(arg)
170+
i += 1
171+
result = subprocess.run(clean + ['-E', '-H'], cwd=entry['directory'],
172+
text=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
173+
(report / 'include-trace.txt').write_text(result.stderr)
174+
assert result.returncode == 0, result.stderr
175+
headers = [m.group(1) for line in result.stderr.splitlines()
176+
if (m := re.match(r'^\.+ (.+)$', line))]
177+
assert any('xim-x-glibc' in path and path.endswith('/features.h') for path in headers), headers
178+
assert not any(re.match(r'/usr/(include|lib/gcc|local/include)(/|$)', path) for path in headers), headers
179+
print('PASS: libc include trace uses the managed payload')
180+
PYTRACE
181+
cat "$report/program-headers.txt" "$report/loader-resolution.txt" \
182+
"$report/compiler-version.txt" "$report/compiler-elf-header.txt" \
183+
"$report/compiler-program-headers.txt" "$report/compiler-loader-resolution.txt" \
184+
"$report/include-trace.txt"
185+
"$MCPP" pack --mode self-contained --format dir --message-format json > "$report/pack.json"
186+
bundle="$(python3 - "$report/pack.json" <<'PYPACK'
187+
import json, sys
188+
artifact = json.load(open(sys.argv[1]))['data']['artifacts'][0]
189+
assert artifact['type'] == 'directory', artifact
190+
print(artifact['path'])
191+
PYPACK
192+
)"
193+
# Directory deployment exercises the documented portable bundle entry point.
194+
cp -a "$bundle" "$work/deployed"
195+
(cd / && env -u LD_LIBRARY_PATH "$work/deployed/native-probe") | tee "$report/deployed.log"
196+
grep -qF 'native-stdlib-cabi=ok' "$report/deployed.log"
197+
(cd "$work" && "$MCPP" new musl-probe)
198+
cd "$work/musl-probe"
199+
"$MCPP" build --target aarch64-linux-musl --toolchain gcc@16.1.0-musl
200+
"$MCPP" run --target aarch64-linux-musl --toolchain gcc@16.1.0-musl
201+
printf '%s\n' 'PASS: native ARM64 LLVM installs, builds and runs'

0 commit comments

Comments
 (0)