Make non-glibc Linux cross-compilation work#55
Conversation
Three small changes that let mujina-miner cross-compile for
aarch64-unknown-linux-musl (and other non-glibc Linux targets) so it
can be deployed to mining hardware that ships with musl userspace --
e.g. the Amlogic A113D control board on Antminer S19 series.
- Switch reqwest to rustls-tls. Default features pull in native-tls,
which transitively requires openssl-sys; cross-building openssl-sys
to musl is painful and unnecessary when reqwest can use rustls.
- Gate udev and tracing-journald to target_env = "gnu". Both link
against glibc-only system libraries (libudev, libsystemd) that have
no good musl story. The existing fallback module in
src/transport/usb.rs already covers the no-udev case as a stub, so
musl Linux falls into the same "USB hashboard discovery
unsupported" path as Windows etc. -- fine for the CPU backend and
any non-USB board.
- Same gate change in src/tracing.rs: the journald init path requires
tracing-journald, so it has to follow the same cfg.
Tested by cross-compiling mujina-minerd from macOS to
aarch64-unknown-linux-musl and running on an Antminer S19j Pro
control board (kernel aarch64, userspace armhf, musl static binary
runs fine via the 64-bit kernel) with MUJINA_USB_DISABLE=1 and the
CPU backend.
Build prereqs on macOS:
rustup target add aarch64-unknown-linux-musl
brew install messense/macos-cross-toolchains/aarch64-unknown-linux-musl
Then:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-unknown-linux-musl-gcc \
CC_aarch64_unknown_linux_musl=aarch64-unknown-linux-musl-gcc \
cargo build --release --target aarch64-unknown-linux-musl --bin mujina-minerd
There was a problem hiding this comment.
Pull request overview
This PR adjusts mujina-miner to successfully cross-compile for non-glibc Linux targets (notably aarch64-unknown-linux-musl) by avoiding glibc-only system integrations and removing OpenSSL/native-tls requirements from the HTTP client dependency chain.
Changes:
- Switch workspace
reqwestconfiguration todefault-features = falseand enablerustls-tls(avoidsopenssl-sys). - Gate Linux-only dependencies (
udev,tracing-journald) tocfg(all(target_os = "linux", target_env = "gnu")). - Gate Linux journald initialization and Linux USB serial-port discovery code to the same glibc-only cfg, falling back to stub behavior on musl.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
Cargo.toml |
Reconfigures reqwest to use rustls and avoid native-tls/OpenSSL. |
mujina-miner/Cargo.toml |
Limits udev and tracing-journald dependencies to glibc Linux targets. |
mujina-miner/src/transport/usb.rs |
Limits Linux USB serial-port discovery module to glibc Linux; uses stub elsewhere (incl. musl). |
mujina-miner/src/tracing.rs |
Limits journald init module to glibc Linux; uses stub elsewhere. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| [target.'cfg(all(target_os = "linux", target_env = "gnu"))'.dependencies] | ||
| tracing-journald = { workspace = true } | ||
| udev = { workspace = true } | ||
|
|
| #[cfg(all(target_os = "linux", target_env = "gnu"))] | ||
| mod linux; | ||
| #[cfg(target_os = "linux")] | ||
| #[cfg(all(target_os = "linux", target_env = "gnu"))] | ||
| use linux as platform; | ||
|
|
| #[cfg(all(target_os = "linux", target_env = "gnu"))] | ||
| mod journald { | ||
| use std::env; | ||
| use std::io; |
|
My reading of this PR is that it brings up several good issues, but doesn't completely solve any of them. What the diff actually accomplishes is making Mujina compile as a static binary. That's useful on its own, but each change raises a bigger question about Mujina's portability, and we should answer those questions deliberately. Here's my attempt at listing them:
Concretely, I think the implementation that falls out is: udev, journald, and rustls become cargo features, with the first two default-on and rustls opt-in alongside a native-tls default. Defining each feature includes deciding what the build does with the feature off. No udev probably means boards come from static configuration instead of discovery; no journald already falls back to console logging. The cfg gates express only platform impossibility, like udev on macOS. The emberone00 integration tests, which find their board through udev, would compile only when the udev feature is on, so the tests follow the same switch as the code they exercise. CI builds and tests both with the default features and with them off. That keeps today's builds unchanged while making the static build a supported configuration instead of a byproduct of the libc. Rather than grow this PR into all of that, I may close it and open one or more issues from the list above so the questions can be worked separately. The PR did its job by raising them. |
Summary
Three small changes that let
mujina-minercross-compile foraarch64-unknown-linux-musl(and other non-glibc Linux targets), so it can be deployed onto mining hardware that ships with musl userspace — concretely, the Amlogic A113D control board found on Antminer S19 series miners.reqwesttorustls-tls. The default features pull innative-tls, which transitively requiresopenssl-sys. Cross-buildingopenssl-systo musl is painful (sysroot, pkg-config wrapper, vendored OpenSSL or a sysroot install) and unnecessary when reqwest can use rustls directly.udevandtracing-journaldtotarget_env = "gnu". Both link against glibc-only system libraries (libudev,libsystemd) that have no good musl story. The existing fallbackmod platforminsrc/transport/usb.rsalready covers the no-udev case as a stub for unsupported platforms (Windows, etc.), so musl Linux now falls into that same path — fine for the CPU backend and any non-USB hashboard.cfgchange insrc/tracing.rsso the journald init mod follows the same gate as its dependency.Net diff: 4 files, +7 / -7 lines.
Test plan
cargo build --releaseon macOS (aarch64-apple-darwin) — unchanged, still builds.cargo build --release --target aarch64-unknown-linux-musl --bin mujina-minerdfrom macOS — now succeeds (previously failed atopenssl-sysandudev).MUJINA_CPUMINER_THREADS=1 MUJINA_CPUMINER_DUTY=50 MUJINA_USB_DISABLE=1 MUJINA_API_LISTEN=0.0.0.0:7785 ./mujina-minerd— comes up cleanly, CPU board attached, dummy job source, REST API responds at/swagger-ui, mining-status log line ticks at 30s.Build steps on macOS
Notes / open questions
reqwestrustls swap is mildly opinionated. If you'd prefer to keepnative-tlsas the default and offer rustls behind a feature flag instead, happy to refactor — but it'd add complexity for the cross-build path with no obvious upstream benefit.