问题
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
回答1:
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.
来源:https://stackoverflow.com/questions/43964691/cmake-undefined-reference