How to get this cmake / gtest code to build
I have library sources in a lib folder:
calculations.hpp:
#ifndef CALCULATIONS_HPP_
#define CALCULATIONS_HPP_
class calculations {
public:
int square(int n);
};
#endif // CALCULATIONS_HPP_
calculations.cpp:
#include "calculations.hpp"
int calculations::square(int n) {
return n * n;
}
CMakeLists.txt file in this folder:
set(SRC_FILES calculations.cpp)
add_library(Calculations STATIC "${SRC_FILES}")
in 'root' folder:
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 in this root folder:
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})
Also in this root folder is the gtest folder structure. libGoogleTest folder with folders.
I also built the libgtest.a and libgtest_main.a lib files which are in libGoogleTest/googletest folder.
If I run the following commands from the 'root' folder:
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
I don't see any libCalculations.a created anywhere.
How to fix this?
I can build using makefiles like this:
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
But how do I do the equivalent using cmake CMakeLists.txt?
After many hours experimenting I found this CMakeLists.txt file worked:
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})