65

I know there is something like find_package(Threads) but it doesn't seem to make a difference (at least by itself). For now I'm using SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-pthread"), but it doesn't look like a correct solution to me.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Tomasz Grobelny
  • 2,666
  • 3
  • 33
  • 43
  • 15
    You are marking this 2011 post as a duplicate of a 2013 post. Please! – Henk van Boeijen Mar 05 '17 at 15:49
  • 2
    @HenkvanBoeijen, exactly, also this question has better answers – maxschlepzig May 01 '17 at 22:18
  • 1
    @maxschlepzig That's highly opinion based. I think good quality questions with accepted answers and a decent amount of upvotes should never be closed. – Henk van Boeijen May 01 '17 at 23:28
  • @HenkvanBoeijen, I am referring to this 2011 question. – maxschlepzig May 02 '17 at 07:34
  • 1
    @maxschlepzig I am sure there are better possible answers to this question, but is the one listed really better? If you look it actually does not answer the question this user asked which is "what is a better way to add the pthreads option to my compile line." The question asked and answered by the post this is marked a duplicate of is why does the accepted answer listed here not work sometimes. Hint: cause your project settings are incorrect. – ltc Jan 31 '18 at 01:57
  • 2
    This question is _how do I get thread into a c++ cmake module_. The other question is _how do I get cmake to recognize a module is c++_. It's actually asking a different question on the same topic, and the short question with the very short good answer by @ltc make this post more useful for this specific question. – gerardw Dec 13 '18 at 02:29
  • Reopened. Don't see a reason to have the **general** question about using pthread in CMake to be marked as a *duplicate* for the **specific** problem ("Could NOT find Threads") about such usage. – Tsyvarev Sep 10 '20 at 12:34

4 Answers4

110

The Threads module in the latest versions (>= 3.1) of CMake generates the Threads::Threads imported target. Linking your target against Threads::Threads adds all the necessary compilation and linking flags. It can be done like this:

set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)

add_executable(test test.cpp)
target_link_libraries(test Threads::Threads)

Use of the imported target is highly recommended for new code, according to the CMake docs

starball
  • 20,030
  • 7
  • 43
  • 238
Alex Che
  • 6,659
  • 4
  • 44
  • 53
  • 1
    What's the difference between the 2 flags? What happens if you just find_package(Threads REQUIRED) and link? – Jay May 04 '20 at 11:17
  • 4
    From the linked documentation page: `CMAKE_THREAD_PREFER_PTHREAD` - prefer pthread library on system with multiple thread libraries available. `THREADS_PREFER_PTHREAD_FLAG` - prefer `-pthread` compiler and linker flag. Omitting those two options can probably import another threads library or skip the `-pthread` flag during compilation or linking. – Alex Che May 04 '20 at 17:23
75

find_package( Threads ) calls a CMake module that first, searches the file system for the appropriate threads package for this platform, and then sets the CMAKE_THREAD_LIBS_INIT variable (and some other variables as well). It does not tell CMake to link any executables against whatever threads library it finds. You tell CMake to link you executable against the "Threads" library with the target_link_libraries() command. So, for example lets say your program is called test. To link it against threads you need to:

find_package( Threads )
add_executable( test test.cpp )
target_link_libraries( test ${CMAKE_THREAD_LIBS_INIT} )
ltc
  • 3,313
  • 1
  • 28
  • 26
  • 4
    But the point is to add this "-pthread" option during compilation, not linking. – Tomasz Grobelny Mar 23 '11 at 13:07
  • 1
    Oh, I see what you mean. I do not believe there is a special way to do that. On most platforms -pthread adds -D_REENTRANT and -lpthread. You could add -D_REENTRANT fairly easily (btw this is a noop on any modern platform I have ever checked on). The real question though is what type of portability are you trying to get. The -pthead option is a gcc option that may not exist for other compilers. If you want to support the most OS platforms possible, with gcc, then what you are currently doing is the way to go. If you want to support multiple compilers on a few platforms use the above. – ltc Mar 23 '11 at 19:39
  • Personally I don't care about this option. The problem is that Boost.Interprocess cares. Without it the compiler exits on an #error directive that clearly states that -pthread is needed (there were alternatives given for different systems - cannot quote it now as I don't have access to that system at the moment). – Tomasz Grobelny Mar 23 '11 at 21:18
  • Ahh. Well there is no way that boost can know if you actually added the -pthread option to the gcc command line. What it can know is if the _REENTRANT macro is set. I took a look and that is indeed what it does to check if the -pthread option is set. At any rate it looks like given your requirements the solution that you already implemented is fine. I would just leave it the way it is. – ltc Mar 24 '11 at 08:10
  • I'm getting "FindThreads only works if either C or CXX language is enabled" but I don't understand why. How do I enable c++ on a make file? – m4l490n Jul 12 '18 at 22:30
  • This answer is wrong, The correct answer is https://stackoverflow.com/a/39547577/775806 – n. m. could be an AI Mar 07 '21 at 09:57
  • @n.'pronouns'm. I do not believe it is fair to say that this answer is wrong. It has been a long time, but I believe it was accurate in 2011. I am pretty sure that the most upvoted answer's method was not available until maybe 2015 or so? Certainly, no one should do it this way now, but it seems like there should be a better way to mark that. – ltc Mar 08 '21 at 21:46
  • 1
    @ltc I'm sorry I wasn't paying attention to the dates. Let's say that this is not the most accurate answer as of today. – n. m. could be an AI Mar 08 '21 at 22:02
10

How about the following:

set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
if(CMAKE_USE_PTHREADS_INIT)
    set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-pthread")
elseif(...)
    ...
endif()
add_executable( test test.cpp )
target_link_libraries( test ${CMAKE_THREAD_LIBS_INIT} )
user3701085
  • 117
  • 1
  • 2
  • The line `set(CMAKE_THREAD_PREFER_PTHREAD TRUE)` rescued me from hours of trying to get [beignet](http://www.freedesktop.org/wiki/Software/Beignet/) compile (Debian Jessie) – Jealie Oct 20 '14 at 17:57
  • 4
    Unless running cmake < 3.1, favor linking the namespaced target (import target) directly instead of the `${CMAKE_THREAD_LIBS_INIT}` variable (see answer by @alex-che). – helmesjo Mar 04 '18 at 11:12
  • 1
    I agree with helmesjo here an article that explains why we should favor targets over variables https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/ – jav Nov 05 '19 at 05:55
-1

If I explicitly specify the default entry point and the library to use, it compiles without problems. The default entry point here is to specify the version in cmake. cmake_minimum_required(...), target_link_libraries(...) Below is an example.

# important
cmake_minimum_required(VERSION 2.8)

project(main)

# set c++ version & etc...
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# important
find_package( Threads )

add_executable(main main.cpp)

# important
target_link_libraries(main ${CMAKE_THREAD_LIBS_INIT})
romulus
  • 1
  • 1