Commit 09fc2ad
committed
feat(targets): the Android rows build, and the two halves of one goal stop disagreeing
`mcpp build --target aarch64-linux-android` produces a real Android artifact
with no project vocabulary beyond `--target`:
aarch64-linux-android -> ELF 64-bit LSB pie, ARM aarch64,
interpreter /system/bin/linker64
x86_64-linux-android -> ELF 64-bit LSB pie, x86-64, same interpreter
Both rows share ONE pin, `android-ndk@30.0.16248370`, and that is where every
defect below came from: the NDK names no architecture, `--target` does, so each
site that fails to say which target is exposed here and by nothing else. On
wasm none of them appear, because `em++` has exactly one target.
`preview`, not `verified`: both were BUILT and neither was EXECUTED, which is
the difference between the two tiers.
## Five engine gaps, each found by the previous one's failure
1. The std module's PRECOMPILE never received `--target`. `stdModuleTargetFlags`
reached only the codegen command, on the reading that step one needs headers
and step two needs the machine. Step one needs both: a `--precompile` that
does not say the target resolves the standard library's own
`#include <__config>` against the building machine. This file already
recorded the identical error text from a Windows host in 2026-08 -- same
cause, different route. The precompile now takes the machine from whichever
source carries it, preferring `stdModuleFlags` because it is a superset.
2. `-D__BIONIC_CTYPE_INLINE=`. bionic declares `isalnum` and its neighbours
`static inline`; libc++'s module surface exports them with `using
std::isalnum`, and a using-declaration cannot export internal linkage, so
the precompile fails on 14 names at once. Scoped to the std module: the rule
being satisfied is about exporting from a module, and a unit that includes
<ctype.h> directly is entitled to bionic's inline definitions.
3. "A toolchain that ships its own sysroot is told nothing" was one token too
strong, and this function already said so further down. The early return
stood in front of "THE TRIPLE, SAID OUT LOUD", which states the opposite
rule for the same reason. Both are right about their own object: the SYSTEM
is the payload's, WHICH TARGET is still mcpp's to say. Reported by the module
loader rather than by either compile, then eight cascading "use of
undeclared identifier 'std'" lines, which is what a reader sees first.
4. The LINK line had no target either. Both link branches are skipped for such
a target and that is correct for what they carry -- C library, C++ runtime,
crt objects and loader are all inside the SDK. What the driver cannot do is
guess which. Falling through empty linked the target's objects with the
host's startup files: six host objects on an aarch64 link. The new third
branch carries `crossTarget` and nothing else.
5. `discover_link_runtime_dirs`' gate was evaluated at the wrong time. The gate
is right; it runs during DETECTION, before the target is assigned, when
`targetTriple` is still the host's. The artifact is what showed it: `-L
<ndk>/.../prebuilt/linux-x86_64/lib/x86_64-unknown-linux-gnu`, whose last
component is this machine's triple, so the string names the question asked.
## Two artifact checks called a correct artifact a defect
Same shape both times: a rule true of a HOST-TARGETED artifact, applied to a
cross one.
- The hermetic link check counted `/system/bin/linker64` as outside the
sandbox. It is the one path this function inspects that is NOT resolved here:
it is recorded in the artifact and read by the DEVICE. Android's is fixed by
ABI and cannot be inside a payload. The message was accurate about what it
saw and wrong about what it meant, and it invited the reader to reinstall an
unrelated glibc payload.
- Runtime closure rule B compared `PT_INTERP` against the HOST's
`RuntimeBinding glibc@2.44` and reported a proven defect -- "one process
cannot mix runtime payloads" is a true sentence about a process that will
never exist. The linux/glibc guard above it does not cover this: an Android
triple's `os` IS `linux`, deliberately.
## host_can_serve stops compiling "Linux" into the engine
The predicate returned `mcpp::platform::is_linux` for own-sysroot rows, and its
own comment named the expiry: "when a darwin or windows NDK lands in the index
-- upstream publishes both -- this is the one line that changes." It landed.
Two halves of one goal then disagreed: the index published the payload on three
hosts while the engine deleted the row from `toolchain list` on two of them.
The symptom was not a wrong answer but an ABSENT one -- on macOS,
`mcpp build --target wasm32-emscripten` reported a target this table knows as
one it had never heard of, which is what the `planned` tier exists to avoid.
Neither half is where it was found. `scan (macos-arm64)` and
`scan (windows-x86_64)` failed on a CELL COUNT, 24 measured against 25
declared, and the one missing cell named the row. A per-host job comparing
against a checked-in table is the only thing here that can see a row disappear.
That predicate's unit test was ALSO true by arithmetic on one host:
`EXPECT_EQ(host_can_serve(*wasm), mcpp::platform::is_linux)` passes on Linux
because there `is_linux` IS `true`. A criterion whose expected value is the host
it runs on cannot report a change on the other two. Now stated unconditionally,
with the "this predicate can still say no" half restored.
## The capability-pin reason fell through a second time
Android became a capability row while the reason chain still had three arms, so
it was explained with the PE+musl sentence -- the same wrong answer recorded
for wasm, reached the same way: a fourth case falling into an `else` written as
the third's answer. So the last arm now names its own row and the fallthrough
is generic; a capability added later gets a sentence that is merely unspecific
instead of false.
Android's reason is not the other three's. They are refused because the
toolchain cannot emit the FORMAT; a stock clang emits aarch64 ELF perfectly
well. What it cannot supply is bionic, and no package adds that to another
compiler.
## The simulator is a row, not a runner
`env = "sim"` gives `aarch64-ios-sim` and `x86_64-ios-sim` -- Rust's pair modulo
the vendor segment this table already elides. Apple's own `-simulator` spelling
parses to the same row, because clang prints that form and a reader who pastes
it back must not be told mcpp has never heard of it. Both arches, because the
simulator runs the HOST's architecture. Both `planned`: the blocker is the same
licence question as the device row, not a payload.
## The API level's default comes from the payload
`min_platform_version` returned an empty string with the comment "the NDK's own
default, which clang supplies". Never verified, and false: bionic's
<sys/cdefs.h> refuses an unversioned triple outright. So the level is mandatory
and a project that never heard of API levels still needs one. It comes from the
NDK's own `meta/platforms.json` -- `{"min": 21, "max": 37}` for r30 -- so a
newer NDK changes the default by being installed rather than by being edited
into this file. 0 when unreadable, which the caller turns into a refusal naming
`min_api_level`; a guessed level would be worse, because it selects which
bionic symbols exist. The same false claim had a second copy in
`llvm_triple()`'s comment and is corrected there too.
## Two vocabulary consequences of the rows leaving `planned`
- A bare `aarch64-linux` must never complete to Android. The rows share the
`arch-os` prefix because the kernel IS Linux; that does not make bionic a
candidate C library for a request that named none. `aarch64-linux` had two
supported siblings and resolved as ambiguous, where it had completed to
`aarch64-linux-musl` before, and both outcomes of that ambiguity are wrong.
Excluded from `siblings` too, since that list is what the diagnostic prints.
- `aarch64-unknown-linux-android21` now parses. mcpp PRINTS that string one
line above the build it describes, and pasting it back answered `unknown
target`, because the env match read `k == "android"` while the API level rides
that segment. The msvc branch below carries the identical note for the
identical reason; Android was missed. One prefix covers all four spellings.
## Tests
- `tests/e2e/641` asserts the vocabulary half, which is what a runner without a
704 MB NDK can assert: both rows name the payload, neither is refused for its
tier, the simulator rows say `planned` rather than `unknown`, the effective
triple parses back, a bare `aarch64-linux` never mentions android, and
`min_api_level` has a floor refused by name.
- `tests/e2e/640` case 6 is EXHAUSTIVE, because adding an arm is what keeps
failing: it takes every pinned row from `toolchain list`, declares a
toolchain that is not its pin, and asserts the PE+musl sentence appears for
exactly one. Measured: 17 capability rows of 34 targets, PE+musl printed once.
The denominator comes from the engine, so a row added tomorrow is in it
without this file being edited -- and it agrees with the unit test's
independently written set of 17.
- `tests/matrix/expected.tsv`: the Android cells move to `capability-pin` and
the wasm cells on macOS/Windows move off `host-cannot-serve`, because the
refusal is now the row's rather than the host's. `android-ndk` deliberately
does NOT enter the declared-compiler column: the scan installs from that axis.
Verified locally, 54/54 payload and 28/28 graph cells for linux-x86_64.
- 109 unit test binaries pass. Three tests failed first and each was correct to:
one asserted the Android rows were planned, one asserted Android was not a
capability pin with the note "it moves when the row does", and one asserted a
bare `aarch64-linux` completion that two new supported siblings had made
ambiguous.1 parent c30dc74 commit 09fc2ad
19 files changed
Lines changed: 1252 additions & 108 deletions
File tree
- .agents/docs
- docs
- zh
- modules/toolchain-model/src
- src
- build
- toolchain
- tests
- e2e
- matrix
- unit
Lines changed: 29 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
984 | 984 | | |
985 | 985 | | |
986 | 986 | | |
987 | | - | |
988 | | - | |
989 | | - | |
990 | | - | |
991 | | - | |
992 | | - | |
993 | | - | |
994 | | - | |
995 | | - | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
996 | 1012 | | |
997 | 1013 | | |
998 | 1014 | | |
| |||
1005 | 1021 | | |
1006 | 1022 | | |
1007 | 1023 | | |
| 1024 | + | |
1008 | 1025 | | |
1009 | 1026 | | |
1010 | 1027 | | |
| |||
1017 | 1034 | | |
1018 | 1035 | | |
1019 | 1036 | | |
1020 | | - | |
1021 | | - | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
1022 | 1040 | | |
1023 | 1041 | | |
1024 | 1042 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
37 | 198 | | |
38 | 199 | | |
39 | 200 | | |
| |||
94 | 255 | | |
95 | 256 | | |
96 | 257 | | |
97 | | - | |
98 | | - | |
99 | | - | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
100 | 273 | | |
101 | 274 | | |
102 | 275 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
776 | 776 | | |
777 | 777 | | |
778 | 778 | | |
779 | | - | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
780 | 783 | | |
781 | 784 | | |
782 | 785 | | |
| |||
0 commit comments