Skip to content

arm64-musl: add rust and cargo to the build dependencies#234

Open
awbx wants to merge 2 commits into
nodejs:mainfrom
awbx:add-rust-arm64-musl
Open

arm64-musl: add rust and cargo to the build dependencies#234
awbx wants to merge 2 commits into
nodejs:mainfrom
awbx:add-rust-arm64-musl

Conversation

@awbx

@awbx awbx commented May 25, 2026

Copy link
Copy Markdown

Summary

Node 26 enables the Temporal API by default, but its build silently skips Temporal when rustc/cargo are missing from PATH. The x64-musl recipe was already updated in #228; this PR is the corresponding fix for arm64-musl that @MikeMcC399 explicitly called out as still outstanding in #227 (comment)... :

PR #228 resolved this issue for amd64. It did not address: recipes/arm64-musl for arm64

So today the unofficial linux-arm64-musl tarball ships without Temporal, which means any downstream consumer of these tarballs (currently x64-alpine via docker-node; arm64-alpine pending nodejs/docker-node#2475) is missing the feature on arm64-musl.

Diff

 RUN apk add --no-cache \
         libstdc++ \
     && apk add --no-cache --virtual .build-deps \
         ...
         ccache \
         xz \
         patch \
+        # rustc/cargo are needed for the Temporal API support in Node 26+
+        # (build silently skips Temporal when they are not in PATH)
+        rust \
+        cargo \
         # extra packages required for creating the musl based cross-compiler
         rsync make gcc g++ bzip2 git

Same rust + cargo apk additions PR #228 made for recipes/musl/Dockerfile.

Verification

alpine:3.22 (the recipe's base) ships both packages:

$ docker run --rm alpine:3.22 sh -c 'apk add --no-cache rust cargo && rustc --version && cargo --version'
rustc 1.87.0 (17067e9ac 2025-05-09) (Alpine Linux 1.87.0-r1)
cargo 1.87.0 (99624be96 2025-05-06) (Alpine Linux 1.87.0-r1)

As with #233, I haven't been able to validate the full Node build locally (musl-cross-make toolchain build is ~30 min and Node from source is ~1–2 hr on my hardware); the change mirrors #228 exactly so the risk should be similar.

Refs: #227, #228

Node 26 enables the Temporal API by default, but its build silently
skips Temporal when rustc/cargo are missing from PATH. The x64-musl
recipe was already updated in nodejs#228; this is the corresponding fix for
arm64-musl that was called out in nodejs#227 as still outstanding.

Refs: nodejs#227
@nikeee

nikeee commented May 25, 2026

Copy link
Copy Markdown
Contributor

Is it confirmed that this works this easily? I tried it in 74ae38b but could not verify that the additional targets needed for arm actually work.

@MikeMcC399

Copy link
Copy Markdown
Contributor

So today the unofficial linux-arm64-musl tarball ships without Temporal, which means any downstream consumer of these tarballs (currently x64-alpine via docker-node; arm64-alpine pending nodejs/docker-node#2475) is missing the feature on arm64-musl.

docker-node does not currently consume linux-arm64-musl in the production branch. It uses only linux-amd64-musl.

Issue nodejs/docker-node#2486 was resolved in Node.js 26.1.0 for amd64 and in Node.js 26.2.0 for arm64.

If there are other consumers looking for this, then it would be helpful if they are in a position to test the outcome of this PR.

@sxa

sxa commented May 26, 2026

Copy link
Copy Markdown
Member

It's not as simple as dumping those two packages in because this is a cross-compiled target so the rust parts of the build need to be setup to cross-compile.
Ref: #228 (comment)

Following sxa's feedback that just adding `rust` and `cargo` apk
packages is insufficient for the cross-compiled arm64-musl recipe.
Alpine's `rust` package only ships the host (x86_64-musl) standard
library, so building `cargo --target=aarch64-unknown-linux-musl`
without a matching std artifact fails.

Pull the prebuilt `aarch64-unknown-linux-musl` std archive from the
upstream Rust dist server (version pinned to match the host toolchain,
SHA256 verified against the publisher's signed manifest) and drop it
into `/usr/lib/rustlib/`. Add a cargo config that points the
cross-compile linker at the musl-cross-make-built
`aarch64-linux-musl-gcc`.

Approach based on nikeee's exploratory commit at
nodejs@74ae38b

Refs: nodejs#227
Refs: nodejs/build#4316
@awbx

awbx commented May 31, 2026

Copy link
Copy Markdown
Author

Thanks for the corrections @sxa and @MikeMcC399.

@MikeMcC399 you're right that docker-node's arm64 image builds Node natively and isn't blocked on the unofficial tarball. I should not have framed that as the primary motivation. The real impact is on direct consumers of node-v*-linux-arm64-musl.tar.xz (the tj/n version manager, pnpm's musl arm64 path, etc.), which is a smaller audience but still real.

@sxa understood on the cross-compile point. Pushed an updated commit (e991c46) that takes @nikeee's approach from 74ae38b :

  1. Pin rust=1.87.0-r1 and cargo=1.87.0-r1 so the host toolchain version matches the std archive pulled below.
  2. Download the rust-std-1.87.0-aarch64-unknown-linux-musl archive from static.rust-lang.org, sha256 verified against the publisher's signed manifest (...-aarch64-unknown-linux-musl.tar.xz.sha256), and drop it into /usr/lib/rustlib/.
  3. Configure cargo via /usr/local/cargo/config.toml to use the musl-cross-make-built aarch64-linux-musl-gcc as the linker for the aarch64-unknown-linux-musl target.
  4. Set CARGO_HOME=/usr/local/cargo.

Full credit to @nikeee for working out the steps; I added the published-sha256 verification step in the commit so we have an explicit trust anchor.

I tried to validate the full Docker image build locally on my Mac but consistently hit a network timeout against dl-cdn.alpinelinux.org from my ISP (60s timeouts on both main and community mirrors). I can confirm the rust-std archive itself downloads and hashes correctly, but couldn't get a clean end-to-end docker build. It would help if your CI infra can take the actual Node build for a spin.

Happy to keep iterating or close in favor of @nikeee opening their own PR if they want to drive it.

@MikeMcC399

Copy link
Copy Markdown
Contributor

The real impact is on direct consumers of node-v*-linux-arm64-musl.tar.xz (the tj/n version manager, pnpm's musl arm64 path, etc.), which is a smaller audience but still real.

Full downstream adoption of Temporal is likely to take until at least EOL of Node.js 24 in April 2028, as it can't be backported to Node.js <=24, so n and pnpm will probably need to wait. There may however be other consumers that would like the support right now though.

@sxa

sxa commented Jun 8, 2026

Copy link
Copy Markdown
Member

@awbx @nikeee Have you verified that the build definitely requires the rust libstd for the target architecture? I ask because I don't believe it was required in the non-Alpine case and it isn't installed by default in the packages we install on Ubuntu for other unofficial-builds e.g. Linux/libc/riscv64.

@nikeee

nikeee commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@sxa I did not verify that it's needed. It seemed sensible to me but since I did not test it and arm-musl wasn't needed for the docker image, I excluded it from my original PR.

Edit: I now verified that this change does not work and bails out with a linker error.

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.

4 participants