Skip to content

ci: Android shares this implementation, and CI says so - #26

Merged
Sunrisepeak merged 2 commits into
mainfrom
ci/android-shares-this-implementation
Sep 11, 2026
Merged

ci: Android shares this implementation, and CI says so#26
Sunrisepeak merged 2 commits into
mainfrom
ci/android-shares-this-implementation

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

mcpp 2026.9.11.3 makes aarch64-linux-android and x86_64-linux-android real
target rows. The question that raises for this package has a short answer:
nothing here changes.

This file is written on the Linux kernel's own system-call interface and
borrows nothing from any C library -- that is what lets it be placed beneath
one. Android's kernel is Linux, the per-architecture system-call ABI is the
same, and src/sys.h branches on __x86_64__ / __aarch64__: the
architecture, not the operating system. A consumer needs no new line either,
because cfg(os = "linux") is true for an Android triple.

A claim about what does not change is exactly the kind that rots unmeasured, so
one step asserts it.

What the step checks

both ABIs build mcpp build --target <t> --features standalone
the objects are the guest's file names ARM aarch64 / x86-64 -- asserted rather than assumed from --target, because one of the two is not the runner's
no C library symbol the same permitted set the native step applies, against a different libc

The last one is the interesting half. Compiling is the weaker statement; the
property this package exists for is the symbol closure, and on Android the C
library is bionic. A reference that resolved to glibc by habit would show up
here as a bionic name.

Two names the native set does not have

Measurement decides them rather than judgement:

__emutls_get_address   defined in libclang_rt.builtins-{aarch64,x86_64}-android.a
__aarch64_swp4_acq     defined in libclang_rt.builtins-aarch64-android.a

and in neither bionic libc.so. So they belong to the category the set
already admits for memcpy and its three neighbours: compiler-emitted,
computing rather than calling, and incapable of re-entering this
implementation.

The emulated-TLS one is not mcpp's choice: build.ninja for this target
carries no -femulated-tls, and the NDK's clang emits the reference by itself
from a bare thread_local int x; at API 21 -- its documented default below the
level where bionic gained ELF TLS.

They are permitted in this step only. Widening the native step's set for a
target it was not measured on is how a check stops being one.

What it does not check

Execution. Running an Android artifact needs a device or an emulator.
Measured by hand on an API 24 x86_64 image: a program written against openkal
alone -- no C library, no import std -- printed openkal: 1-2-3 with exit 0.
The device ABI has no execution path from an x86_64 runner at all, because
Google's emulator refuses a foreign guest (QEMU2 emulator does not support arm64 CPU architecture).

One matrix leg, because the axis does not reach this target: the Android rows
carry a capability pin, so mcpp refuses any other toolchain for them and
matrix.toolchain selects nothing here.

Verification

Both directions, by extracting the step and running it locally:

  • passes on both ABIs (17 objects each, correct architecture)
  • with puts added to a source, reports
    references a symbol it must not: puts for each ABI and exits 1

Depends on

mcpp 2026.9.11.3 (mcpp-community/mcpp#610). Until that is released this job
needs MCPP_SOURCE_REF, which the workflow already supports -- on the released
2026.9.11.2 the Android rows are still planned and the build is refused by
the tier gate.

mcpp 2026.9.11.3 makes `aarch64-linux-android` and `x86_64-linux-android` real
target rows, and the question that raises for this package has a short answer:
nothing here changes. This file is written on the Linux kernel's own
system-call interface and borrows nothing from any C library. Android's kernel
IS Linux, the per-architecture system-call ABI is the same, and `src/sys.h`
branches on `__x86_64__` / `__aarch64__` -- the architecture, not the operating
system.

A claim about what does not change is exactly the kind that rots unmeasured, so
one step now asserts it.

THE SECOND HALF IS THE INTERESTING ONE. Compiling is the weaker statement; the
property this package exists for is that its objects name no C library symbol,
and on Android the C library is a DIFFERENT one. A reference that resolved to
glibc by habit would appear here as a bionic name, so the same permitted set is
applied to the same kind of output for another libc. The architecture of the
objects is asserted too rather than assumed from `--target`, because one of the
two is not the runner's.

TWO NAMES THE NATIVE SET DOES NOT HAVE, and measurement decides them:
`__emutls_get_address` and `__aarch64_swp4_acq` are both defined in the NDK's
`libclang_rt.builtins-<arch>-android.a` and in NEITHER bionic `libc.so`. They
belong to the category the set already admits for memcpy and its three
neighbours -- compiler-emitted, computing rather than calling, and incapable of
re-entering this implementation. The emulated-TLS one is not mcpp's choice:
`build.ninja` for this target carries no `-femulated-tls`, and the NDK's clang
emits the reference by itself from a bare `thread_local int x;` at API 21.
They are permitted in this step only; widening the native step's set for a
target it was not measured on is how a check stops being one.

One matrix leg, because the axis does not reach this target: the Android rows
carry a capability pin, so mcpp refuses any other toolchain for them and
`matrix.toolchain` selects nothing here.

NOT EXECUTION, and the step says so. Running an Android artifact needs a device
or an emulator. Measured by hand on an API 24 x86_64 image: a program written
against openkal alone -- no C library, no `import std` -- printed
`openkal: 1-2-3` with exit 0. The device ABI has no execution path from an
x86_64 runner at all, since Google's emulator refuses a foreign guest.

Verified in both directions by extracting the step and running it locally: it
passes on both ABIs, and with a `puts` call added it reports
"references a symbol it must not: puts" for each and exits 1.
The Android step ran against mcpp 2026.8.27.1 -- this repository's pinned
`MCPP_VERSION` -- where `aarch64-linux-android` and `x86_64-linux-android` do
not exist as target rows at all, so it failed with exit 2. The rows become
real in 2026.9.11.3, which is now tagged.

This is the CI pin, which is what this repository is TESTED against, and not a
floor: nothing here records a minimum engine for consumers, and moving a floor
would make a client stopped at the old one unable to use this package at all.

The job stays red until the index carries 2026.9.11.3 -- `xlings install
mcpp@$MCPP_VERSION` can only resolve what the published index has, and the
release's own ecosystem job is what puts it there. That ordering is the
dependency this PR already records, now expressed in the file rather than only
in prose.
@Sunrisepeak
Sunrisepeak merged commit 8672403 into main Sep 11, 2026
2 of 4 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.

1 participant