TLDR: Split pthread flags out of ldflags, and stop using them when building libconsensus.
Building libconsensus on Linux using Clang currently warns. i.e:
0./autogen.sh
1./configure --disable-tests --disable-bench --with-utils=no --with-daemon=no --with-gui=no --disable-wallet --with-libs=yes CC=clang CXX=clang++
2make V=1 -j6
3... -Wl,-z -Wl,relro -Wl,-z -Wl,now -pthread -Wl,-soname -Wl,libbitcoinconsensus.so.0 -o .libs/libbitcoinconsensus.so.0.0.0
4clang: warning: argument unused during compilation: '-pthread' [-Wunused-command-line-argument]
5clang: warning: argument unused during compilation: '-pthread' [-Wunused-command-line-argument]
Besides wanting to quiet the warnings, after digging into this it seemed we could clean up how we are passing around the pthread flags. I also learnt a bit more about how libtools builds shared libraries, and that passing -pthread
on the link line wouldn’t be enough to link against pthreads anyways, due to libtools usage of -nostdlib (see related discussion where we build DLLs).
This can be demonstrated with a patch to libconsensus:
0diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
1index 15e204062..10bf3582f 100644
2--- a/src/script/bitcoinconsensus.cpp
3+++ b/src/script/bitcoinconsensus.cpp
4@@ -10,6 +10,8 @@
5 #include <script/interpreter.h>
6 #include <version.h>
7
8+#include <pthread.h>
9+
10 namespace {
11
12 /** A class that deserializes a single CTransaction one time. */
13@@ -127,3 +129,10 @@ unsigned int bitcoinconsensus_version()
14 // Just use the API version for now
15 return BITCOINCONSENSUS_API_VER;
16 }
17+
18+void *func_pthread(void *x) { return x; }
19+
20+void f() {
21+ pthread_t t;
22+ pthread_create(&t,0,func_pthread,0);
23+}
After building, you’ll find you have a libbitcoinconsensus.so
using pthread symbols, but which isn’t linked against libpthread:
0ldd -r src/.libs/libbitcoinconsensus.so
1 linux-vdso.so.1 (0x00007ffe49378000)
2 libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f553cee7000)
3 libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f553cda2000)
4 libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f553cd88000)
5 libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f553cbc5000)
6 /lib64/ld-linux-x86-64.so.2 (0x00007f553d15d000)
7undefined symbol: pthread_create (src/.libs/libbitcoinconsensus.so)
This libtool behaviour has been known about for some time, i.e this thread from 2005, describes the same issue. The suggestion from libtool maintainers at the time is to add -lpthread
to LDFLAGS.
Also worth noting is that some of the users in those threads were also using the AX_PTHREADS
macro, same as us, to determine how to compile with/link against pthreads. This macro has recently been updated, with reference to this issue. You can compare the output from the version we currently use, to the new version:
0# our ax_pthread macro:
1 PTHREAD_CFLAGS = -pthread
2 PTHREAD_LIBS =
3 PTHREAD_CC = gcc / clang
4
5# the new ax_pthread macro
6 PTHREAD_CFLAGS = -pthread
7 PTHREAD_LIBS = -lpthread
8 PTHREAD_CC = gcc / clang
Note that as part of this PR I’ve also added PTHREAD_LIBS
to the split out flags. Although we weren’t using it anywhere previously (and wouldn’t have seemed to matter for the most part, given it was likely empty for most builders), the macro assumes it’s use. i.e:
NOTE: You are assumed to not only compile your program with these flags, but also to link with them as well. For example, you might link with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS … $PTHREAD_LIBS $LIBS