Skip to content

Measure on the runner which of 0113's triples it can compile C for - #302

Merged
iderex merged 1 commit into
mainfrom
the-c-cross-toolchains-the-runner-carries-291
Sep 5, 2026
Merged

iderex merged 1 commit into
mainfrom
the-c-cross-toolchains-the-runner-carries-291

Conversation

@iderex

@iderex iderex commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

The issue this belongs to

#291. It stays open, and the section at the end says on which of its conditions.

What changed

A new gate leg, cross-toolchain, measures on the runner which of 0113's seven
target triples that image can compile C for. It compiles one C translation unit
per triple, using the compiler invocations named in
.github/cross-toolchain/probes, and prints what each one answered.

The unit asks for the C library headers rather than only for the ones a
freestanding compiler supplies itself. That is the whole difference between this
and a survey worth nothing: a driver reaches an unknown platform's triple without
a sysroot for as long as nothing needs a header, so a probe that stopped at
resolving a name would report every Apple triple served on a Linux image carrying
no Apple SDK.

.github/targets/targets.sh gains a triples verb, and the survey consumes it.
The set of triples is 0113's, that script is the reader the targets leg already
proves with fixtures, and a second reader here would agree with it until the day
it did not.

CONTRIBUTING.md describes the leg where it describes every other one, and
corrects the sentence that counted two runs reporting without refusing. There are
three.

What failure it prevents

0243 decides a certificate is validated through rustls. Every crypto provider
rustls offers is C. The targets leg compiles the library for seven triples on
one Linux runner with no C cross-toolchain. 0291 weighed the three ways out of
that, took the wait, and wrote down in its own text that it had made the choice
without ever measuring which C cross-compilers the image carries:

git show origin/main:docs/decisions/0291-the-provider-the-socket-waits-on.md | sed -n '/^## What was not measured for this/,/^The choice does not rest on it/p' | head -8
## What was not measured for this

Which C cross-compilers the runner image carries. #291's body names that
measurement as its own first act and it is still unmade; every cross-compile
reading behind this question, in
[0243](0243-the-means-a-certificate-is-validated-with.md) and on #291, was taken
on a Windows machine outside this tree and is that machine's rather than the
runner's.

That record names the same reading as one of the four conditions that reverse it:
an image already carrying a working cross-toolchain for all seven makes the first
way out cost no runner bill and no maintained matrix, and the reason for waiting
is then gone. So the wait rests on a premise nobody had checked on the machine
that would have to hold it, and the check itself is one job.

The narrower failure is what the leg refuses rather than what it reports. A
survey that examined nothing exits zero and prints a page indistinguishable from
one that examined seven triples and found every one of them served, and a reading
of that page is what somebody would end a wait on.

Evidence

The commit this was run at:

git rev-parse HEAD
621627c595f1896649471b7a346d13a8fc2ddc36

Every fixture in the new script holds:

bash .github/cross-toolchain/cross-toolchain.sh selftest | grep -c '^ok  '
20

The set the survey walks comes out of the reader the targets leg uses, through
the verb this change adds to it:

bash .github/targets/targets.sh triples
aarch64-linux-android
armv7-linux-androideabi
aarch64-apple-ios
aarch64-apple-tvos
aarch64-apple-darwin
x86_64-pc-windows-msvc
x86_64-unknown-linux-gnu

and that script's own fixtures are unmoved by the verb:

bash .github/targets/targets.sh selftest > /dev/null 2>&1 ; echo "exit=$?"
exit=0

doc-paths and invariants pass on the tree this pushes:

bash .github/doc-paths/doc-paths.sh check | tail -2
Every path these documents name resolves against the tracked set.

bash .github/invariants/invariants.sh check | tail -1
Every rule above was applied to its subject and refused nothing.

THE READING THIS CHANGE EXISTS TO TAKE IS NOT IN THIS BODY, AND IT CANNOT BE.
The measurement is the runner's, and the only run that produces it is the job this
change adds. What follows is this machine's answer, which is Windows and not the
runner, and it is pasted to show the leg working end to end rather than as the
figure:

