Skip to content

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

Closed
rust-lang/rust
#69519

Description

@12101111

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)

Activity

  1. added a commit that references this issue on Nov 6, 2019
    e92f433
  2. ehuss commented on Nov 13, 2019

    @ehuss
    Contributor

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

  3. mati865 commented on Nov 13, 2019

    @mati865
    Member

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

  4. ehuss commented on Nov 13, 2019

    @ehuss
    Contributor

    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.

  5. reopened this on Nov 13, 2019
  6. mati865 commented on Nov 13, 2019

    @mati865
    Member

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

  7. ehuss commented on Nov 13, 2019

    @ehuss
    Contributor

    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?

  8. mati865 commented on Nov 13, 2019

    @mati865
    Member

    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.

  9. ehuss commented on Nov 14, 2019

    @ehuss
    Contributor

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

  10. t3hmrman commented on Feb 18, 2020

    @t3hmrman

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

  11. sfackler commented on Feb 18, 2020

    @sfackler
    Member

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

  12. paulwang001 commented on Feb 27, 2020

    @paulwang001

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

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

  13. t3hmrman commented on Feb 27, 2020

    @t3hmrman

    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.

  14. 12101111 commented on Feb 27, 2020

    @12101111
    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

  15. t3hmrman commented on Feb 27, 2020

    @t3hmrman

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

  16. added 2 commits that reference this issue on Mar 9, 2020
  17. added 3 commits that reference this issue on Mar 16, 2020
  18. joelparkerhenderson commented on May 30, 2020

    @joelparkerhenderson

    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
    
  19. sanmai-NL commented on Nov 17, 2023

    @sanmai-NL

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

  20. joelparkerhenderson commented on Nov 18, 2023

    @joelparkerhenderson

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: bugO-muslOS: musl targets

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions