The changes for better c11 thread use in swipl 9.0.4 (stable) failed to link on FreeBSD12.4 with the error:
Undefined symbol “cnd_init”
Adding to LDFLAGS -lstdthreads permits a successful build.
Earlier, I had modified cmake/Params.cmake
if(MULTI_THREADED)
set(C_CFLAGS “${C_CFLAGS} -pthread”)
endif()
by appending -lstdthreads but to no avail. (Aside: I did change this line to be -lpthread -lstdthreads, but it doesn’t appear to be used during the build??)
cmake/Params.cmake is definitely the wrong place. It is there to populate a file pams.h which is used to populate some Prolog flags that help the system building foreign extensions.
Probably this should be handled in cmake/Config.h. I’m a little confused here. There are some references to variables set by cmake FindThreads(), but I see no call to this. This probably needs some study. Feel free to investigate
Because swi-pl uses cnd_init cnd_destroy and probably others, the swipl package requires linking with -lstdthreads.
I suspect something like cmake/FindGMP.cmake is required to test for the existance of
threads.h
and the location of
libstdthreads.so.0
which in FreeBSD is located at
/usr/include/threads.h
/usr/lib/libstdthreads.so.0
OR
modify cmake/Config.cmake to include tests for threads.h in a manner similar to pthread.h and then, if FreeBSD include libstdthreads. Though this seems like a lot of work for just FreeBSD
I have no familiarity with Linux (or cmake), I’m guessing that these c11 calls are incorporated into their standard thread library, while FreeBSD has these calls resolved in libstdthreads.
If this is unique to FreeBSD, then it probably suffices for the “port maintainer” to include
LDFLAGS+= -lstdthreads
in the FreeBSD port lang/swi-pl/Makefile
And, finally, add Threads::Threads as input for libswipl. Now, on Linux that doesn’t do a lot as when we inspect FindThreads.cmake (which is what find_package(Threads) uses) it roughly does
find pthread.h
Test whether we can use threads without any flags. This is the case for Linux, where the thread functions are part of libc. So, Linux is done here
Try -pthread. That should be what happens for FreeBSD.
So, we need to find out why this doesn’t work. Try to find FindThreads.cmake and check the messages it produces. The thread detection is early in the configuration.
Hi Jan, I appreciate your prompt attention. Unfortunately there isn’t a FindThreads.cmake, however the pthread test is correct and finds and uses libthr during the build. Extract from the build log includes
– Looking for threads.h
– Looking for threads.h - found
– Looking for mach/thread_act.h
– Looking for mach/thread_act.h - not found
– Looking for pthread_np.h
– Looking for pthread_np.h - found
…
which is good and consistent with the
CMakeLists.txt: set(THREADS_PREFER_PTHREAD_FLAG TRUE)
I have included first few libraries from a ldd of swipl, which is achieved with LDFLAGS= -lstdthreads:
/usr/local/bin/swipl:
libstdthreads.so.0 => /usr/lib/libstdthreads.so.0 (0x80106e000)
libtcmalloc_minimal.so.4 => /usr/local/lib/libtcmalloc_minimal.so.4 (0x801074000)
libswipl.so.9 => /usr/local/lib/swipl/lib/amd64-freebsd/libswipl.so.9 (0x801253000)
libc.so.7 => /lib/libc.so.7 (0x801481000)
libthr.so.3 => /lib/libthr.so.3 (0x801880000)
Apologies re FindThreads.cmake I have no familiarity with cmake, I was looking within the build hierarchy for swipl. Yes it is in /usr/local/share/cmake/Modules/FindThreads.cmake and does contain pthread tests
I inserted
set(CMAKE_C_STANDARD 11) at line 220 of the top level CMakeLists.txt. The build failed due to undefined cnd_init, per original post.
When I force linking with lstdthreads, swipl 9.0.4 works correctly with the simple threaded tests that I use.
I suspect that libstdthreads isn’t sought by cmake, so not a swipl issue. If you agree I’ll raise this with the FreeBSD maintainer of cmake?
Aside: Of the 1516 ports/applications that I build/use on servers, only swipl and swipl-ld require lstdthreads; 1254 use libthr (pthread).
Yes, I think it makes sense to raise this with cmake. Either directly or through the FreeBSD channels. There is already some discussion on the cmake forum about when -pthread should be tested.
Seems related to demanding C11. I always try to stick with the oldest acceptable standard, so C99 was good enough for a long time. Some internal reorganization became a lot simpler using C11 Generics though. I think it is up to FreeBSD and cmake to make sure C11 works at some point.