Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot produce proc-macro when --target is set on musl host toolchain #7563

Closed
12101111 opened this issue Nov 6, 2019 · 16 comments · Fixed by rust-lang/rust#69519
Closed
Labels
C-bug Category: bug O-musl OS: musl targets

Comments

@12101111
Copy link

12101111 commented Nov 6, 2019

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)

@12101111 12101111 added the C-bug Category: bug label Nov 6, 2019
12101111 added a commit to 12101111/cargo that referenced this issue Nov 6, 2019
Fix building proc-macro crates on musl host when --target is specified.
@ehuss
Copy link
Contributor

ehuss commented Nov 13, 2019

AFAIK, rustc musl host fundamentally does not support proc-macros. Some more information may be found at rust-lang/rust#40174.

@ehuss ehuss closed this as completed Nov 13, 2019
@mati865
Copy link
Contributor

mati865 commented Nov 13, 2019

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).

@ehuss
Copy link
Contributor

ehuss commented Nov 13, 2019

Oh, I think I see. I've never been able to get rustc musl to work on any system. Do you know, is there any information on how to get it to work? Whatever I've tried, I get all sorts of errors (symbol not found, libgcc_s.so.1 not found, etc) just running rustc -V.

@ehuss ehuss reopened this Nov 13, 2019
@mati865
Copy link
Contributor

mati865 commented Nov 13, 2019

@ehuss you need musl compiler (musl-gcc) in the path to build for musl.

Whatever I've tried, I get all sorts of errors (symbol not found, libgcc_s.so.1 not found, etc) just running rustc -V.

You have probably installed musl host toolchain on glibc based linux, it's possible to run it there but sketchy. You'd have more luck running it on Alpine Linux or musl variant Void Linux.

Slightly offtopic but I want you to understand what is going on:
You can cross compile code from OP on linux-gnu to linux-musl or wasi just fine because proc macro runs on linux-gnu and get static binary.
Compiling it on linux-musl for any target won't work out of the box because user have to disable crt-static. I think it won't hurt for wasi but this prevents user from creating static binary on musl whenever proc-macros are involved.

I don't know how to fix it, generally proc-macros always have to be compiled dynamically for host assuming it supports dylibs. Probably this has to be fixed in rustc itself but I don't remember that code well enough to tell for sure.

@ehuss
Copy link
Contributor

ehuss commented Nov 13, 2019

You have probably installed musl host toolchain on glibc based linux, it's possible to run it there but sketchy. You'd have more luck running it on Alpine Linux or musl variant Void Linux.

On a fresh install of Alpine Linux, I get the exact same errors as other distros trying to run rustc for stable-x86_64-unknown-linux-musl: https://gist.github.com/ehuss/57a81703bdfb4abcd64ddfbdc4d371c0

I just tried with the latest nightly, with the same result. Any ideas what I'm missing? This is using rustup to install. Do I need to install a special package? Are there dependencies I need to install?

@mati865
Copy link
Contributor

mati865 commented Nov 13, 2019

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.

@ehuss
Copy link
Contributor

ehuss commented Nov 14, 2019

Ah, adding g++ did the trick, thanks!

@t3hmrman
Copy link

Just ran into this and want to make sure I'm understanding this correctly -- it sure seems like it's impossible to build a static binary (or at least the closest we can get to it on linux w/ musl) if you have any dependency that uses macros?

It seems like the only workaround is to dynamically link libgcc...

@sfackler
Copy link
Member

You don't need to use a MUSL host toolchain to target MUSL.

@paulwang001
Copy link

~/.cargo/config
[build]
rustflags = "-C target-feature=-crt-static"

OR
$>RUSTFLAGS="-C target-feature=-crt-static" cargo build

@t3hmrman
Copy link

t3hmrman commented Feb 27, 2020

Thanks @paul-sedun/@sfackler

Maybe I wasn't clear about my misunderstanding -- it wasn't whether you needed musl installed or how to specifically to do it, but more about the fact if you choose to do use crt-static you must then the generated binary must at runtime be dynamically linked.

I'm going directly off what @mati865 said (reproduced below):

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).

If I'm reading this correctly, then it means that at the moment Rust cannot generate the closest thing we have to a static binary on linux if the project being built uses macros.

[EDIT] - Just trying to make sure this is clear but I'm not trying to slight rust here, just want to make sure that I arrived at the right conclusion.

@12101111
Copy link
Author

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

@t3hmrman
Copy link

Thank you for the explanation, I think I understand now!

Centril added a commit to Centril/rust that referenced this issue Mar 9, 2020
…=nagisa,smaeul

 Don't use static crt by default when build proc-macro

Don't check value of `crt-static` when build proc-macro crates, since they are always built dynamically.
For more information, see rust-lang/cargo#7563 (comment)
I hope this will fix issues about compiling `proc_macro` crates on musl host without bring more issues.
Note: I can't test this on my musl host locally, because I encounter this issue when bootstraping from a beta snapshot.
Fix rust-lang/cargo#7563
Centril added a commit to Centril/rust that referenced this issue Mar 9, 2020
…=nagisa,smaeul

 Don't use static crt by default when build proc-macro

Don't check value of `crt-static` when build proc-macro crates, since they are always built dynamically.
For more information, see rust-lang/cargo#7563 (comment)
I hope this will fix issues about compiling `proc_macro` crates on musl host without bring more issues.
Note: I can't test this on my musl host locally, because I encounter this issue when bootstraping from a beta snapshot.
Fix rust-lang/cargo#7563
bors added a commit to rust-lang/rust that referenced this issue Mar 16, 2020
 Don't use static crt by default when build proc-macro

Don't check value of `crt-static` when build proc-macro crates, since they are always built dynamically.
For more information, see rust-lang/cargo#7563 (comment)
I hope this will fix issues about compiling `proc_macro` crates on musl host without bring more issues.
Note: I can't test this on my musl host locally, because I encounter this issue when bootstraping from a beta snapshot.
Fix rust-lang/cargo#7563
@joelparkerhenderson
Copy link

joelparkerhenderson commented May 30, 2020

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

@sanmai-NL
Copy link

@joelparkerhenderson Any particular reason you set linker=musl-gcc?

@joelparkerhenderson
Copy link

IIRC, I was attempting to stop dynamic linking related to release builds. IIRC, I was following rust-lang/rust#54243 and https://stackoverflow.com/questions/64737810/rust-building-a-statically-linked-binary-including-external-c-libraries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug O-musl OS: musl targets
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants