Startec
Startec

Reputation: 13206

Undefined reference after using CMAKE to generate a makefile

I can generate my CMake project, but I can't build it.

I have a fairly straightforward project structure:

├── bin                                                                                                                                                                                                                                       
├── build                                                                                                                                                                                                                                     
├── CMakeLists.txt                                                                                                                                                                                                                            
├── include                                                                                                                                                                                                                                   
│   └── project                                                                                                                                                                                                                               
│       ├── base_socket.h                                                                                                                                                                                                                     
│       ├── tcp_client.h                                                                                                                                                                                                                      
│       ├── tcp_server.h                                                                                                                                                                                                                      
│       ├── udp_client.h                                                                                                                                                                                                                      
│       └── udp_server.h                                                                                                                                                                                                                      
├── LICENSE.txt                                                                                                                                                                                                                               
├── README.md                                                                                                                                                                                                                                 
└── src                                                                                                                                                                                                                                       
    └── project                                                                                                                                                                                                                               
        ├── base_socket.cpp                                                                                                                                                                                                                   
        ├── CMakeLists.txt                                                                                                                                                                                                                    
        ├── main.cpp                                                                                                                                                                                                                          
        ├── tcp_client.cpp                                                                                                                                                                                                                    
        ├── tcp_server.cpp                                                                                                                                                                                                                    
        ├── udp_client.cpp                                                                                                                                                                                                                    
        └── udp_server.cpp 

And a fairly straight forward CMakeLists.txt file in the top directory:

# Project initialization                                                                                                                                                                                                                      
cmake_minimum_required(VERSION 2.7.2 FATAL_ERROR)                                                                                                                                                                                             

project("cpp_sockets")                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             

# Add include directory                                                                                                                                                                                                                       
include_directories(include)                                                                                                                                                                                                                  

# Add subdirectories                                                                                                                                                                                                                          
add_subdirectory(src/project)                                                                                                                                                                                                                 

And also a fairly simple one in src/project/CmakeLists.txt:

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)                                                                                                                                                                                   
set(HEADER_DIR ${CMAKE_SOURCE_DIR}/include/project)                                                                                                                                                                                           
set(HEADER_FILES                                                                                                                                                                                                                              
  ${HEADER_DIR}/base_socket.h                                                                                                                                                                                                                 
  ${HEADER_DIR}/tcp_client.h                                                                                                                                                                                                                  
  ${HEADER_DIR}/tcp_server.h                                                                                                                                                                                                                  
  ${HEADER_DIR}/udp_client.h                                                                                                                                                                                                                  
  ${HEADER_DIR}/udp_server.h                                                                                                                                                                                                                  
  )                           

add_executable(cpp_sockets main.cpp ${HEADER_FILES}) 

When I cd into /build and type cmake .. it works fine.

However, when I follow that with make, I get many terrible errors about undefined reference.

main.cpp:(.text+0x2c6): undefined reference to `UDPClient::UDPClient(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'                                                                            
main.cpp:(.text+0x2eb): undefined reference to `UDPClient::send_message(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'                                                                              
main.cpp:(.text+0x359): undefined reference to `UDPServer::UDPServer(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'                                                                            
main.cpp:(.text+0x380): undefined reference to `UDPServer::socket_bind()'                                                                                                                                                                     
main.cpp:(.text+0x38c): undefined reference to `UDPServer::listen()'                                                                                                                                                                          
main.cpp:(.text+0x400): undefined reference to `TCPClient::TCPClient(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'                                                                            
main.cpp:(.text+0x40c): undefined reference to `TCPClient::make_connection()'                                                                                                                                                                 
main.cpp:(.text+0x42b): undefined reference to `TCPClient::send_message(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'                                                                              
main.cpp:(.text+0x492): undefined reference to `TCPServer::TCPServer(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'                                                                            
main.cpp:(.text+0x4b9): undefined reference to `TCPServer::socket_bind()'                                                                                                                                                                     
CMakeFiles/cpp_sockets.dir/main.cpp.o: In function `UDPClient::~UDPClient()':                                                                                                                                                                 
main.cpp:(.text._ZN9UDPClientD2Ev[_ZN9UDPClientD5Ev]+0x14): undefined reference to `Socket::~Socket()'                                                                                                                                        
CMakeFiles/cpp_sockets.dir/main.cpp.o: In function `UDPServer::~UDPServer()':                                                                                                                                                                 
main.cpp:(.text._ZN9UDPServerD2Ev[_ZN9UDPServerD5Ev]+0x14): undefined reference to `Socket::~Socket()'                                                                                                                                        
CMakeFiles/cpp_sockets.dir/main.cpp.o: In function `TCPClient::~TCPClient()':                                                                                                                                                                 
main.cpp:(.text._ZN9TCPClientD2Ev[_ZN9TCPClientD5Ev]+0x14): undefined reference to `Socket::~Socket()'                                                                                                                                        
CMakeFiles/cpp_sockets.dir/main.cpp.o: In function `TCPServer::~TCPServer()':                                                                                                                                                                 
main.cpp:(.text._ZN9TCPServerD2Ev[_ZN9TCPServerD5Ev]+0x14): undefined reference to `Socket::~Socket()'                                                                                                                                        
collect2: error: ld returned 1 exit status                                                                                                                                                                                                    
src/project/CMakeFiles/cpp_sockets.dir/build.make:94: recipe for target '../bin/cpp_sockets' failed                                                                                                                                           
make[2]: *** [../bin/cpp_sockets] Error 1                                                                                                                                                                                                     
CMakeFiles/Makefile2:85: recipe for target 'src/project/CMakeFiles/cpp_sockets.dir/all' failed                                                                                                                                                
make[1]: *** [src/project/CMakeFiles/cpp_sockets.dir/all] Error 2                                                                                                                                                                             
Makefile:83: recipe for target 'all' failed                                                                                                                                                                                                   
make: *** [all] Error 2

main.cpp file looks like:

  #include "project/udp_server.h"                                                                                                                                                                                                            
  #include "project/udp_client.h"                                                                                                                                                                                                            
  #include "project/tcp_client.h"       

Why would the linker not be able to find the references like this?

Upvotes: 2

Views: 1578

Answers (1)

Edward
Edward

Reputation: 6292

It looks like your src/project/CMakeLists.txt neglects to specify the other cpp files, like udp_server.cpp and udp_client.cpp, as dependencies of the executable cpp_sockets. You need to do this in order for CMake to compile those source files; it won't automatically figure out to compile them just because you have included their corresponding headers. In fact, the add_executable declaration doesn't need to say anything about the headers, because the include_directories command takes care of that.

Given the header files that your main.cpp depends on, its add_executable line should look like this:

add_executable(cpp_sockets main.cpp udp_server.cpp udp_client.cpp tcp_client.cpp)

Upvotes: 2

Related Questions