2

I am trying to build a CMake project, below is a sample code of what I am trying to do.

I have two header files I am developing and I want to call a member function in class Processor from class Loader using the thread header. Here is the code, along with the CMake, and the error message I got after running the make command.

CMakeLists.txt

cmake_minimum_required(VERSION 3.2.2)
project(c-plus-assignment)
## C++11 Flags
add_compile_options(-std=c++11)
add_compile_options(-pthread)
add_compile_options(-Werror=return-type)                   # error on missing return type
add_compile_options(-Werror=format)                        # error on wrong printf formats
add_compile_options(-Werror=parentheses)                   # error when using ambiguous syntax
include_directories(${PROJECT_SOURCE_DIR}/include)

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)


add_executable(main_app
        main.cpp
        src/Processor.cpp
        src/Loader.cpp
        src/Logger.cpp)

Loader.hpp

#pragma once
#include <string>
#include <c-assignment/Processor.hpp>

using namespace std;
class Loader
{
private:
  Processor *Processor_obj; // creating an object out of the Processor class
  std::thread t1;
  Processor boo;


public:
    Loader();
    ~Loader();
    void thr(int time);
    string usr_input;
    void read_usr_input(void);
};

Processor.hpp

#pragma once
#include <string>
#include <thread>

using namespace std;

class Processor
{
public:

    bool status;       //status of processing true = free, false = busy
    float wait_amount; //variable to store the random generated float
    Processor();
    void process(string);
};

Loader.cpp

#include <c-assignment/Loader.hpp>
#include <c-assignment/Logger.hpp>
#include <c-assignment/Processor.hpp>
#include <iostream>
#include <thread>

Loader::Loader()
{
  Processor_obj = new Processor(); // creating an object out of the Processor class
}
Loader::~Loader()
{
  t1.join();
}
void Loader::read_usr_input(void)
{

  std::cout << "Please enter a command" << '\n';
  std::cin >> Loader::usr_input;
  if (Processor_obj->status == true) //check if the Processor is busy or not
  {
    if (Loader::usr_input == "fc" || Loader::usr_input == "out")
    {
      //Processor_obj->process(Loader::usr_input);
      Loader::t1 = std::thread(&Processor::process,Loader::boo,Loader::usr_input);
    }
    //else if (){}
    //else if (){}
    else
    {
    std::cout << "Unknown command" << '\n';
    }
    std::cout << '\n' << "you entered the command" << Loader::usr_input << '\n';
  }
  else {std::cout << "Processor class is busy" << '\n';}
}

Processor.cpp

#include <c-assignment/Processor.hpp>
#include <c-assignment/Logger.hpp>
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
#include <random>
#include <ctime>
using namespace std;

Processor::Processor()
{
  Processor::status = true;
}
void Processor::process(string usr_input)
{
  srand(time(NULL));
  Processor::wait_amount = ((float)rand() / RAND_MAX) * (3.00f - 1.00f) + 1.00f;
  std::cout << "waiting time is" << (Processor::wait_amount)*1000 << "milliseconds" << '\n';
  Processor::status = false;
  std::this_thread::sleep_for(std::chrono::milliseconds((int)(Processor::wait_amount)*1000));
  Processor::status = true;
  std::cout << "/Processed/" << '\n';
}

main.cpp

#include <c-assignment/Processor.hpp>
#include <c-assignment/Loader.hpp>
#include <c-assignment/Logger.hpp>

int main()
{

    while (true) {
        Processor a;
        Loader b;
        Logger c;
        //a.process("rfc");
        b.read_usr_input();

    }
    return 0;
}

And this is the output when I run make:

    [ 20%] Linking CXX executable main_app
CMakeFiles/main_app.dir/src/Loader.cpp.o: In function `std::thread::thread<void (Processor::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), Processor&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>(void (Processor::*&&)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), Processor&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)':
Loader.cpp:(.text._ZNSt6threadC2IM9ProcessorFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEJRS1_RS7_EEEOT_DpOT0_[_ZNSt6threadC5IM9ProcessorFvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEJRS1_RS7_EEEOT_DpOT0_]+0xb4): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
CMakeFiles/main_app.dir/build.make:172: recipe for target 'main_app' failed
make[2]: *** [main_app] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/main_app.dir/all' failed
make[1]: *** [CMakeFiles/main_app.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
Kevin
  • 16,549
  • 8
  • 60
  • 74
sh_aldeen
  • 23
  • 1
  • 6

1 Answers1

1

The important section of your make output is the linker error: undefined reference to 'pthread_create'. This indicates that the linker cannot find the definition for this pthread function. You have not linked the pthread libraries in your CMake, so you should try doing that to fix your error. After your CMake call to add_executable(), add the line:

target_link_libraries(main_app PRIVATE Threads::Threads)

This assumes that your call to find_package(Threads REQUIRED) correctly found the pthread libraries and populated the imported target Threads::Threads. If that doesn't work, you can also try linking directly to the pthread library instead with the following:

target_link_libraries(main_app PRIVATE pthread)
Kevin
  • 16,549
  • 8
  • 60
  • 74
  • Thank you very much that really solved the issue. I am facing another problem that I don't know where to put the t1.join(); where it should be some where because I am running the program infinitly. if run once and then give me "terminate called without an active exception" if you have any clue please help – sh_aldeen Oct 31 '19 at 03:06