cargo: cannot produce proc-macro when `--target` is set on musl host toolchain

Problem

On a musl based linux system , cross compilation will fail when using proc-macro

Steps

1.Cargo.toml:

[package]
name = "demo"
version = "0.1.0"
edition = "2018"

[dependencies]
serde= { version = "1.0", features = ["derive"] }

2.src/main.rs:

fn main(){}
$ RUSTFLAGS="-C target-feature=-crt-static" cargo build --target=wasm32-wasi
error: cannot produce proc-macro for `serde_derive v1.0.102` as the target `x86_64-unknown-linux-musl` does not support these crate types

Possible Solution(s)

Problem is : https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/build_context/target_info.rs#L406

proc-macro can’t build without RUSTFLAGS=-C target-feature=-crt-static

Notes

Output of cargo version: cargo 1.40.0-nightly (5da4b4d47 2019-10-28)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 16 (8 by maintainers)

Commits related to this issue

Most upvoted comments

Compiling binary dynamically linked to musl on musl host (need RUSTFLAGS set) or binary statically linked to musl on glibc host will works. This issue is about the fact that, when a crate use proc-macro, on a musl host (1) we can’t cross compile it for other targets (2) we can’t compile it statically linked to musl. We can’t do (1) because cargo set RUSTFLAGS to empty when compile proc-macro. we can’t do (2) because it will let proc-macro compile statically, which is wrong. The problem is cargo don’t have a concept about HOSTRUSTFLAGS that only apply to build script and proc-macro, but the behavior of crt-static is control by RUSTFLAGS. However, RUSTFLAGS isn’t a out of box solution. On every platform that have rustc built and runs, proc-macro is compiled dynamically, so the better solution is rustc don’t check whether a target can compile proc-macro (as it always can), and compile it dynamically directly

Musl target does support proc-macros.

The issue here is proc-macros are dylibs and Rust doesn’t support linking dylibs to static CRT on targets other than Windows. Historically musl target links static CRT by default so one has to disable it with target-feature=-crt-static to get proc-macro. Binary will be build dynamically linked so it requires musl to be installed on the target to run (it loses portability).

Maybe a bit overkill but installing g++ or build-base should give you everything you need.

On a fresh install of Alpine Linux

Using container in Docker/Podman is enough to try it BTW.

I hit the same error message, and here’s what worked for me to build a Rust Rocket app in a Dockerfile using Alpine and Rust nightly. I welcome feedback – this is my first time trying Docker + Rust nightly + Alpine musl.

FROM alpine:latest as builder-system
RUN apk update
RUN apk add binutils build-base ca-certificates curl file g++ gcc libressl-dev make patch rust
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
RUN . ~/.cargo/env && rustup toolchain install nightly && rustup default nightly
RUN . ~/.cargo/env && rustup target add x86_64-unknown-linux-musl

WORKDIR /usr/src/demo_rust_rocket
COPY Cargo.toml Cargo.toml
RUN mkdir src/
RUN echo "fn main() {println!(\"if you see this, the build broke\")}" > src/main.rs
RUN . ~/.cargo/env && RUSTFLAGS="-C linker=musl-gcc -C target-feature=-crt-static" cargo build --release --target=x86_64-unknown-linux-musl