Skip to content

A compiler is refused only when the realisation needs a token it cannot take - #671

Merged
Sunrisepeak merged 1 commit into
mainfrom
fix/gcc-refused-for-empty-cabi-realisation
Sep 18, 2026
Merged

Sunrisepeak merged 1 commit into
mainfrom
fix/gcc-refused-for-empty-cabi-realisation

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

Summary

Three regressions from 2026.9.18.1, found by openkal-musl and
openkal-llvm-runtime CI within hours of that release, all one shape: the
engine treated "the target already satisfies this declaration" and "this
declaration cannot be realised" as the same case.

Separate from #670 on purpose — that PR is a release-machinery fix
(release.yml); this is an engine fix. Mixing them would make either harder
to review, and this one gates three downstream repositories, so it needs to
ship as its own release regardless of #670's timing.

The three regressions, and the one rule they dissolve into

  1. GCC on Linux was refused for merely DECLARING [c-abi], before
    realisation ran. openkal-musl 0.15.0's own Linux declaration
    (presents = "posix", data-model = "arch-default", wchar = 32) realises
    to nothing — Linux's default triple already is that — so nothing about
    it needed Clang. Every GCC user of openkal-musl on Linux lost the package
    for a substitution nothing asked GCC to perform.

  2. macOS does not satisfy presents = "posix" by default — caught by
    the verification probe on a real build: declared __unix__ defined,
    measured undefined. Apple's clang predefines __APPLE__/__MACH__ on
    its default triple, never __unix__.

  3. A freestanding target had no realisation for presents = "posix" at
    all
    , refused outright — blocking openkal-llvm-runtime on
    riscv64-none-elf before it reached anything else.

(1) is fixed by reordering: cenv::realise (a pure function of the
declaration and the target, not the compiler) runs first, and the
Clang-only gate fires only when the result is non-empty. Windows is
unchanged — its Cygwin-flavoured substitution is non-empty, so a non-Clang
compiler is still refused there.

(2) and (3) dissolve into one rule, simpler than what it replaces:
realising presents = "posix" means the same observable fact everywhere —
__unix__ defined, _WIN32 not — and targets differ only in what it
costs. Linux: nothing. macOS and freestanding: one token, -D__unix__
neither already defines it, for the identical reason. Windows: the
Cygwin-flavoured substitution.

Known cost, not hidden: portable code written
#ifdef __unix__ ... #elif defined(__APPLE__) now takes the Unix branch on
macOS too. Left to the mcpp-index 30-member measurement to weigh, per the
coordinator's own framing — flip it there with data if the cost exceeds the
benefit, not here in advance.

Tests

  • tests/unit/test_cenv.cppMacosPosixArchDefaultDefinesUnix (was
    MacosPosixArchDefaultIsANoOp, now asserts the -D__unix__ token and
    expectation pair), FreestandingPosixDefinesUnix (new — was
    FreestandingAcceptsOnlyNone, which asserted presents = "posix" on a
    freestanding target REFUSED; that assertion was the bug and is gone),
    FreestandingWindowsIsStillRefused (new — pins that windows on
    freestanding is unaffected).
  • tests/unit/test_cenv_probe.cpp
    TheDUnixTokenCenvRealiseProducesForMacosAndFreestandingSatisfiesItsOwnExpectation:
    the exact -D__unix__ token + expectation pair cenv::realise now
    produces, handed to a real compiler, produces no mismatch — the half
    cenv::realise's own pure-function tests cannot check.
  • tests/e2e/742_gcc_accepted_when_the_realisation_is_empty.sh (new) — leg
    A reproduces the GCC/Linux regression against a real build with
    openkal-musl's own declaration (fails without this fix, confirmed
    locally before committing); leg B pins GCC (mingw) on Windows still
    refused with the existing diagnostic.

Version

2026.9.18.1 shipped these regressions; bumped to 2026.9.18.2 so
downstream has a release with the fix. check_version_pins.sh passes.

Verification

Full mcpp test: 123/123. Both e2e legs above pass. Doc lint
(check_docs_style.sh + check_docs_structure.sh) clean. docs/22 (+ zh
mirror) updated with the corrected mapping table and the reasoning for both
corrections. CHANGELOG carries a ## [2026.9.18.2] section (verified
against the extraction logic PR #670 hardens, so this release's notes will
not come out empty either way).

repositories hit the same shape within a day of 2026.9.18.1

Three regressions from 2026.9.18.1, all one shape: the engine treated a
target already satisfying a [c-abi] declaration and a target being unable
to realise it as the same case, so it either refused a compiler it never
needed to, or refused a target it could have realised.

1. GCC on Linux was refused for a package merely DECLARING [c-abi], before
   realisation ran at all. openkal-musl 0.15.0's own declaration on Linux
   (presents = "posix", data-model = "arch-default", wchar = 32) realises
   to nothing -- Linux's default triple already is that -- so nothing
   about it needed Clang. Every GCC user of openkal-musl on Linux lost the
   package for a substitution nothing asked GCC to perform. Fixed by
   reordering: cenv::realise (a pure function of the declaration and the
   target, not the compiler) runs first, and the Clang-only gate fires
   only when the result is non-empty. Windows is unchanged: the
   Cygwin-flavoured substitution there is non-empty, so a non-Clang
   compiler is still refused, naming what it cannot do.

2. macOS does not satisfy presents = "posix" by default -- caught by the
   verification probe on a real build (declared __unix__ defined, measured
   undefined), which is exactly the class of error that probe exists to
   catch. Apple's clang predefines __APPLE__/__MACH__ on its default
   triple, never __unix__; the original design text assumed macOS already
   presented it the way Linux does.

3. A freestanding target had no realisation for presents = "posix" at all,
   refused outright, which blocked openkal-llvm-runtime on riscv64-none-elf
   before it reached any other target.

2 and 3 dissolve into the same one-line rule, simpler than what it
replaces: realising presents = "posix" means the same observable fact
everywhere -- __unix__ defined, _WIN32 not -- and targets differ only in
what it costs. Linux: nothing. macOS and freestanding: one token,
-D__unix__ -- neither already defines it, for the identical reason.
Windows: the Cygwin-flavoured substitution. Known cost, left to the
mcpp-index 30-member measurement to weigh: #ifdef __unix__ ... #elif
defined(__APPLE__) now takes the Unix branch on macOS too.

Tests: test_cenv.cpp pins the GCC/Linux-accepted and GCC/Windows-still-
refused halves via cenv::realise directly (MacosPosixArchDefaultDefinesUnix,
FreestandingPosixDefinesUnix, FreestandingWindowsIsStillRefused);
test_cenv_probe.cpp adds the token cenv::realise now produces for macOS/
freestanding handed to a real compiler, proving the probe agrees with it;
e2e 742 reproduces the GCC/Linux regression against a real build (fails
without this fix) and pins GCC/Windows still refused.

Version bump: 2026.9.18.1 shipped these regressions; downstream needs a
release with the fix, so this is 2026.9.18.2.
@Sunrisepeak
Sunrisepeak merged commit 9cd8638 into main Sep 18, 2026
40 of 42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants