使用cmake构建google测试单元测试时出现链接器错误



如何获取此cmake/gtest代码来构建

我在库文件夹中有库源:

计算.hpp:

#ifndef  CALCULATIONS_HPP_
#define CALCULATIONS_HPP_
class calculations {
public:
int square(int n);
};
#endif // CALCULATIONS_HPP_

计算.cpp:

#include "calculations.hpp"
int calculations::square(int n) {
return n * n;
}

此文件夹中的CMakeLists.txt文件:

set(SRC_FILES calculations.cpp)
add_library(Calculations STATIC "${SRC_FILES}")

在"根"文件夹中:

calculations_unittests.cpp:

#include "calculations.hpp"
#include <gtest/gtest.h>
TEST(CalculationsUnitTests, square_test) {
calculations calc;
ASSERT_EQ(calc.square(2), 4);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

此根文件夹中的CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)
set (CMAKE_CXX_STANDARD 14)
set(GTEST_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libGoogleTest/googletest/include/")
message( "GTEST_INCLUDE_DIR = ${GTEST_INCLUDE_DIR}" )
message( "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}" )
include_directories("${GTEST_INCLUDE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/")
set(GTEST_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/libGoogleTest/googletest/libgtest.a")
set(GTEST_MAIN_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/libGoogleTest/googletest/libgtest_main.a")
message( "GTEST_LIBRARY = ${GTEST_LIBRARY}" )

add_subdirectory(lib)
# Locate GTest
find_package(GTest REQUIRED)
message( "lib = ${Calculations}" )
# Link runTests with what we want to test and the GTest and pthread library
add_executable(runTests calculations_unittests.cpp ${Calculations})

这个根文件夹中还有gtest文件夹结构。带有文件夹的libGoogleTest文件夹。

我还构建了libgtest.a和libgtest_main.a库文件,它们位于libGoogleTest/googletest文件夹中。

如果我从"根"文件夹运行以下命令:

combera@combera-1604_64:~/Documents/scratch/cmake_gtest$ cmake CMakeLists.txt 
GTEST_INCLUDE_DIR = /home/combera/Documents/scratch/cmake_gtest/libGoogleTest/googletest/include/
CMAKE_CURRENT_SOURCE_DIR = /home/combera/Documents/scratch/cmake_gtest
GTEST_LIBRARY = /home/combera/Documents/scratch/cmake_gtest/libGoogleTest/googletest/libgtest.a
lib = 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/combera/Documents/scratch/cmake_gtest
combera@combera-1604_64:~/Documents/scratch/cmake_gtest$ make runTests
[ 50%] Linking CXX executable runTests
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `CalculationsUnitTests_square_test_Test::TestBody()':
calculations_unittests.cpp:(.text+0x30): undefined reference to `calculations::square(int)'
calculations_unittests.cpp:(.text+0x73): undefined reference to `testing::Message::Message()'
calculations_unittests.cpp:(.text+0xa0): undefined reference to `testing::internal::AssertHelper::AssertHelper(testing::TestPartResult::Type, char const*, int, char const*)'
calculations_unittests.cpp:(.text+0xb3): undefined reference to `testing::internal::AssertHelper::operator=(testing::Message const&) const'
calculations_unittests.cpp:(.text+0xbf): undefined reference to `testing::internal::AssertHelper::~AssertHelper()'
calculations_unittests.cpp:(.text+0x107): undefined reference to `testing::internal::AssertHelper::~AssertHelper()'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `main':
calculations_unittests.cpp:(.text+0x164): undefined reference to `testing::InitGoogleTest(int*, char**)'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `__static_initialization_and_destruction_0(int, int)':
calculations_unittests.cpp:(.text+0x1da): undefined reference to `testing::internal::GetTestTypeId()'
calculations_unittests.cpp:(.text+0x248): undefined reference to `testing::internal::MakeAndRegisterTestInfo(char const*, char const*, char const*, char const*, testing::internal::CodeLocation, void const*, void (*)(), void (*)(), testing::internal::TestFactoryBase*)'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `RUN_ALL_TESTS()':
calculations_unittests.cpp:(.text._Z13RUN_ALL_TESTSv[_Z13RUN_ALL_TESTSv]+0x5): undefined reference to `testing::UnitTest::GetInstance()'
calculations_unittests.cpp:(.text._Z13RUN_ALL_TESTSv[_Z13RUN_ALL_TESTSv]+0xd): undefined reference to `testing::UnitTest::Run()'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `CalculationsUnitTests_square_test_Test::CalculationsUnitTests_square_test_Test()':
calculations_unittests.cpp:(.text._ZN38CalculationsUnitTests_square_test_TestC2Ev[_ZN38CalculationsUnitTests_square_test_TestC5Ev]+0x14): undefined reference to `testing::Test::Test()'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `testing::internal::scoped_ptr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::reset(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)':
calculations_unittests.cpp:(.text._ZN7testing8internal10scoped_ptrINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5resetEPS7_[_ZN7testing8internal10scoped_ptrINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5resetEPS7_]+0x29): undefined reference to `testing::internal::IsTrue(bool)'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `testing::internal::scoped_ptr<std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> > >::reset(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >*)':
calculations_unittests.cpp:(.text._ZN7testing8internal10scoped_ptrINSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEEE5resetEPS7_[_ZN7testing8internal10scoped_ptrINSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEEE5resetEPS7_]+0x28): undefined reference to `testing::internal::IsTrue(bool)'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `testing::AssertionResult testing::internal::CmpHelperEQ<int, int>(char const*, char const*, int const&, int const&)':
calculations_unittests.cpp:(.text._ZN7testing8internal11CmpHelperEQIiiEENS_15AssertionResultEPKcS4_RKT_RKT0_[_ZN7testing8internal11CmpHelperEQIiiEENS_15AssertionResultEPKcS4_RKT_RKT0_]+0x43): undefined reference to `testing::AssertionSuccess()'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `testing::AssertionResult testing::internal::CmpHelperEQFailure<int, int>(char const*, char const*, int const&, int const&)':
calculations_unittests.cpp:(.text._ZN7testing8internal18CmpHelperEQFailureIiiEENS_15AssertionResultEPKcS4_RKT_RKT0_[_ZN7testing8internal18CmpHelperEQFailureIiiEENS_15AssertionResultEPKcS4_RKT_RKT0_]+0x87): undefined reference to `testing::internal::EqFailure(char const*, char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o:(.rodata._ZTV38CalculationsUnitTests_square_test_Test[_ZTV38CalculationsUnitTests_square_test_Test]+0x20): undefined reference to `testing::Test::SetUp()'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o:(.rodata._ZTV38CalculationsUnitTests_square_test_Test[_ZTV38CalculationsUnitTests_square_test_Test]+0x28): undefined reference to `testing::Test::TearDown()'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o: In function `CalculationsUnitTests_square_test_Test::~CalculationsUnitTests_square_test_Test()':
calculations_unittests.cpp:(.text._ZN38CalculationsUnitTests_square_test_TestD2Ev[_ZN38CalculationsUnitTests_square_test_TestD5Ev]+0x20): undefined reference to `testing::Test::~Test()'
CMakeFiles/runTests.dir/calculations_unittests.cpp.o:(.rodata._ZTI38CalculationsUnitTests_square_test_Test[_ZTI38CalculationsUnitTests_square_test_Test]+0x10): undefined reference to `typeinfo for testing::Test'
collect2: error: ld returned 1 exit status
CMakeFiles/runTests.dir/build.make:94: recipe for target 'runTests' failed
make[3]: *** [runTests] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/runTests.dir/all' failed
make[2]: *** [CMakeFiles/runTests.dir/all] Error 2
CMakeFiles/Makefile2:79: recipe for target 'CMakeFiles/runTests.dir/rule' failed
make[1]: *** [CMakeFiles/runTests.dir/rule] Error 2
Makefile:118: recipe for target 'runTests' failed
make: *** [runTests] Error 2

我看不到在任何地方创建了任何libCalculations.a。

如何解决此问题?

我可以使用这样的makefile构建:

LIB_DIR=./lib
GOOGLE_TEST_LIB = gtest
GOOGLE_TEST_INCLUDE=./libGoogleTest/googletest/include/
G++ = g++
G++_FLAGS = -c -Wall -I $(GOOGLE_TEST_INCLUDE) -I ./lib
LD_FLAGS = -L ./libGoogleTest/googletest -l $(GOOGLE_TEST_LIB) -l pthread libCalculations.a
OBJECTS = main.o
TARGET = main
all: $(TARGET)
libCalculations.a: libCalculations.a
ar rcs libCalculations.a calculations.o
calculations.o: calculations.hpp calculations.cpp
g++ -o calculations.o $(LIB_DIR)/calculations.cpp
$(TARGET): $(OBJECTS)
g++ -o $(TARGET) $(OBJECTS) $(LD_FLAGS)
%.o : %.cpp
$(G++) $(G++_FLAGS) $<
clean:
rm -f $(TARGET) $(OBJECTS)
.PHONY: all clean

但是,我如何使用cmake CMakeLists.txt进行等效操作呢?

经过几个小时的实验,我发现这个CMakeLists.txt文件有效:

cmake_minimum_required(VERSION 3.5)
project(calcTests)
set (CMAKE_CXX_STANDARD 14)
set(GTEST_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libGoogleTest/googletest/include/")
#message( "GTEST_INCLUDE_DIR = ${GTEST_INCLUDE_DIR}" )
#message( "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}" )
include_directories("${GTEST_INCLUDE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/")
set(GTEST_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/libGoogleTest/googletest/libgtest.a")
set(GTEST_MAIN_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/libGoogleTest/googletest/libgtest_main.a")
message( "GTEST_LIBRARY: ${GTEST_LIBRARY}" )

add_subdirectory(lib)
# it seems that gtest is built with the shared .so pthreads lib
find_library(pthreads NAMES libpthread.so FIND_LIBRARY_USE_LIB64_PATHS)
message( "Using thread lib: ${pthreads}" )
# Locate GTest
find_package(GTest REQUIRED)
set(CMAKE_PREFIX_PATH "./lib")
find_library(Calculations NAMES libCalculations.a "./lib/")
message( "Calculations lib: ${Calculations}" )

add_executable(calcTests calculations_unittests.cpp ${Calculations} ${pthreads})
target_link_libraries(calcTests ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} ${Calculations} ${pthreads})

最新更新