Give the Intel Mac host back the recipe that cross-builds it - #171
Merged
Conversation
hosts.json says x86_64-apple-darwin is stage 3, cross-built on the arm64 runner; build-host.sh has called it native since #161, which made it so in both places at once. db4d1a5 turned the lock back into a cross and left the recipe alone, so stage 3 configured with the machine's own compiler: "-- Host: arm64-apple-darwin", every component at --host=aarch64-apple- darwin, and an arm64 SDK published under the Intel name. It stayed green through the SDK, the static validation and the toolchain contract -- the contract runs run.sh under arch -x86_64, and a Rosetta process execs an arm64 binary natively, so it never demanded the slice. What demanded it was the bootstrap smoke test, 18 minutes in: arch -x86_64 bootstrap-installed/bin/arm-vita-eabi-gcc, Bad CPU type in executable. The recipe restored here is the one #161 deleted, unchanged: the wrappers from setup-macos-cross.sh in PATH and the toolchain file that pins the triplet. The test is what was missing. The lock and the case block are two halves of one decision and nothing tied them together, so it runs the real case block for every host in hosts.json and fails when one that names a build_host gets no toolchain file, or one that names none gets a toolchain file.
VITASDK_HOST_NAME is what the artifacts are called; the toolchain triplet is what they are. Nothing compared the two, so the build whose toolchain file had gone missing named one host and produced another, and everything downstream agreed with the name: the tarball, the package architecture, the bootstrap, the provenance. The check runs as soon as both are known, which costs seconds instead of the 18 minutes the bootstrap smoke test needed to reach the same conclusion by running a binary. arm64 and aarch64 are one machine here: Apple writes the first, config.sub the second, and both reach this line depending on who was asked. The name derivation moves to cmake/PublishedHostName.cmake so its test can call it instead of keeping a second copy of the FreeBSD rule.
The format guard exists because a staged build assembles one SDK out of two machines, and a file belonging to the producer can reach the consumer's tree without anything else noticing. On Apple it could not see that: both machines emit Mach-O, so arm64 and x86_64 were the same answer -- and the one host pair staged across two architectures, x86_64-apple-darwin cross-built on the arm64 runner, was exactly the blind spot. The cputype sits four bytes behind the magic, in the byte order the magic announces. A universal binary carries one per slice and none of its own, so it stays unclassified rather than guessed at. The test drives the check with the real cmake binary against the triplet of the machine it is not, which exercises the Mach-O path on macOS and the ELF one on Linux, and the helper it calls now takes the host to check against instead of hardcoding Windows.
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.
stage3 (x86_64-apple-darwin)is the one red host of nine invitasdk/autobuilds#36, and it dies at the only line of the job that demands an x86_64 slice:That job never cross-compiled anything. Line 532 of its own log, 18 minutes earlier:
and every component under it at
checking host system type... aarch64-apple-darwin. It built a native arm64 SDK and published it under the Intel name.cmake/hosts.jsonsays this host is stage 3, cross-built on the arm64 runner.scripts/ci/build-host.shhas called it native since #161, which made it so in both places at once.db4d1a593turned the lock back into a cross and left the recipe alone:The first commit puts that back, unchanged.
Why everything green stayed green
Three checks ran over that tree and none of them could see it.
The toolchain contract, because
run.shunderarch -x86_64is a Rosetta process, and a Rosetta processexecs an arm64 binary natively. It exercised an arm64 gcc and said OK. Onlyarch -x86_64 <binary>directly demands the slice, which is what the smoke test does and why it is the line that failed.ValidateSdk, because it compares the tree againsthost_native— which wasarm64-apple-darwin. Consistent tree, consistent answer. The published name it disagreed with was never part of the comparison.The host binary format guard, because on Apple it only asked "is this Mach-O?". Both machines answer yes. It is the guard written for exactly this — a file from the producer riding into the consumer's tree in a staged build — and
x86_64-apple-darwin, cross-built on the arm64 runner, is the one host pair where it was blind.The bootstrap that came out was mixed, and the log shows it:
pacman --versionandvdpm --helpran fine underarch -x86_64two lines before the failure, because the vdpm bundle is downloaded per published host name and really was x86_64. The client was Intel and the toolchain was not.The three commits
The recipe, plus
tests/ci/test-cross-host-recipe.sh. The lock and the case block are two halves of one decision and nothing tied them together. The test runs the real case block for every host inhosts.jsonand fails when one that names abuild_hostgets no toolchain file, or one that names none gets one. With the bug reintroduced it says so by name:The name gate.
VITASDK_HOST_NAMEis what the artifacts are called; the toolchain triplet is what they are, and nothing compared them. Now the build stops as soon as both are known:That is 1.5 seconds instead of the 18 minutes the smoke test needed to reach the same conclusion by running a binary.
arm64andaarch64are accepted as one machine: Apple writes the first,config.subthe second. The FreeBSD publish rule moves intocmake/PublishedHostName.cmakeso its test calls it instead of keeping a second copy.The Mach-O cputype, four bytes behind the magic, in the byte order the magic announces. A universal binary carries one per slice and none of its own, so it stays unclassified. This is what makes
ValidateSdkable to see an arm64 binary in an Intel tree at all. Its test drives the check with the realcmakebinary against the triplet of the machine it is not, which exercises the Mach-O path on macOS and the ELF one on Linux.Verified
A reduced probe in the probe repository drives this script's own case block, configures, and builds one host dependency —
deps_hostexists only on the cross path, so the configure output already tells the two builds apart:master-- Host: arm64-apple-darwin, no toolchain file, nozlib_host-- Host: x86_64-apple-darwin,deps_host/lib/libz.a: x86_64On a clean
macos-14runner againstmasterthat reproduces in a 33-second job. Every suite in thechecksjob passes locally: 7 cmake scripts, 8 CI tests.AI tools were used in preparing this PR (Claude Opus 5, Anthropic).