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/01b7088a06e7310c8773e78e8be4f6e8…
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
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com