3

How can I get CMake to link pthread statically on Windows? I use MSYS2 MinGW 32 bit and cmake v3.7.

What I would like to achieve is a compiler invocation like

g++ -static-libgcc -static-libstdc++ -std=c++11 -o test test.cpp -Wl,-Bstatic -lpthread

Setting

target_link_libraries(test PUBLIC "-Wl,-Bstatic -lpthread")

results in -Wl,-Bdynamic -Wl,-Bstatic -lpthread being called. If I change CMAKE_EXE_LINKER_FLAGS, pthreads is included before my object files and thus symbols are not resolved.

zeeMonkeez
  • 5,057
  • 3
  • 33
  • 56
  • One clarification: 1) When you say you want to link pthread statically on Windows, do you mean to produce a static library (test will be a static library?) or you want to link to the pthread static library? – fedepad Jan 27 '17 at 09:16
  • @fedepad I want to produce an executable linked to static pthread (as the updated call to g++ would produce) – zeeMonkeez Jan 27 '17 at 20:28

2 Answers2

1

find the Threads module:

find_package(Threads REQUIRED)
add_executable(myApp main.cpp)
target_link_libraries(myApp Threads::Threads)

Note from the documentation:

For systems with multiple thread libraries, caller can set CMAKE_THREAD_PREFER_PTHREAD

Nicolas Holthaus
  • 7,763
  • 4
  • 42
  • 97
  • Adding that target does not seem to change the linker call. `pthread` does not appear on the command line (but cmake finds it according to `CMakeCache.txt`: `//Have symbol pthread_create CMAKE_HAVE_LIBC_CREATE:INTERNAL=1 //Have include pthread.h CMAKE_HAVE_PTHREAD_H:INTERNAL=1` – zeeMonkeez Jan 27 '17 at 03:21
  • Thanks for your answer. It seems really `target_link_libraries(ptest2 -static)` is all that was needed here. – zeeMonkeez Jan 27 '17 at 21:31
1

As the FindThreads.cmake mention in its source code:

# For systems with multiple thread libraries, caller can set
#
# ::
#
#   CMAKE_THREAD_PREFER_PTHREAD
#
# If the use of the -pthread compiler and linker flag is preferred then the
# caller can set
#
# ::
#
#   THREADS_PREFER_PTHREAD_FLAG
#
# Please note that the compiler flag can only be used with the imported
# target. Use of both the imported target as well as this switch is highly
# recommended for new code.

So in addition to what already said, you might need to set the additional flag THREADS_PREFER_PTHREAD_FLAG. In some systems (OSX, etc.) this flag is needed at compilation time because it defines some macros that would be missing if you would only link -lpthread.

set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
add_library(test test.cpp)
set_property(TARGET test PROPERTY CXX_STANDARD 11)
set_target_properties(test PROPERTIES LINK_SEARCH_START_STATIC 1)
set_target_properties(test PROPERTIES LINK_SEARCH_END_STATIC 1)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
find_package(Threads REQUIRED)  

target_link_libraries(test Threads::Threads)  

Does it help?

fedepad
  • 4,509
  • 1
  • 13
  • 27
  • 1
    Thanks for taking time to answer. It turns out that `target_link_libraries(test -static)` is all that's needed on this platform. – zeeMonkeez Jan 27 '17 at 21:30
  • Nice, good to know, as I think I've never seen that -static called inside target_link_libraries()... http://stackoverflow.com/questions/16991225/cmake-and-static-linking – fedepad Jan 27 '17 at 23:24
  • say the docs: A link flag: Item names starting with -, but not -l or -framework, are treated as linker flags. Note that such flags will be treated like any other library link item for purposes of transitive dependencies, so they are generally safe to specify only as private link items that will not propagate to dependents. — that's why my original attempt didn't work. – zeeMonkeez Jan 28 '17 at 00:58