bash .github/cross-toolchain/cross-toolchain.sh check | grep -E '^This runner|^NOT SERVED'
This runner compiles C for 1 of the 7 triple(s) 0113's set names.
NOT SERVED: aarch64-linux-android armv7-linux-androideabi aarch64-apple-ios aarch64-apple-tvos aarch64-apple-darwin x86_64-unknown-linux-gnu.

The runner's own figure is the cross-toolchain check on this pull request, and
it is what belongs on #291.

The means

Bash and awk beside the workflow, which is what every other leg in this gate is
made of. It carries the three rules: each rule is refusable and refuses through
one path, each has a fixture proving it bites that runs before the check judges
anything, and every claim it makes is the output of a command it printed. It adds
no language, no runtime and no dependency this tree does not already have, and
the subject is a compiler on a machine rather than a value in the tree, which is
outside what the Rust suite can reach at all.

What a guard here refuses, and the proof it bites

Six refusals, each watched failing on a deliberate violation and each green again
once the violation is taken back out. The violation, then the run:

A block short of a field.

sed '/^reason: The host triple of the runner/d' probes.bak > .github/cross-toolchain/probes
bash .github/cross-toolchain/cross-toolchain.sh check | grep '^::error::' ; echo "exit=$?"
::error::.github/cross-toolchain/probes carries x86_64-unknown-linux-gnu without reason. A block short of a field is a probe that runs whatever it happens to name, against a triple nobody stated, for a reason nobody wrote.
exit=1

A field spelled wrong, which is the one-character mistake somebody actually
makes: the block then reads as complete-looking prose with a value missing.

sed 's/^reason: The host triple of the runner/reasons: The host triple of the runner/' probes.bak > .github/cross-toolchain/probes
::error::.github/cross-toolchain/probes carries a line this loader does not read as a field: reasons. A field spelled wrong leaves its block short of a value, and the block is then a probe nobody argued for.
exit=1

A triple in 0113's set that no block covers, which is what happens the day a
client platform is added to the target register and nobody opens this one.

awk '/^triple: aarch64-apple-tvos$/{skip=3} skip{skip--; next} {print}' probes.bak > .github/cross-toolchain/probes
::error::aarch64-apple-tvos is in 0113's set and .github/cross-toolchain/probes carries no probe for it. A triple added to that set and left unsurveyed is a platform this run says nothing about, on a page that reads as though it said something about all of them.
::error::the register and 0113's set disagree in 1 place(s). Nothing was compiled.
exit=1

A probe for a triple that set does not name, which is the same comparison in
the other direction.

{ cat probes.bak; printf '\ntriple: x86_64-unknown-freebsd\nprobe: cc\nreason: A platform nobody links.\n'; } > .github/cross-toolchain/probes
::error::.github/cross-toolchain/probes carries a probe for x86_64-unknown-freebsd and 0113's set does not name that triple. A probe for a platform nobody links is a compiler this run reports on for no reason, and it is how a register outlives the platform it was written for.
::error::the register and 0113's set disagree in 1 place(s). Nothing was compiled.
exit=1

A register that is all prose.

grep '^#' probes.bak > .github/cross-toolchain/probes
::error::.github/cross-toolchain/probes names no probe. An empty register invokes nothing, exits zero and prints a page indistinguishable from a run that surveyed every triple and found them served, so it is refused rather than read as a set with nothing to do.
exit=1

A loader that stopped matching, which is the one that cannot be reached by
editing the register. It was reached by breaking the reader on purpose: one
condition added to the awk in declared_probes so that it silently drops the
aarch64-apple-darwin block, leaving the register untouched and every block
complete.

::error::.github/cross-toolchain/probes offers 10 block(s) and this loader read 9 of them as complete with none reported short. A loader that stopped matching reports an empty set and reads exactly like a register with nothing to survey, so the disagreement is refused rather than passed.
exit=1

The register and the reader are back as this branch carries them, and the run is
green with nothing refused:

git status --short ; echo "exit=$?"
exit=0
bash .github/cross-toolchain/cross-toolchain.sh check > /dev/null 2>&1 ; echo "exit=$?"
exit=0

What this does not cover

