Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ The decisions below are derived from these rules. Each rule names its source in
| `dialect_cxxflags`, `c_standard`, `linkage`, `target`, `cxx_runtime`, `dependency_linkage`, `macos_deployment_target` | root manifest only | graph-wide | n/a | consistent |
| `ios_deployment_target` | parsed and inherited | **refused** | n/a | **F3** |

**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`.

### 3.2 Inheritance placement: F1, F2, F8

**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.
Expand Down
1,308 changes: 1,308 additions & 0 deletions .agents/docs/2026-09-25-issues-693-696-triage-and-repair-plan.md

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion .agents/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ superseded_by: 2026-09-07-....md # when status is superseded
---
```

309 records.
310 records.

## By subject

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

### design

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

### 2026-09

- [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
- [Workspace inheritance, flag scoping and the published form: a unified repair plan (#690)](2026-09-25-issue-690-workspace-build-inheritance-consistency.md) — landed
- [#690: self-review before release, engine and ecosystem](2026-09-25-issue-690-self-review.md) — landed
- [#690: implementation plan](2026-09-25-issue-690-implementation-plan.md) — landed
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/bootstrap-mcpp/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ inputs:
# `package.name`, so one of the two was simply unreachable — and which one
# depended on the machine, which is why CI failed on `compat:lua` on
# Windows and `mcpplibs.capi:lua` on Linux. Never pin below that.
default: '2026.9.20.1'
default: '2026.9.26.2'
cache-target:
description: also restore/save target/ (build artifacts + BMIs)
required: false
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/setup-macos-llvm/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ inputs:
# Floor imposed by the index, not a routine bump — see
# .github/actions/bootstrap-mcpp/action.yml for why 0.4.69 is required
# (two packages named `lua` in one repo need openxlings/xlings#381).
default: '2026.9.20.1'
default: '2026.9.26.2'
image:
description: >
The runner label the job runs on (macos-15, xcode-27). It is part of the
Expand Down
130 changes: 130 additions & 0 deletions .github/tools/check_unicode_paths.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env bash
# check_unicode_paths.sh: mcpp#693 on Windows: a project in a directory whose
# name is not ASCII builds and runs on every toolchain row, and the files mcpp
# writes for other tools hold that name in UTF-8.
#
# THE SHAPE OF THE FAILURE THIS GUARDS. Up to mcpp 2026.9.25.1 mcpp held paths in
# the process ANSI code page. A name that page could spell (U+00E9 on code page
# 1252, every Chinese name on code page 936) reached compile_commands.json as
# ANSI bytes and failed every build with
# error: internal: unhandled exception: [json.exception.type_error.316]
# and a name it could not spell failed with a narrowing exception. mcpp.exe now
# declares the UTF-8 code page, build programs are linked with the same
# declaration, and the response files of the MSVC tools begin with a byte order
# mark. Each of those is a separate way back to the failure, which is why every
# row runs in every directory.
#
# Rows: llvm (clang++, the Windows default), msvc (cl.exe) and mingw (gcc@16.1.0
# for x86_64-windows-gnu), each in an ASCII directory, a directory named
# `caf` + U+00E9 (inside code page 1252) and one named U+6D4B U+8BD5 (outside
# it). One more project runs a build.mcpp that reads its own directory from the
# environment and prints it back as an include directory: the round trip of a
# path through a build program. Names are built from bytes, so this file stays
# ASCII.
#
# Usage: MCPP=<mcpp.exe> bash .github/tools/check_unicode_paths.sh
set -uo pipefail

: "${MCPP:?set MCPP to the mcpp.exe under test}"
ROOT=$(mktemp -d)
CAFE="caf$(printf '\xc3\xa9')"
CJK="$(printf '\xe6\xb5\x8b\xe8\xaf\x95')"
CAFE_ANSI="caf$(printf '\xe9')"
failed=0

ok() { echo " ok $*"; }
bad() { echo " FAIL $*"; failed=1; }

# write_project DIR TOOLCHAIN_LINES
write_project() {
mkdir -p "$1/src"
printf '[package]\nname = "unicodeprobe"\nversion = "0.1.0"\n\n%b\n' "$2" > "$1/mcpp.toml"
cat > "$1/src/main.cpp" <<'EOF'
import std;
int main() {
std::println("unicode probe");
return 0;
}
EOF
}

# The generated file holds the directory name in UTF-8, and never in the ANSI
# code page.
check_bytes() {
local file=$1 name=$2 row=$3
[ -f "$file" ] || { bad "$row: no $(basename "$file")"; return; }
if ! LC_ALL=C grep -qF "$name" "$file"; then
bad "$row: $(basename "$file") does not hold the directory name in UTF-8"
fi
if [ "$name" = "$CAFE" ] && LC_ALL=C grep -qF "$CAFE_ANSI" "$file"; then
bad "$row: $(basename "$file") holds the ANSI spelling of the directory name"
fi
}

rows=(
'llvm|[toolchain]\nwindows = "llvm@20.1.7"|'
'msvc|[toolchain]\nwindows = "msvc@system"|'
'mingw|[toolchain]\ndefault = "gcc@16.1.0"|--target x86_64-windows-gnu'
)

for name in ascii "$CAFE" "$CJK"; do
for row in "${rows[@]}"; do
IFS='|' read -r rid tc args <<<"$row"
dir="$ROOT/$name/$rid"
label="$rid in '$name'"
write_project "$dir" "$tc"
cd "$dir" || { bad "$label: cannot enter the directory"; continue; }
# shellcheck disable=SC2086
if ! "$MCPP" build $args > build.log 2>&1; then
bad "$label: the build failed"; tail -15 build.log | sed 's/^/ /'; continue
fi
# shellcheck disable=SC2086
out=$("$MCPP" run $args 2>&1)
if ! grep -q 'unicode probe' <<<"$out"; then
bad "$label: the program did not run"; printf '%s\n' "$out" | tail -5 | sed 's/^/ /'
continue
fi
if [ "$name" != ascii ]; then
ninja=$(find target -name build.ninja -newer mcpp.toml | head -1)
check_bytes "$ninja" "$name" "$label"
check_bytes compile_commands.json "$name" "$label"
fi
ok "$label"
done
done

# A path through a build program: MCPP_MANIFEST_DIR in, `mcpp:include-dir` out,
# and the header found at the directory the program printed.
dir="$ROOT/$CJK/buildprogram"
mkdir -p "$dir/src" "$dir/inc"
printf '[package]\nname = "unicodebp"\nversion = "0.1.0"\n\n[toolchain]\nwindows = "llvm@20.1.7"\n' > "$dir/mcpp.toml"
printf '#define UNICODE_BP 42\n' > "$dir/inc/unicode_bp.h"
cat > "$dir/build.mcpp" <<'EOF'
#include <cstdio>
#include <cstdlib>
int main() {
const char* here = std::getenv("MCPP_MANIFEST_DIR");
if (!here) return 1;
std::printf("mcpp:include-dir=%s/inc\n", here);
return 0;
}
EOF
cat > "$dir/src/main.cpp" <<'EOF'
#include "unicode_bp.h"
import std;
int main() {
std::println("build program {}", UNICODE_BP);
return 0;
}
EOF
cd "$dir"
if "$MCPP" build > build.log 2>&1 && "$MCPP" run 2>&1 | grep -q 'build program 42'; then
ok "a path through build.mcpp in '$CJK'"
else
bad "a path through build.mcpp in '$CJK'"; tail -15 build.log | sed 's/^/ /'
fi

cd / && rm -rf "$ROOT"
[ "$failed" = 0 ] && echo "OK: every row builds in every directory" && exit 0
echo "FAIL: at least one row did not build in a directory whose name is not ASCII"
exit 1
2 changes: 1 addition & 1 deletion .github/workflows/bootstrap-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
# Dormant (workflow_dispatch only), but kept in step with the rest —
# check_version_pins.sh holds it there. Floor: 0.4.69, below which the
# index cannot resolve two packages that share a short name.
XLINGS_VERSION: '2026.9.20.1'
XLINGS_VERSION: '2026.9.26.2'
steps:
- uses: actions/checkout@v4

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci-fresh-install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ jobs:
env:
XLINGS_NON_INTERACTIVE: '1'
run: |
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.20.1
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"

- name: Install mcpp and config mirror
Expand Down Expand Up @@ -312,7 +312,7 @@ jobs:

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

- name: Install mcpp and config mirror
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-linux-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ jobs:

- name: Bootstrap xlings + released mcpp
run: |
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.20.1
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
export PATH="$HOME/.xlings/subos/current/bin:$PATH"
xlings update
xlings install mcpp -y -g
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/ci-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,17 @@ jobs:
# restore the LLVM default for the remaining steps
"$MCPP_SELF" toolchain default llvm@20.1.7

# mcpp#693: a project in a directory whose name is not ASCII, inside the
# runner's code page 1252 and outside it, on the llvm, MSVC and MinGW rows,
# plus a path carried through build.mcpp. Each row reaches a different
# consumer of mcpp's text: Ninja's build file, the MSVC response files,
# and the MinGW driver.
- name: "Paths: non-ASCII project directories on every toolchain row (mcpp#693)"
shell: bash
run: |
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
MCPP="$MCPP_SELF" bash .github/tools/check_unicode_paths.sh


# GRAPHICS ON THIS HOST, BUILD ONLY, AND THAT IS THE WHOLE CLAIM.
#
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/cross-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ jobs:
# release assets were uploaded in a broken state (records present,
# blobs missing → 404 on GET); re-uploaded clean. The stale-INDEX
# half is handled by the marker-clear below.
XLINGS_VERSION: '2026.9.20.1'
XLINGS_VERSION: '2026.9.26.2'
run: |
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \
Expand Down Expand Up @@ -289,7 +289,7 @@ jobs:
- name: Bootstrap mcpp via xlings
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: '2026.9.20.1'
XLINGS_VERSION: '2026.9.26.2'
run: |
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/openkal-cross.yml
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ jobs:
for t in tests/e2e/285_*.sh tests/e2e/286_*.sh tests/e2e/287_*.sh \
tests/e2e/288_*.sh tests/e2e/289_*.sh tests/e2e/291_*.sh \
tests/e2e/292_*.sh tests/e2e/293_*.sh tests/e2e/294_*.sh \
tests/e2e/738_*.sh; do
tests/e2e/738_*.sh tests/e2e/778_*.sh; do
echo "=== $t ==="
bash "$t" 2>&1 | tee "$(basename "$t").log" || true
rc=${PIPESTATUS[0]}
Expand Down Expand Up @@ -630,4 +630,15 @@ jobs:
"OK: the list answers what can be built, not what has a payload" || fail=1
check 738_a_graph_supplied_target_closes_the_hosts_own_search.sh \
"PASS: 738 a graph-supplied target closes the host's own search" || fail=1
# mcpp#696, the link-side twin of 738: both legs, because the one
# that separates the engines is the refusal, and a skip of either
# prints the final line all the same.
check 778_a_graph_link_searches_no_host_directory.sh \
"ok: -lm is answered by openkal-musl's own archive, and the program runs" || fail=1
check 778_a_graph_link_searches_no_host_directory.sh \
"ok: an unanswered -lm fails, and the note names openkal-musl 0.19.2" || fail=1
check 778_a_graph_link_searches_no_host_directory.sh \
"ok: aarch64-linux-musl links -lm from the graph and runs under qemu-aarch64" || fail=1
check 778_a_graph_link_searches_no_host_directory.sh \
"ok: a host directory in ldflags is refused, by name" || fail=1
[ "$fail" = 0 ] || exit 1
14 changes: 7 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
# Pin xlings to a known-good version. The upstream install
# script always grabs `latest` (no version override), so we
# download + self-install manually to avoid broken releases.
XLINGS_VERSION: '2026.9.20.1'
XLINGS_VERSION: '2026.9.26.2'
run: |
if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
Expand Down Expand Up @@ -314,7 +314,7 @@ jobs:
- name: Bootstrap mcpp via xlings
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: '2026.9.20.1'
XLINGS_VERSION: '2026.9.26.2'
run: |
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \
Expand Down Expand Up @@ -385,7 +385,7 @@ jobs:
# below are pinned to the same version as XLINGS_VERSION; they are
# NOT interpolated from it, so check_version_pins.sh scans for them
# explicitly (they were absent from the old lock-step comment).
XLA="xlings-2026.9.20.1-linux-aarch64.tar.gz"
XLA="xlings-2026.9.26.2-linux-aarch64.tar.gz"
# NOT fetch_release.sh: this asset is OPTIONAL and the `if` is the
# point — an arch with no prebuilt xlings must fall through quietly,
# while the helper retries a 404 five times before giving up. The one
Expand All @@ -394,9 +394,9 @@ jobs:
# cover it.
if curl -fsSL --retry 3 --retry-delay 2 --retry-all-errors \
--connect-timeout 20 --max-time 600 -o "/tmp/$XLA" \
"https://github.com/openxlings/xlings/releases/download/v2026.9.20.1/$XLA"; then
"https://github.com/openxlings/xlings/releases/download/v2026.9.26.2/$XLA"; then
tar -xzf "/tmp/$XLA" -C /tmp
XLBIN=$(find /tmp/xlings-2026.9.20.1-linux-aarch64 -path '*/bin/xlings' -type f | head -1)
XLBIN=$(find /tmp/xlings-2026.9.26.2-linux-aarch64 -path '*/bin/xlings' -type f | head -1)
if [ -n "$XLBIN" ]; then
mkdir -p "$STAGING/$WRAPPER/registry/bin"
cp "$XLBIN" "$STAGING/$WRAPPER/registry/bin/xlings"
Expand Down Expand Up @@ -474,7 +474,7 @@ jobs:
- name: Bootstrap mcpp via xlings
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: '2026.9.20.1'
XLINGS_VERSION: '2026.9.26.2'
run: |
if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then
WORK=$(mktemp -d)
Expand Down Expand Up @@ -657,7 +657,7 @@ jobs:
shell: bash
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: '2026.9.20.1'
XLINGS_VERSION: '2026.9.26.2'
run: |
# Captured before the `cd` below, in POSIX form: this step never
# returns to the workspace, and GITHUB_WORKSPACE is a backslash
Expand Down
Loading
Loading