5

I want to use the newest version of Boost library and have the following contents of a CMakeLists.txt file:

cmake_minimum_required (VERSION 3.0)
project (foo)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DBOOST_ERROR_CODE_HEADER_ONLY -lpthread")
# set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread")

add_executable (first first.cpp)

With that I keep getting the following linker error:

undefined reference to `pthread_detach

However, if I compile my code without the use of CMake, with the following command:

g++ foo.cpp -std=c++11 -DBOOST_ERROR_CODE_HEADER_ONLY -lpthread

It works fine.

The question is how to get it to work using CMake. Why doesn't it work when I specify the compiler flags via setting CMAKE_CXX_FLAGS? I thought I might have to specify CMAKE_EXE_LINKER_FLAGS instead, but doing that doesn't help at all.

Kevin
  • 16,549
  • 8
  • 60
  • 74
user6646922
  • 497
  • 1
  • 6
  • 15
  • Possible duplicate of [cmake and libpthread](https://stackoverflow.com/questions/1620918/cmake-and-libpthread) – Tsyvarev May 26 '18 at 17:39

2 Answers2

16

CMake has native support for all the things you're trying to solve by explicit flag specification, so you should use that instead:

cmake_minimum_required (VERSION 3.0)
project (foo)

add_executable (first first.cpp)
target_compile_options (first PRIVATE -std=c++11)
target_compile_definitions (first PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
target_link_libraries (first pthread)

If you can increase your minimum CMake version requirement to 3.1, you can replace the hard-coded std flag with native CMake too:

cmake_minimum_required (VERSION 3.1)
project (foo)

add_executable (first first.cpp)
set_target_properties (first PROPERTIES
  CXX_STANDARD 11
  CXX_STANDARD_REQUIRED TRUE
  CXX_EXTENSIONS FALSE
)
target_compile_definitions (first PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
target_link_libraries (first pthread)

The advatange is that not all compilers express "use C++11 without extensions" the same way, and CMake will translate the requirement to the correct flags for you.

If you're going to need the same C++11 setup for many executables, you can instead set CMake variables which prepopulate the properties. Note that the variables must be set before the executables are created:

set (CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_STANDARD_REQUIRED TRUE)
set (CMAKE_CXX_EXTENSIONS FALSE)

add_executable (first first.cpp)
target_compile_definitions (first PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
target_link_libraries (first pthread)

add_executable (second second.cpp)
target_compile_definitions (second PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
target_link_libraries (second pthread)

# ... and so on
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • 2
    Additionally, starting with CMake 3.8, it's possible to do: `target_compile_features(first PUBLIC cxx_std_11)` to set C++ standard. This way targets that depend on `first` will automagically be built with C++11 flags. – joe_chip May 26 '18 at 18:12
2

In general, one should specify libraries using target_link_libraries instead of overriding linker flags directly.


In this case, you can do it differently:

add_executable (first first.cpp)

find_package(Threads REQUIRED)
target_link_libraries(first PRIVATE Threads::Threads)

Threads::Threads above stands for threading library for your system. This has the advantage of being cross platform - when you want to compile your project on, e. g. Windows, linker won't complain about unknown pthread library.

For the same reason, setting C++ version the way @Angew does in theirs answer is preferred - it just works, without having to manually adjust flags for each compiler.

joe_chip
  • 2,468
  • 1
  • 12
  • 23