Target x86_64-unknown-linux-musl fails to link

I am trying to compile targeting x86_64-unknown-linux-musl (cargo build --release --target x86_64-unknown-linux-musl) and and no matter what I do I keep getting different linking errors.

(1) If I don't define anything related to the linked in .cargo/config.toml I get this error (simplified as the rest shown):

/usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

(2) If instead I define (trying to guide myself from this post Enable rust-lld on x86_64-unknown-linux-musl):

[target.x86_64-unknown-linux-musl]
linker = "rust-lld"
rustflags = ["-C", "target-feature=-crt-static"]

I get:

error: linking with `rust-lld` failed: exit code: 1
  = note: rust-lld: error: unable to find library -lgcc_s

(3) And if I define:

[target.x86_64-unknown-linux-musl]
linker = "rust-lld"

I get:

  = note: rust-lld: error: undefined symbol: __strncpy_chk
          >>> referenced by harfbuzz.cc
          >>>               harfbuzz.o:(bool _parse_number<double, hb_parse_double(char const**, char const*, double*, bool)::'lambda'(char const*, char**)>(char const**, char const*, double*, bool, hb_parse_double(char const**, char const*, double*, bool)::'lambda'(char const*, char**)) (.constprop.0)) in archive /tmp/rustcAie9yo/libharfbuzz_sys-104a993656c30b7b.rlib

          rust-lld: error: undefined symbol: __memmove_chk
          >>> referenced by harfbuzz.cc
          >>>               harfbuzz.o:(reorder_marks_arabic(hb_ot_shape_plan_t const*, hb_buffer_t*, unsigned int, unsigned int)) in archive /tmp/rustcAie9yo/libharfbuzz_sys-104a993656c30b7b.rlib

          rust-lld: error: undefined symbol: __vsnprintf_chk
          >>> referenced by harfbuzz.cc
          >>>               harfbuzz.o:(hb_buffer_t::message_impl(hb_font_t*, char const*, __va_list_tag*)) in archive /tmp/rustcAie9yo/libharfbuzz_sys-104a993656c30b7b.rlib

          rust-lld: error: undefined symbol: __memcpy_chk
          >>> referenced by harfbuzz.cc
          >>>               harfbuzz.o:(hb_language_from_string) in archive /tmp/rustcAie9yo/libharfbuzz_sys-104a993656c30b7b.rlib
          >>> referenced by harfbuzz.cc
          >>>               harfbuzz.o:(void AAT::StateTableDriver<AAT::ObsoleteTypes, void>::drive<AAT::RearrangementSubtable<AAT::ObsoleteTypes>::driver_context_t>(AAT::RearrangementSubtable<AAT::ObsoleteTypes>::driver_context_t*)) in archive /tmp/rustcAie9yo/libharfbuzz_sys-104a993656c30b7b.rlib
          >>> referenced by harfbuzz.cc
          >>>               harfbuzz.o:(void AAT::StateTableDriver<AAT::ObsoleteTypes, void>::drive<AAT::RearrangementSubtable<AAT::ObsoleteTypes>::driver_context_t>(AAT::RearrangementSubtable<AAT::ObsoleteTypes>::driver_context_t*)) in archive /tmp/rustcAie9yo/libharfbuzz_sys-104a993656c30b7b.rlib
          >>> referenced 2 more times

The closest I suppose I am to finally perform linking is by doing the alternative (2) but haven't found a solution to it. Doing https://serverfault.com/a/266141 yielded that the link already existed.

@mbrubeck perhaps you are familiar with this kind of problem?

Did you install musl-dev on Ubuntu and libgcc that musl depends on?

Yes... I think so. Here are the commands I run (either in a container or WSL2):

sudo apt update &&
sudo apt upgrade -y
&& sudo apt install -y pkg-config musl-dev musl-tools libx11-dev libxkbfile-dev libxkbfile-dev libfreetype6-dev libfontconfig libfontconfig1-dev libstdc++6 python3
sudo ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib/x86_64-linux-gnu/libstdc++.so

I don't know if this is of any help here but I use a docker image and have defined two functions to be used in my zsh shell (should work for bash the same). I should mention that this is Fedora Linux.

function musl-build() {
  podman run \
    -v cargo-cache:/root/.cargo/registry:Z \
    --net=host \
    -v "$PWD:/volume:Z" \
    --rm -it \
    clux/muslrust:stable cargo build --release

  }



function musl-build-nightly() {
  podman run \
    -v cargo-cache:/root/.cargo/registry:Z \
    --net=host \
    -v "$PWD:/volume:Z" \
    --rm -it \
    clux/muslrust cargo build --release
  }

I had also tried that very same Docker image without success.

Is this correct right?

I'm sorry. I'm not near my computer in a few weeks so I cannot help you.

Perhaps @kornel would like to help you.

If you're willing to tolerate use of Docker, then there's a pre-made image for cross-compilation:

1 Like

I'm going try this one! I've tried two other all-in-one solutions for musl compilation but none worked

Tried using your suggestion, and after adding missing libraries, I keep getting errors as:

/usr/lib/x86_64-linux-gnu/libexpat.so: undefined reference to ...
/usr/lib/x86_64-linux-gnu/libfontconfig.so: undefined reference to ...
/usr/lib/x86_64-linux-gnu/libfreetype.so: undefined reference to ...
/usr/lib/x86_64-linux-gnu/libxcb.so: undefined reference to ...

How can verify I have those libraries installed? Most of them are trying to function in glibc for different versions:

GLIBC_2.25
GLIBC_2.2.5
GLIBC_2.3
GLIBC_2.3.4
GLIBC_2.7
GLIBC_2.11
GLIBC_2.4
GLIBC_2.14
GLIBC_2.3.2

When doing ldd --version looks like I have the glibc version 2.27. Why do I need to have the newer version of glibc if supposedly I am linking statically?

If you're building for MUSL, you can't use any dynamic libraries. Especially, you can't let the build touch anything for -linux-gnu. These are effectively incompatible operating systems. You can't use any Linux package managers to get pre-built dependencies, since they're all built around GNU libc.

Use cargo tree to find what *-sys crates your build pulls in, and ensure that every single one of them is built from source, or removed from your project.

Unfortunately, there's no standard for how sys crates enable building from source. Some may have a Cargo feature like vendored or fallback. Some may require setting an env var. Some may require you to get source tarball yourself, cross-build it yourself for MUSL, and set an env var with the build location.

1 Like

Awesomely valuable, thank you!
Will every *-sys crate always have a way of being compiled from source right? What happens if the *-sys crate is way up on the dependencies hierarchy, for example I dependend on A, A on B, and B on *-sys?

Unfortunately there's no guarantee that a sys crate can build from source. Some may just call pkg-config and hope for the best.

If you need to set an env var for a sys crate, it doesn't matter where it's in the dependency tree.

If you need to set a Cargo feature for a sys crate, and it's not your direct dependency, you can add it as your direct dependency and set the feature yourself. Features apply to all copies of the crate everywhere.

If a crate that is a dependency of a dependency is broken, you can use [patch.crates-io] section to replace it with your own code.

That is great info, once again. I've also found this amazing nugget of info of yours:


That explains so much. This should be included in one of the rust-lang books, is awesome!
How can I discover which method is being used by the crate to enable, if possible, compilation from source? In this crate of yours https://github.com/kornelski/rust-lcms2-sys is straight forward, but looks like some of my dependencies aren't that explicit.

You'd have to check crate's readme. If you really need to dig in, check [features] section of Cargo.toml for clues, or build.rs to see what it's actually doing.