rustpthreadsx86-64libcmusl

How to Fix Undefined Reference To PThread on Musl x86_64 LibC?


I've been trying to compile against Musl for a while now. My goal is to make a game engine binary which can execute on as many x86_64 Linux distros as possible with the same binary.

The problem is, symbols such as pthread_mutex_init are not found by the linker, x86_64-linux-musl-gcc, even though pthread is embedded into the Musl libc as per Musl design.

I'm building the engine in Rust and am using the command, cargo build --release --target=x86_64-unknown-linux-musl --bin catgirl-engine for debugging the compilation steps.

I've created an Asciinema Recording to demonstrate the compilation failure.

The static error is:

  = note: /home/alexis/Desktop/game/build/x86-64-linux-musl-cross/bin/../lib/gcc/x86_64-linux-musl/9.4.0/../../../../x86_64-linux-musl/bin/ld: /home/alexis/Desktop/game/android/app/jni/SDL/build/libSDL2.a(SDL_sysmutex.c.o): undefined reference to symbol 'pthread_mutex_init'
          /home/alexis/Desktop/game/build/x86-64-linux-musl-cross/bin/../lib/gcc/x86_64-linux-musl/9.4.0/../../../../x86_64-linux-musl/bin/ld: /home/alexis/Desktop/game/build/x86-64-linux-musl-cross/bin/../x86_64-linux-musl/lib/libc.so: error adding symbols: DSO missing from command line
          collect2: error: ld returned 1 exit status

Before I found out that pthread was embedded in Musl's libc, I tried linking to the lib directory as well as specifying the include directory for the headers. I've even tried linking against the files in Debian packages libc6-dev-amd64-cross and musl-dev.

I was expecting to compile the engine without being tied to a specific version of libc. This is to increase mass portability as then I'd just need to ship my engine with the custom version of SDL, SDL_image, and SDL_ttf.

I already successfully build the engine for Android and package SDL, SDL_image, and SDL_ttf with the Android build of the app, so I'd like to do the same with the x86_64 version.

I first discovered this problem when I learned the glibc version on Github Actions is far newer than what Debian provides.

Here's my ~/.cargo/config

[target.x86_64-unknown-linux-musl]
ar = "/home/alexis/Desktop/game/build/x86-64-linux-musl-cross/bin/x86_64-linux-musl-ar"
linker = "/home/alexis/Desktop/game/build/x86-64-linux-musl-cross/bin/x86_64-linux-musl-gcc"
rustflags = ["-L/home/alexis/Desktop/game/android/app/jni/SDL/build", "-L/home/alexis/Desktop/game/android/app/jni/SDL_image/build", "-L/home/alexis/Desktop/game/android/app/jni/SDL_ttf/build", "-L/home/alexis/Desktop/game/build/x86-64-linux-musl-cross/lib", "-L/home/alexis/Desktop/game/build/x86-64-linux-musl-cross/x86_64-linux-musl/lib", "-Clink-arg=-Wl,-rpath,.,-rpath-link,/home/alexis/Desktop/game/android/app/jni/SDL/build", "-Clink-arg=-L/home/alexis/Desktop/game/build/x86-64-linux-musl-cross/x86_64-linux-musl/lib", "-Clink-arg=-lpthread"]

The last build I made of x86_64-linux-musl-cross was based on this commit. As Github Actions (through Ubuntu) uses a newer libc than my laptop (latest release Debian), I am using a local build of x86_64-linux-musl-cross for my local building and am using the Github build of the same commit for remote building.


Solution

  • As per @JohnBollinger's suggestion, what I needed to do was explicitly link the c library. I added the rust flag, -Clink-arg=-Wl,-lc, to the build.

    There was other stuff I needed to solve, but they are different problems. The solution I provided in this answer is the correct one to solve this question.