#291 stays open, and this body is where it was closed by accident. The
sentence that stood here was written with the verb close in front of the
number and a negation in front of the verb. GitHub read the keyword and
discarded the negation, and the merge closed the issue. It is reopened, the
sentence is rewritten to the safe form - the number with no verb in front of it
at all - and the instance is written on the issue rather than only repaired
here. It is the third time this trap has been sprung on this board.

What that sentence was saying is unchanged. #291's second condition asks for a green target
leg on a tree carrying the dependency, and no tree carries it:

git show origin/main:Cargo.lock | grep -cE '^name = "(rustls|rustls-platform-verifier|rustls-rustcrypto|aws-lc-sys|ring)"'
0

It does not end 0291's wait and it cannot. That record waits on two things and
this is the second of them. The first is a version string, re-read at the moment
this was written rather than carried over:

cargo search rustls-rustcrypto --limit 1
rustls-rustcrypto = "0.0.2-alpha"    # Pure Rust cryptography provider for the Rustls TLS library...

unchanged from what 0291 quotes, so nothing here reverses anything.

It does not measure whether a provider builds. One translation unit that asks
for the C library headers is the first thing a provider's generated sources fail
on, and it is not a build of aws-lc or of anything else. A triple this leg
reports served can still fail deeper in a real build script.

It does not link. Every probe stops at -c, so a platform whose headers are
present and whose linker or libraries are not is reported served.

It does not find a compiler nobody named. The register holds what somebody
wrote down, so an image carrying a working cross-toolchain under a name that is
not in it is reported unserved. That is a block to add rather than a change to the
script, and the run prints the bound on itself.

It says nothing about any image but the one the job ran on, and nothing
carries the answer forward. An image that gains a toolchain next month changes the
verdict with nothing here noticing until the next run.

It refuses nothing about what it finds. A triple with no compiler on the image
is the state 0291 already decided to wait through. A red tick for it would redden
every pull request for a decision that is already taken and written down, and this
body is the disclosure of that rather than a claim that the leg is a gate.

Nothing here was run on a Linux machine before this pull request. The figures
above are this Windows machine's, the leg has never executed on ubuntu-latest
until this branch, and its first run there is the first run of the code as well as
the first taking of the measurement.

Who has read it

Nobody other than me. There was no second reader available for this change, and
the evidence above stands in place of one.

)

0243 validates a certificate through `rustls`, every crypto provider `rustls`
offers is C, and the targets leg compiles seven triples on one Linux runner.
0291 weighed the cross-toolchain, the dropped client platform and the wait, took
the wait, and recorded in its own text that it had never measured which C
cross-compilers that image carries: every reading behind the question was taken
on a Windows machine outside this tree. #291's body names that measurement as
the issue's own first act, and it was still unmade.

This is that measurement, taken where it has to be taken. A new leg compiles one
C translation unit for every triple in 0113's set, using the invocations named
in a register beside it, and reports which of them the image can compile C for.
The unit asks for the C library headers on purpose: a driver reaches an unknown
platform's triple without a sysroot for as long as nothing needs a header, so a
probe that stopped at resolving a name would report every Apple triple served on
a Linux image carrying no Apple SDK.

The failure it prevents is a survey that cannot be read. A block short of a
field, a field spelled wrong, a triple in 0113's set that no block covers, a
probe for a triple that set does not name, a loader that stopped matching, and a
register naming nothing all exit zero and print a page indistinguishable from a
run that examined seven triples and found every one of them served. Each is
refused, and each was watched refusing before it shipped.

It refuses nothing about what it finds. A triple with no compiler on the image is
the state 0291 already decided to wait through, and a red tick for it would
redden every pull request for a decision that is already taken and written down.

The set of triples is not read twice. `.github/targets/targets.sh` gains a
`triples` verb, so the survey consumes the reader the targets leg already proves
with its own fixtures instead of carrying a second copy that would agree with it
until the day it did not.

#291 stays open on its second condition, which asks for a green target leg on a
tree carrying the dependency, and no tree carries it.

Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
@iderex iderex added the ci label Sep 5, 2026
@iderex iderex self-assigned this Sep 5, 2026
@iderex
iderex merged commit 7587fa7 into main Sep 5, 2026
28 checks passed
@iderex
iderex deleted the the-c-cross-toolchains-the-runner-carries-291 branch September 5, 2026 03:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant