4

I got the following error with the first running of the command

cmake .

But if I run the command again, the compilation succeed. That is, I have to run cmake twice for make the project compiled. Why is it so? How could I fix it?

Error message:

CMakeFiles/exec.dir/Timer.cpp.o: In function `std::thread::thread<Timer::Timer()::{lambda()#1}>(Timer::Timer()::{lambda()#1}&&)':
/usr/include/c++/7/thread:122: undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
CMakeFiles/exe.dir/build.make:146: recipe for target 'exe' failed
make[2]: *** [exe] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/exe.dir/all' failed
make[1]: *** [CMakeFiles/exe.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)

set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -g -std=c++14 -std=c++11 -std=c++17 ")

project(myproject)

set(SOURCE_FILES main.cpp Timer.cpp TimerEntity.cpp)
add_executable(exe ${SOURCE_FILES})
GccGUY
  • 341
  • 1
  • 3
  • 12
  • 1
    Are you sure -pthread should be in compilation flags? Missing references are link time errors, and external libraries are pointles at the point of compilation into object file. – KIIV Nov 20 '19 at 08:17
  • 1
    Related: https://stackoverflow.com/questions/1620918/cmake-and-libpthread. That question describes working with pthreads in CMake. – Tsyvarev Nov 20 '19 at 11:38

3 Answers3

6

It is not usually noted, but appending compiler flags via

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} <...>")

should be placed after the project() call.

Exactly project() call sets the initial value of CMAKE_CXX_FLAGS variable.

Normally, project() call is issued just after the cmake_minimum_required():

cmake_minimum_required(VERSION 3.10)
project(437_Hw1)

...

Details

In your current code, when you call cmake the first time, your first setting set(CMAKE_CXX_FLAGS ...) is replaced by the value of the following project() call and stored in the CACHE.

When you call cmake the second time, CMAKE_CXX_FLAGS variable is already set (it is loaded from the cache). So, set(CMAKE_CXX_FLAGS ...) sets the variable to correct value. Moreover, following project() doesn't change CMAKE_CXX_FLAGS variable because it finds it already in the cache.

Community
  • 1
  • 1
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
3

I reworked your CMakeLists.txt to use modern CMake:

cmake_minimum_required(VERSION 3.7)
project(437_Hw1)

# CMake can set the standard in a cross-platform way for you
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_BUILD_TYPE Debug)

set(SOURCE_FILES main.cpp SubTimer.cpp TimerEntity.cpp)
add_executable(exe ${SOURCE_FILES})

# These two lines add the platform-specific magic for the right threading library/headers.
find_package(Threads)
target_link_libraries(exe Threads::Threads)
Botje
  • 26,269
  • 3
  • 31
  • 41
2

I suggest you replace the line

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -g -std=c++14 -std=c++11 -std=c++17 ")

with

set(CMAKE_CXX_STANDARD 17)
target_link_libraries(exe pthread)

and see if that helps.

Arne J
  • 415
  • 2
  • 9
  • 1
    you are saying. I cannot use on windows ? So, how could i use thread? If I write in ubuntu then in order to work on windows. – GccGUY Nov 20 '19 at 08:48
  • Then you will need a wrapper interface for the windows threads libraries. You could write your own using the windows API, or preferably one that is already there, like boost or qt. – Arne J Nov 20 '19 at 08:53
  • 3
    @herobee1965 Use `std::thread` (part of the C++11 standard and up) instead of `pthread` (Unix library that implements threads) – Botje Nov 20 '19 at 08:59
  • @Botje I use std::thread but when i compile. I need to put pthread? – GccGUY Nov 20 '19 at 09:00
  • That is true, on Linux you need to specifically link to pthread when using `std::thread`, the linker will not do this for you. I don't know what it gives on Windows. Maybe no need to link to anything at all ? – Arne J Nov 20 '19 at 09:02