user3676804
user3676804

Reputation: 31

CMake - Undefined Reference

I am trying to include gtest to my project.

The problem is that I get a undefined reference error in the GTest.

I am trying to test the Node class in Gtest. Inside the constructor of the Node I am using the Class Logger. Although I have added the library logger to the gtest-target I still the undefined reference error regarding to the Logger....

My guess CMake does no look for nested classes that are used inside Node. only Node itself.

Temperoy fix If I use the Logger in the gtest-node.cpp it works gtest.cpp

/* Pseudo Code */
TEST Node
{ 
     Logger::log("Temp Fix")
     Node * n = Node(0,0,0)
}

This way the the Logger is directly used in the gtest this way the logger-library will be add to the target by cmake.

My Setup (pseudo-code because my project is way bigger than this) (https://github.com/ronsalm/LearningLunch)

├── CMakeLists.txt
├── main.cpp
├── logger
│   ├── CMakeLists.txt
│   ├── logger.cpp
│   └── logger.h
├── Node
│   ├── CMakeLists.txt
│   ├── node.cpp
│   └── node.h
└── Gtest
    ├── CMakeLists.txt
    ├── gtest-node.cpp
    └── node.h

main.cpp

/* Pseudo Code */
int main()
{ 
     Node * n = Node(0,0,0)
}

logger.h

/* Pseudo Code */
class Logger
{ 
     log(string)
}

logger.cpp

/* Pseudo Code */
Logger::log(string s)
{
//write to string to file
}

node.h

/* Pseudo Code */
class Node
{ 
     Node(int,int,int)
}

node.cpp

/* Pseudo Code */
Node::node(int x, int y , int z)
{
     Logger::log("Create Node")
}

gtest.cpp

/* Pseudo Code */
TEST Node
{ 
     Node * n = Node(0,0,0)
}

CMakeLists.txt (Root)

project(applic)
include_directories(
      "${CMAKE_SOURE_DIR/node"
      "${CMAKE_SOURE_DIR/logger")

add_library(node node.cpp)
add_executable(applic main.cpp)
target_link_libraries(applic logger node)

CMakeLists.txt (Logger)

add_library(logger logger.cpp)

CMakeLists.txt (Node)

add_library(node node.cpp)

CMakeLists.txt (Gtest)

add_executable(gtest-node gtest-node.cpp)
set_target_properties(gtest-node PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
target_link_libraries(gtest-logger gtest phtread logger node)
add_test(NAME node COMMAND $<TARGET_FILE:gtest-node>

enable_testing()

The original error:

../../../../lib/libdatabase.a(sql.cpp.o): In function `SQL::Open()':
/home/rsalm/test/src/database/sql/sql.cpp:19: undefined reference to `Logger::TagDebug'
/home/rsalm/test/src/database/sql/sql.cpp:19: undefined reference to `Logger::instance(std::string const&)                                               '
../../../../lib/libdatabase.a(sql.cpp.o): In function `SQL::Close()':
/home/rsalm/test/src/database/sql/sql.cpp:27: undefined reference to `Logger::TagDebug'
/home/rsalm/test/src/database/sql/sql.cpp:27: undefined reference to `Logger::instance(std::string const&)                                               '
../../../../lib/libdatabase.a(sql.cpp.o): In function `Logger& operator<< <char [25]>(Logger&, char const (&) [25])                                               ':
/home/rsalm/test/inc/logger.h:33: undefined reference to `Logger::pInstance'
../../../../lib/libdatabase.a(sql.cpp.o): In function `Logger& operator<< <char [21]>(Logger&, char const (&) [21])                                               ':
/home/rsalm/test/inc/logger.h:33: undefined reference to `Logger::pInstance'
../../../../lib/libdatabase.a(sql.cpp.o): In function `Logger& operator<< <char [26]>(Logger&, char const (&) [26])                                               ':
/home/rsalm/test/inc/logger.h:33: undefined reference to `Logger::pInstance'
../../../../lib/libdatabase.a(sql.cpp.o): In function `Logger& operator<< <char [24]>(Logger&, char const (&) [24])                                               ':
/home/rsalm/test/inc/logger.h:33: undefined reference to `Logger::pInstance'
collect2: error: ld returned 1 exit status
src/layout/gtest/CMakeFiles/gtest-layout-factory.dir/build.make:98: recipe for target '../bin/gtest-layout-factory'                                                failed
make[2]: *** [../bin/gtest-layout-factory] Error 1
CMakeFiles/Makefile2:1824: recipe for target 'src/layout/gtest/CMakeFiles/gtest-layout-factory.dir/all' failed

Upvotes: 2

Views: 5372

Answers (1)

Craig Scott
Craig Scott

Reputation: 10137

Your node library uses the logger library, but you haven't specified that link relationship. You need to add the following:

target_link_library(node PRIVATE logger)

Then, any time you link to node, CMake will append logger to the link libraries if node is built as a static library.

You almost get away with what you did with the linking of the gtest-logger target where you explicitly added the logger library there, assuming you actually meant gtest-node rather than gtest-logger in that call to target_link_library(). If you had listed logger after node, I would have expected the build to work (assuming the target name typo), but that would not be the correct way to do it. You should only need to explicitly list logger as a link dependency of gtest-logger if something in gtest.cpp directly referenced something from the Logger class.

Upvotes: 4

Related Questions