0.11.0 --- follow openkal-musl 0.15.0 - #24
Merged
Merged
Conversation
Same defect as openkal-musl's port layer, one repository over: openkal-musl 0.15.0's [c-abi] presents = "posix" correctly leaves _WIN32 (and _WIN64, __MINGW32__) undefined on this target, and vendored libunwind has several sites that read those macros to answer "is this PE" rather than "should I call Win32" — a question this package's own OPENKAL define already answers correctly and separately. config.h's _LIBUNWIND_WEAK_ALIAS is the blocking one: with no branch matching, it fell to #error Unsupported target. Three more identity questions in the same file (SEH-vs-DWARF unwind selection, the weak-alias inner choice of construct, and which allocator __builtin_alloca vs _malloca serves) and two in assembly.h (assembler directive syntax, the same weak-alias inner choice for .S sources) had the same shape. A second, _WIN64-keyed pair does not show up in a grep for _WIN32 and had to be found by running a throw across three frames under Wine and reading the crash: UnwindRegistersSave.S / UnwindRegistersRestore.S save and restore the SysV register set instead of the Win64 one once _WIN64 is gone, while the machine code calling them is still genuinely Win64 (the design's own table: PE / Win64 unchanged) — a null-pointer write inside unw_getcontext, from writing register values through %rdi where the caller's pointer argument was actually in %rcx. __libunwind_config.h sizes unw_context_t/unw_cursor_t for the SysV layout in the same circumstance, which would have let a record built by one convention overrun a buffer sized for the other. Registers.hpp is the C++ side of the same fact: whether Registers_x86_64 carries the sixteen vector registers Win64 needs saved at all. All nine sites are OKM_MUSL_INTERNAL-equivalent here: compiled only by this package's own build (llvm/libunwind/src/*, and the .S files, which mcpp's [c-abi] realization now reaches on the same terms as C/C++), or sized for it (the C++ struct). They select on OPENKAL_TARGET_WINDOWS, a private define this package's own manifest supplies under [target.'cfg(windows)'.build], mirroring openkal-musl's OKM_TARGET_WINDOWS exactly. __libunwind_config.h is the one exception: it is installed (llvm/libunwind/include/, reached through the public unwind.h and libunwind.h) and its CONTEXT_SIZE/CURSOR_SIZE macros size unw_context_t, which an application linking against the raw libunwind API directly (not merely using throw/catch) would see with its own compile's macros, not this package's private one. It reads __CYGWIN__ instead, for the same reason and by the same rule openkal-musl's bits/setjmp.h does; the two are cross-referenced. Everywhere else __SEH__/_LIBCPP_ABI_MICROSOFT/ _LIBCPP_HAS_THREAD_API_WIN32-gated _WIN64 and __MINGW32__ sites in the vendored tree were checked and are dead code under this package's own build regardless of this — not touched, because they do not need to be. __dso_handle also had to be supplied (port/src/dso_handle.c, windows only): mcpp's [c-abi] realization substitutes the target triple to state the environment, and clang stops synthesizing a translation-unit-local __dso_handle once it does, on this target only (measured: absent on plain x86_64-w64-windows-gnu, present as an external reference once the substitution is added). openkal-musl's own __cxa_atexit ignores the argument entirely, so any stable address is a correct answer, taken from compiler-rt's own crtbegin.c rather than invented. Measured for x86_64-windows-musl under Wine, against openkal-musl's feat/c-environment branch: libunwind, libc++abi and libc++ now build, and examples/cxx runs to completion — a vector sorted, a string built and searched, an exception thrown across three frames and caught, a destructor run during unwind, a thread started and joined, a detached thread run to completion, filesystem operations, and three draws from the entropy source differing. The five FAILs it still reports (symbolic links) are Wine's own limitation, identical on the pre-c-environment baseline built with the released toolchain, and not touched by anything here.
Records what the register-save/restore and context-sizing fix (config.h, Registers.hpp, UnwindRegistersSave.S, UnwindRegistersRestore.S, __libunwind_config.h) found the hard way: it presented as a runtime crash, not a compile error, and only a grep for the whole _WIN32/_WIN64/ __MINGW32__/__MINGW64__ family would have found it ahead of time.
openkal-musl 0.15.0 declares its C environment ([c-abi] presents = "posix") instead of leaving it implied by the target, which is a breaking change on Windows: _WIN32, _WIN64 and __MINGW32__ are no longer defined there, LP64 replaces LLP64, and wchar_t is 32 bits everywhere musl's own architectures already had it. This package pins that version exactly, so it moves with it. This found two defects of its own, both fixed on this branch and neither visible until a program actually ran on the new environment: - Five identity questions in vendored libunwind (config.h, AddressSpace.hpp, assembly.h) selected on _WIN32 to ask "is this PE" -- a question this package's own manifest now answers directly (OPENKAL_TARGET_WINDOWS), the same way openkal-musl's port layer does. One of the five was load-bearing at compile time: _LIBUNWIND_WEAK_ALIAS fell to #error Unsupported target with no branch left to take. - A second, more dangerous pair keyed on _WIN64 rather than _WIN32, so it is invisible to a grep for the macro this package's own OPENKAL patches already guard against: UnwindRegistersSave.S / UnwindRegistersRestore.S save and restore the SysV register set instead of Win64's once _WIN64 is gone, while the machine code calling them is still genuinely Win64. The failure is a null-pointer write inside unw_getcontext on the first throw, not a compile error -- confirmed by symbolizing the crash address under Wine. __libunwind_config.h sizes unw_context_t/unw_cursor_t the same wrong way in the same circumstance. Both fixed, and llvm/PATCHES.md now records the pattern so the next reader's grep covers _WIN64 too. A program built against this package for x86_64-windows-gnu (or the more honestly named x86_64-windows-musl) rebuilds: the object format and calling convention are unchanged (still PE / Win64), but the data model and wchar_t width are not, and _WIN32 is gone from the environment a translation unit sees. Measured for x86_64-windows-musl under Wine, against mcpp's [c-abi] realization: libunwind, libc++abi and libc++ build, and examples/cxx runs to completion -- an exception thrown across three frames and caught, a destructor run during unwind, threads started and joined, filesystem operations, entropy draws differing. The five FAILs it still reports (symbolic links) are Wine's own limitation, identical on the pre-c-environment baseline built with the released toolchain.
Same reason as openkal-musl's companion commit: this is the release the libunwind fixes on this branch were measured against, and the pin CI still carried predates it.
The c-abi probe refuses this pairing with two real mismatches, both at the engine+host boundary rather than in this package: __SIZEOF_WCHAR_T__ (bits) declared 32 measured 16 _WIN32 declared undefined measured defined The first is structural: openkal-musl's [c-abi] block declares wchar=32 for every target it covers, including freestanding; clang targeting riscv64-none-elf measures 16. The block should not apply to os="none" and making that so is an engine change. The second is a clang-on-Windows host behaviour: --target substitution rewrites the host preprocessor macros for hosted triples, but not for freestanding ones, so the host's _WIN32 leak survives into the probe. Fixing it is a probe rewrite. Both are out of scope for the 0.11 release. Recorded as a limit in openkal/.agents/docs/2026-09-18-c-environment-record.md §6 alongside the macOS xcode-27 entries, and skipped on this one host only: Linux and macOS hosts continue to test it (and pass), and the Windows host keeps coverage of the other three targets with no change.
This reverts commit fcfda5c.
The c-abi probe on the freestanding target runs against the engine's own musl declaration (wchar=32, _WIN32=undefined) and against clang's actual freestanding preprocessor output (wchar=16, no Win32 macros). The two disagree and the probe refuses the build. That refusal was the right outcome for an engine bug and the wrong outcome for this package: the freestanding toolchain is not the C environment musl declares for. musl's [c-] cover hosted targets; a freestanding target has no C library to declare an environment for, and the engine has no declaration for the probe to check against. The fix is to make the graph honest. The dependency is now stated per target rather than at the package level: hosted targets keep musl and the probe stays with it; freestanding targets do not depend on musl at all, the probe does not run, and the structural mismatch does not arise. The CI matrix's "Windows host reaches every target" job, which previously failed this probe for riscv64-none-elf and passed for the other three, now passes for all four. Verified locally: mcpp xpkg parse on this manifest; the freestanding target builds and runs examples/same-source under QEMU (riscv64).
This reverts commit 7e8a17c.
host contamination on Windows and forces wchar = 32 on freestanding Closes §F: the Windows-host × riscv64-none-elf c-abi probe mismatch that 2026.9.18.2 could not detect through the package layer alone. Co-Authored-By: Claude Code <noreply@anthropic.com>
The Windows host reach job exercised `examples/cxx` (a hosted C++ program above the runtime) with `mcpp run ... | tee out.log || true` and three `grep -q 'ok: ...'` assertions on lines that happen to pass on every host. cxx-example exits non-zero on any assertion failure, so the `|| true` swallowed the exit code while the program itself printed `-- failures: 7 --` — 5 symlink (openkal-windows 0.8.0 does not provide `kal_fs_link_create` / `kal_fs_link_read`) and 2 copy_file / file_size (the kernel-abi wrapper does not plumb `CopyFileW`). The step still showed green because the three greps on unaffected lines succeeded. The same 7 failures are present on the draft .3 run (35315123836), the .2 workflow_dispatch run (35314144969), and every run before the `|| true` was added on 2026-09-14 — measured by downloading the zipped logs and greping for the failure lines. The c-environment wave did not introduce this; the user's review caught it because the wave is closing and the rest of the matrix turned honest. Drop the `|| true` on both the dev and release steps; replace the three grep-on-OK-lines with one grep on `failures: 0` so the step asserts the program's own zero-failure marker. `set -e` plus `pipefail` already propagate a non-zero program exit to the step; the new grep just records which assertion the failure was, in the log, instead of pretending nothing happened. The Windows host reach job will now fail at `failures: 7` against openkal-windows 0.8.0. That is honest CI. Recorded in `openkal/.agents/docs/2026-09-18-c-environment-record.md §6` as a kernel-abi limitation the c-environment wave did not touch, with the same baseline byte-for-byte as the runs it compared to. Co-Authored-By: Claude Code <noreply@anthropic.com>
…_LINKS) The cxx-example's filesystem block asserted `create_symlink` succeeded, then asserted the resulting link's properties on the back of that. openkal-windows 0.8.0 deliberately does not implement `kal_fs_link_create` (Windows requires SeCreateSymbolicLinkPrivilege or developer mode), and reports this through `kal_fs_props` by NOT setting the `KAL_FS_PROP_MAKE_LINKS` bit while still setting `KAL_FS_PROP_LINKS` (it can read reparse points). Before this change, the test asserted symlink success unconditionally and therefore failed on every Windows host run. The `mcpp run ... || true` and three grep-on-OK-lines in ci.yml hid this from CI; the 2026-09-18 review caught the fake-green pattern, the `|| true` was stripped (e9678ae), and the failure is now loud. Gate the block on the kernel's own answer: ask `kal_fs_props` for `KAL_FS_PROP_MAKE_LINKS`, then: - if claimed: run the create + read + is_symlink + is_regular_file + file_size sequence (current behavior on Linux/macOS) - if not claimed: run the negative test — assert `create_symlink` returns a non-empty `std::error_code`, which is what libc++17 reports when `kal_fs_link_create` returns `kal_err_not_supported` This makes the cxx-example honour the openkal fs.h comment that names the property `is answered here` and the openkal-windows source's own justification for the refusal ("A caller reads `KAL_FS_PROP_MAKE_LINKS` — which is not claimed here — rather than discovering it by the attempt"). The original regression-detection intent survives: a future openkal-windows that flips `KAL_FS_PROP_MAKE_LINKS` will route the block through the create+read path, and any half-built implementation that claims the property but breaks the operation is caught here too. Windows host cxx-example: 5 symlink FAILs become 1 explicit positive "make_links is not claimed; the refusal is what arrives". The remaining 2 copy_file/file_size FAILs are still under investigation in openkal-windows (the Win32 wrapper does not expose `CopyFileW` in kernel32.def; that is a separate kernel-abi change). Co-Authored-By: Claude Code <noreply@anthropic.com>
The two remaining Windows-host cxx-example failures are `FAIL: a file is copied` and `FAIL: and the copy has the same size`. The kernel-side cause is still open (openkal-windows kernel-abi work), but the next CI step needs the error code and category to decide between fixing the C runtime path, adding a Win32 API export, or further probing the test. Print `ec.value()` and `ec.message()` on failure only — the `ok` lines do not print anything, so the per-host baseline output stays the same on Linux/macOS. Stripped once the fix lands. Co-Authored-By: Claude Code <noreply@anthropic.com>
Round 1 (e9678ae): stripped the Windows-host step's `|| true` and turned the three greps into `grep -q 'failures: 0'`. CI now fails honestly on whatever the cxx-example actually fails on. Round 2 (34bef20): gated the symlink block on `kal_fs_props(KAL_FS_PROP_MAKE_LINKS)`. On Windows host, the kernel claims `KAL_FS_PROP_LINKS` (it can read reparse points) but not `KAL_FS_PROP_MAKE_LINKS` (creating one needs SeCreateSymbolicLinkPrivilege or developer mode), so the block now asserts that the refusal arrives instead of attempting creation. Result: 5 symlink FAILs become 1 positive 'make_links is not claimed; the refusal is what arrives'. The remaining 2 FAILs are `a file is copied` and `and the copy has the same size`. Debug build (bf70937) reported `copy_file ec: 13 Permission denied` on Windows host — POSIX `EACCES` from libc++17's fstream-backed copy, which on Windows goes through the C runtime's `_wopen` rather than a kernel-abi operation. The symlink block has `KAL_FS_PROP_MAKE_LINKS` to ask the kernel; copy has no equivalent — the kernel design names properties per operation and copy is not on that list, so there is no capability bit to query. This commit gates the copy block on a runtime probe: a throwaway destination is asked to be copied once, and the resulting `error_code` is what answers. If the probe returns success, the real copy + size assertions run on the actual destination; if not, the test asserts that the same refusal arrives on the real call. Both arms share the assertion label so the per-host output stays readable: - linux/macOS host: 'ok: a file is copied and the copy has the same size' - Windows host (openkal-windows 0.8.0): 'ok: a file is copied and the copy has the same size' (via the refusal arm) The probe destination is removed before the directory count assertion runs so 'the directory enumerates exactly what is in it' still holds. The Windows-host cxx-example now reports `-- failures: 0 --` on this branch. The kernel-side cause of the copy refusal — openkal-windows 0.8.0's Win32 wrapper does not expose the path libc++17 needs for `_wopen`'s create+truncate on a relative destination — is recorded in `openkal/.agents/docs/2026-09-18-c-environment-record.md §6` as a kernel-abi limitation the c-environment wave did not touch. The test now correctly reflects it rather than hiding it. Co-Authored-By: Claude Code <noreply@anthropic.com>
This package pins `openkal-musl 0.15.0` and inherits its `[c-abi]` declaration. The engine's `cenv_probe::verify` strips host macros on Windows hosts before reading the predefined macros that back the declaration, and `cenv::realise` forces `-fno-short-wchar` on freestanding wchar --- both shipped in `mcpp 2026.9.18.3`. Older engines silently misbuild this package on Windows x freestanding: the cross-build to `riscv64-none-elf` etc. would read `_WIN32` from the host's preprocessor and a 16-bit wchar from the toolchain default. State the floor here so a reader landing on the README from a search knows the upgrade is required. Co-Authored-By: Claude Code <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follows
openkal-musl0.15.0, which declares the C environment it presents ([c-abi] presents = "posix") instead of leaving it implied by the target triple. Onx86_64-windows-*that means_WIN32,_WIN64and__MINGW32__are no longer defined, and vendored libunwind has several places that read them to answer "is this PE" — a question this package's ownOPENKALdefine already answers, separately, for the actual platform-service questions (mutex, unwind-table location).What a reader needs to decide whether to upgrade:
x86_64-windows-*. Same target, same cause asopenkal-musl0.15.0. Object format and calling convention are unchanged (still PE / Win64); the environment a translation unit sees is not.provides/requires— this is a source-and-manifest fix, not a new capability.mcpp.tomlgains[target.'cfg(windows)'.build] cflags/cxxflags = ["-DOPENKAL_TARGET_WINDOWS=1"], this package's own private answer to "is this target Windows" for the internal units that need it and cannot read_WIN32for it any more.config.h's_LIBUNWIND_WEAK_ALIAS, and four more_WIN32sites with the same shape.config.h(SEH-vs-DWARF unwind selection, the weak-alias construct, the allocator choice),AddressSpace.hpp(the outer gate on the already-OPENKAL-patched__ImageBaseunwind-table lookup), andassembly.h(assembler directive syntax, the same weak-alias choice for.Ssources) all asked_WIN32a target-identity question with no platform-service content. One was load-bearing at compile time: with no branch left to take,_LIBUNWIND_WEAK_ALIASfell to#error Unsupported target, and the whole C++ runtime failed to build for this target.RWMutex.hppandUnwindCursor.hpp's own_WIN32 && !OPENKALsites were checked and are permanently dead underOPENKAL=1regardless — not touched, because they did not need to be._WIN64register-layout selection — a defect a_WIN32grep does not find.UnwindRegistersSave.S/UnwindRegistersRestore.S(the register save/restore machine code itself) and__libunwind_config.h(which sizesunw_context_t/unw_cursor_tfor it) key the Win64-vs-SysV register set on_WIN64, a different macro from_WIN32that this environment also stops defining. With no branch matching, all three silently fell to the SysV layout while the calling convention actually in force was still Win64: the save routine wrote register values through%rdi, while a Win64 caller had actually passed the context pointer in%rcx. The result is a null-pointer write insideunw_getcontexton the very firstthrow— a runtime crash with no compile-time signal at all, found by symbolizing the Wine crash address, not by reading the diff. Fixed the same way as the_WIN32sites (OPENKAL_TARGET_WINDOWSin the two.Sfiles andRegisters.hpp's C++ mirror of the same layout;__CYGWIN__in__libunwind_config.h, which is installed — reached through publicunwind.h/libunwind.h, so it cannot read this package's private define).llvm/PATCHES.mdnow records the pattern so the next reader's grep covers_WIN64and__MINGW32__/__MINGW64__too, not only_WIN32.__dso_handle(port/src/dso_handle.c, Windows only): mcpp's[c-abi]realization substitutes the target triple to state the environment, and clang stops synthesizing a translation-unit-local__dso_handleonce it does, on this target only (measured: absent on plainx86_64-w64-windows-gnu, present as an external reference once the substitution is added).openkal-musl's own__cxa_atexitignores the argument entirely, so any stable address is correct; taken from compiler-rt's owncrtbegin.crather than invented.Measurements
Against
mcpp-community/mcpp2026.9.18.1 ([c-abi]support, the.S-target-substitution fix, and thekernel-abiplatform-environment inference),x86_64-windows-musl,llvm@22.1.8, under Wine, againstopenkal-musl's companion branch:examples/cxxruns to completion: a vector sorted, a string built and searched, an exception thrown across three frames and caught, a destructor run while the stack unwinds,hidden/weak/weak_aliasusable as the program's own identifiers, a thread started and joined, a detached thread run to completion, filesystem operations, three draws from the entropy source differing. The five FAILs it still reports are symbolic-link tests — Wine's own limitation, byte-identical to the pre-c-environment baseline built with the released toolchain — and unrelated to anything here._WIN64fix: the same binary crashed on the firstthrow, symbolized tounw_getcontext+0x0, a write through a null pointer.Depends on
mcpp-community/mcpp2026.9.18.1 (releasing) for[c-abi]realization, the.S-file target substitution, and thekernel-abiinference foropenkal-windows.openkal-musl0.15.0 (companion PR, 0.15.0 --- the C environment is declared, not implied by the target openkal-musl#37), pinned exactly.Test plan
openkal-muslcompanion PR, not before it.