Skip to content

fix(ci): build both triples on amd64; cross-rs images are amd64-only - #16

Merged
ddreyer merged 2 commits into
st-masterfrom
fix/cross-images-are-amd64-only
Aug 18, 2026
Merged

fix(ci): build both triples on amd64; cross-rs images are amd64-only#16
ddreyer merged 2 commits into
st-masterfrom
fix/cross-images-are-amd64-only

Conversation

@ddreyer

@ddreyer ddreyer commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Failure

Run 32087564323, Build aarch64-unknown-linux-musl, step Build musl tarball, ~16s in:

#2 [internal] load metadata for ghcr.io/cross-rs/aarch64-unknown-linux-musl:0.2.5
#2 ERROR: no match for platform in manifest: not found
make[1]: *** [Makefile:264: cross-image-aarch64-unknown-linux-musl] Error 1

Cause

scripts/cross/aarch64-unknown-linux-musl.dockerfile builds FROM ghcr.io/cross-rs/aarch64-unknown-linux-musl:0.2.5. That image is published for linux/amd64 only:

$ docker manifest inspect ghcr.io/cross-rs/aarch64-unknown-linux-musl:0.2.5
  platforms: ['linux/amd64', 'unknown/unknown']
$ docker manifest inspect ghcr.io/cross-rs/x86_64-unknown-linux-musl:0.2.5
  platforms: ['linux/amd64', 'unknown/unknown']

That is by design. A cross-rs "aarch64" image is an amd64 container carrying a toolchain that targets aarch64 - it is not an arm64 image, and it cannot run on ubuntu-24.04-arm.

The comment in the matrix claiming cross uses a same-arch container was simply wrong, and the arm64 runner choice followed from it. Runner availability was never the problem; a probe workflow confirmed ubuntu-24.04-arm schedules fine.

Fix

Both legs now run on ubuntu-24.04, which is how upstream's publish.yml builds these same targets (make package-aarch64-unknown-linux-musl-all on their x86_64 release-builder-linux).

This remains real cross-compilation, not emulation. cross only needs QEMU to run target binaries - for tests - and cross build does not do that. So the runbook's "2-3x slower under QEMU" warning does not apply to this path.

The matrix simplifies to a plain triple list since runner is no longer per-entry.

Also: static-linking check switched from ldd to file

Two reasons:

  1. ldd cannot inspect a foreign-architecture binary, and the aarch64 artifact now is one, being cross-compiled on an amd64 host.

  2. The old condition was fragile independently of that:

    if ldd ... | grep -qv 'not a dynamic executable'; then fail

    grep -qv succeeds when any single line fails to match, so any incidental extra output would have failed the build.

The replacement matches statically linked in file -b output, which is architecture-independent and matches on exactly the property we care about.

🤖 Generated with Claude Code


Second commit: accept static-pie in the assertion

The x86_64 leg then failed too - but it built successfully (22m23s) and failed only on the assertion, against a binary that is genuinely static:

/tmp/verify/bin/vector: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, not stripped
##[error]binary is dynamically linked
	statically linked

Two separate false positives:

  1. The ldd form. On this runner ldd prints \tstatically linked for a static binary - not not a dynamic executable. So grep -qv matched and failed the build. The output string it tested for was simply wrong.

  2. The file replacement in the first commit matched only statically linked. Rust's musl targets emit a static-PIE, which file(1) reports as static-pie linked - so it would have failed in exactly the same way.

Now accepts both spellings, verified against real file(1) output:

Output Result
... x86-64, ..., static-pie linked, not stripped PASS
... ARM aarch64, ..., static-pie linked, not stripped PASS
... x86-64, ..., statically linked, not stripped PASS
... dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2 FAIL
... dynamically linked, interpreter /lib/ld-musl-aarch64.so.1 FAIL

Useful data point

The x86_64 build took 22m23s, well under the 60-90 min I had estimated for these runners, and comfortably inside timeout-minutes: 180.

ddreyer and others added 2 commits August 17, 2026 18:30
The aarch64 leg failed immediately:

  #2 [internal] load metadata for ghcr.io/cross-rs/aarch64-unknown-linux-musl:0.2.5
  #2 ERROR: no match for platform in manifest: not found

scripts/cross/aarch64-unknown-linux-musl.dockerfile builds FROM
ghcr.io/cross-rs/aarch64-unknown-linux-musl:0.2.5, which is published for
linux/amd64 only -- confirmed via `docker manifest inspect` on both cross-rs
images. That is by design: a cross-rs "aarch64" image is an amd64 container
carrying a toolchain that targets aarch64, not an arm64 image. It cannot run on
ubuntu-24.04-arm.

The earlier comment claiming cross uses a same-arch container was wrong. Both
legs now run on ubuntu-24.04, matching how upstream's publish.yml builds these
targets. This is still real cross-compilation rather than emulation: cross only
needs QEMU to *run* target binaries, which `cross build` does not do.

Also switches the static-linking assertion from `ldd` to `file`. ldd cannot
inspect a foreign-architecture binary, which the aarch64 artifact now is on an
amd64 host. The old `ldd ... | grep -qv 'not a dynamic executable'` was fragile
regardless -- grep -qv succeeds whenever any single line fails to match, so
incidental extra output would have tripped it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The x86_64 leg built fine and then failed the assertion on a binary that is
static:

  /tmp/verify/bin/vector: ELF 64-bit LSB pie executable, x86-64, version 1
  (SYSV), static-pie linked, not stripped
  ##[error]binary is dynamically linked

Two separate bugs, both false positives:

1. The `ldd` form. On this runner ldd prints "\tstatically linked" for a static
   binary, not "not a dynamic executable", so `grep -qv` matched and the check
   failed. The assumed output string was simply wrong.

2. The `file` replacement in the previous commit matched only "statically
   linked". Rust's musl targets emit a static-PIE, which file(1) reports as
   "static-pie linked" -- so it would have failed the same way.

Now accepts both spellings. Verified against real file(1) output for static-pie
(x86-64 and aarch64), plain static, and both dynamic forms.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ddreyer
ddreyer merged commit cfbf5f9 into st-master Aug 18, 2026
8 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