Hello,
Today I was investigating a link issue that occurs in Buildroot with the libarchive package. It turns out that the code of this package uses pthread_mutex_lock/pthread_mutex_unlock in some places to be thread-safe, but does *not* link with the libpthread library.
I was originally surprised that this could even work, but I discovered that the libc intentionally provides a stub implementation of pthread_mutex_lock/unlock. The idea behind this is that a library can use pthread_mutex_lock/unlock without linking to libpthread. This way, if the application using the library is single-threaded and doesn't link with libpthread, pthread_mutex_lock/unlock are no-ops. On the other hand, if the application using the library is multi-threaded, it will link with libpthread, and therefore the libpthread versions of pthread_mutex_lock/unlock will be used.
This all seems good, until you get to static linking. Indeed with uClibc-ng, the following program:
#include <pthread.h>
int main(void) { pthread_mutex_t lock; pthread_mutex_lock(&lock); return 0; }
will link perfectly fine with dynamic linking:
$ ./host/usr/bin/arm-linux-gcc -o foo foo.c $ ./host/usr/bin/arm-linux-readelf -d foo | grep NEEDED 0x00000001 (NEEDED) Shared library: [libc.so.0]
but will fail to build with static linking:
$ ./host/usr/bin/arm-linux-gcc -o foo foo.c -static /tmp/ccda8vkc.o: In function `main': foo.c:(.text+0x14): undefined reference to `pthread_mutex_lock' collect2: error: ld returned 1 exit status
And this explains the build failures like http://autobuild.buildroot.net/results/01b/01b7088a06e7310c8773e78e8be4f6e88... that we are seeing in Buildroot.
It is worth mentioning that using the musl C library, this test case works fine in both dynamic linking and static linking cases (and the libarchive error also does not occur).
Thomas