3

Environment

ubuntu 16.04, gcc 5.4.0, cmake 3.5.1

Question

  1. target_link_libraries(promise pthread)
  2. target_link_libraries(promise -pthread)
  3. target_link_libraries(promise -lpthread)

What's the differences, which is better ?


Problem

promise.cpp

std::promise<int> pr;
auto fut = pr.get_future();
pr.set_value(10); // throw std::exception and terminate

CMakeLists.txt

add_executable(promise promise.cpp)
target_link_libraries(promise pthread)

Solution

Modify CMakeLists.txt slightly.

add_executable(promise promise.cpp)
target_link_libraries(promise -pthread)

I found the answer from here. But I don't know why ?

But, the best solution is portable.

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
target_link_libraries(promise Threads::Threads)
Community
  • 1
  • 1
pingsoli
  • 427
  • 4
  • 11

3 Answers3

6

All calls are generally wrong. As answered by @vre, you should use find_package(Threads) instead.

But all these calls are effectively the same!

Calls

target_link_libraries(promise pthread)

and

target_link_libraries(promise -lpthread)

are transformed into the same linker's command line: for parameters not starting with -, CMake will add -l automatically (from target_link_libraries documentation):

A plain library name: The generated link line will ask the linker to search for the library (e.g. foo becomes -lfoo or foo.lib).

While calls

target_link_libraries(promise -lpthread)

and

target_link_libraries(promise -pthread)

are translated into different flags, for linking process these flags means the same.

Option -pthread, passed to gcc, would add additional compile definitions. But parameters for target_link_libraries are not used for compilation.


Why using find_package(Threads) is correct

If one uses

set(THREADS_PREFER_PTHREAD_FLAG ON) # Without this flag CMake may resort to just '-lpthread'
find_package(Threads)

a library target Threads::Threads is created, with additional compile and link options -pthread attached to it as an interface.

When use

target_link_libraries(promise Threads::Threads)

CMake automatically propagates interface compile and link options, thus promise target is both compiled and linked with -pthread option.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • You should have tried it, but, CMake generates `-lpthread` option, I have no idea what happened. – pingsoli Apr 11 '18 at 08:38
  • Do you mean not `-lpthread` but `-pthread` option? CMake generates `-pthread` option for **link command** ("Linking C executable"), but not for *compile command* ("Building C object"). This is what my answer talks about. – Tsyvarev Apr 11 '18 at 08:46
  • I used `find_packages(Threads) target_link_libraries(promise Threads::Threads)`, then `cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON ..`, `make promise` I found g++ used `-lpthread` not `-pthread` option. It's confusing. – pingsoli Apr 11 '18 at 09:10
  • 1
    Then please add `set(THREADS_PREFER_PTHREAD_FLAG ON)` before the `find_package` call. This is why I linked to the FindThreads.cmake documentation. – vre Apr 11 '18 at 09:21
  • 2
    I have updated the answer with *THREADS_PREFER_PTHREAD_FLAG* flag using. – Tsyvarev Apr 11 '18 at 09:24
1

First, we can use cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON to see the underlying commands of make.

target_link_libraries(promise pthread) and target_link_libraries(promise -lpthread) will result the same link option: -lpthread, like:

/usr/bin/c++   -std=c++11  -rdynamic CMakeFiles/promise.dir/promise.cpp.o  -o promise -lpthread

However, target_link_libraries(promise -pthread) will give you -pthread option:

/usr/bin/c++   -std=c++11  -rdynamic CMakeFiles/promise.dir/promise.cpp.o  -o promise -pthread

The difference between -pthread and -lpthread is well explained here. In general, you should use -pthread and target_link_libraries(promise -pthread).

btw, clang built binary seems ok with both options.

halfelf
  • 9,737
  • 13
  • 54
  • 63
1

I would suggest using the modern CMake way by means of imported targets:

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
target_link_libraries(promise Threads::Threads)

This does not only add the library dependency, it also sets the compile option and works on almost all platforms. See the answers to the following post for further details: Difference between -pthread and -pthreads for C/C++ on Ubuntu 14.04

And have a look into the fine documentation of FindThreads.cmake module: https://cmake.org/cmake/help/v3.11/module/FindThreads.html

vre
  • 6,041
  • 1
  • 25
  • 39