Mo...
Mo...

Reputation: 1961

How to link gtest with CMake?

I'm trying to create a minimal example of gtest with CMake, but I'm not sure how I have to link the test.

I have read the README of the gtest. But, instead of creating CMakeLists.txt.in, I'd like to learn how to manually add the gtest to my project that uses CMake.

Problem

Error Message

Scanning dependencies of target tests
[ 25%] Building CXX object CMakeFiles/tests.dir/tests/main_test.cc.o
/Users/kkweon/temp/gtest_tutorial/tests/main_test.cc:5:1: warning: treating Unicode character as whitespace [-Wunicode-whitespace]
  ::testing::InitGoogleTest(&argc, argv);
^
/Users/kkweon/temp/gtest_tutorial/tests/main_test.cc:5:3: warning: treating Unicode character as whitespace [-Wunicode-whitespace]
  ::testing::InitGoogleTest(&argc, argv);
 ^
/Users/kkweon/temp/gtest_tutorial/tests/main_test.cc:6:1: warning: treating Unicode character as whitespace [-Wunicode-whitespace]
  return RUN_ALL_TESTS();
^
/Users/kkweon/temp/gtest_tutorial/tests/main_test.cc:6:3: warning: treating Unicode character as whitespace [-Wunicode-whitespace]
  return RUN_ALL_TESTS();
 ^
4 warnings generated.
[ 50%] Building CXX object CMakeFiles/tests.dir/tests/add_test.cc.o
[ 75%] Building CXX object CMakeFiles/tests.dir/src/add.cc.o
[100%] Linking CXX executable tests
Undefined symbols for architecture x86_64:
  "testing::InitGoogleTest(int*, char**)", referenced from:
      _main in main_test.cc.o
  "testing::Test::SetUp()", referenced from:
      vtable for AddTest_AddIntegers_Test in add_test.cc.o
  "testing::Test::TearDown()", referenced from:
      vtable for AddTest_AddIntegers_Test in add_test.cc.o
  "testing::Test::Test()", referenced from:
      AddTest_AddIntegers_Test::AddTest_AddIntegers_Test() in add_test.cc.o
  "testing::Test::~Test()", referenced from:
      AddTest_AddIntegers_Test::~AddTest_AddIntegers_Test() in add_test.cc.o
  "testing::Message::Message()", referenced from:
      AddTest_AddIntegers_Test::TestBody() in add_test.cc.o
  "testing::UnitTest::GetInstance()", referenced from:
      RUN_ALL_TESTS() in main_test.cc.o
  "testing::UnitTest::Run()", referenced from:
      RUN_ALL_TESTS() in main_test.cc.o
  "testing::internal::AssertHelper::AssertHelper(testing::TestPartResult::Type, char const*, int, char const*)", referenced from:
      AddTest_AddIntegers_Test::TestBody() in add_test.cc.o
  "testing::internal::AssertHelper::~AssertHelper()", referenced from:
      AddTest_AddIntegers_Test::TestBody() in add_test.cc.o
  "testing::internal::GetTestTypeId()", referenced from:
      ___cxx_global_var_init in add_test.cc.o
  "testing::internal::MakeAndRegisterTestInfo(char const*, char const*, char const*, char const*, testing::internal::CodeLocation, void const*, void (*)(), void (*)(), testing::internal::TestFactoryBase*)", referenced from:
      ___cxx_global_var_init in add_test.cc.o
  "testing::internal::GetBoolAssertionFailureMessage(testing::AssertionResult const&, char const*, char const*, char const*)", referenced from:
      AddTest_AddIntegers_Test::TestBody() in add_test.cc.o
  "testing::internal::IsTrue(bool)", referenced from:
      testing::internal::scoped_ptr<std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::reset(std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) in add_test.cc.o
      testing::internal::scoped_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::reset(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) in add_test.cc.o
  "testing::internal::AssertHelper::operator=(testing::Message const&) const", referenced from:
      AddTest_AddIntegers_Test::TestBody() in add_test.cc.o
  "typeinfo for testing::Test", referenced from:
      typeinfo for AddTest_AddIntegers_Test in add_test.cc.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [tests] Error 1
make[2]: *** [CMakeFiles/tests.dir/all] Error 2
make[1]: *** [CMakeFiles/tests.dir/rule] Error 2
make: *** [tests] Error 2

Information

I have downloaded the googletest repository to /Users/kkweon/github/googletest

and "gtest.h" is located in /Users/kkweon/github/googletest/googletest/include/gtest/gtest.h

My project structure:

.
├── CMakeLists.txt
├── src
│   ├── add.cc
│   ├── add.h
│   └── main.cc
└── tests
    ├── add_test.cc
    └── main_test.cc

and CMakeLists.txt file

cmake_minimum_required(VERSION 3.0)

set(EXTRA_BINCFLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${EXTRA_BINCFLAGS})

include_directories(/Users/kkweon/github/googletest/googletest/include)
include_directories(src)

set(SOURCES src/add.cc)
set(TEST_SOURCES tests/main_test.cc tests/add_test.cc)

add_executable(main src/main.cc ${SOURCES})
add_executable(tests ${TEST_SOURCES} ${SOURCES})

Entire Sourcecode: github

Thank you in advance!

Upvotes: 6

Views: 12124

Answers (1)

Stanislav Pankevich
Stanislav Pankevich

Reputation: 11368

It is not enough to just include_directories with googletest. You have to also add its sources to be compiled.

This is what we do:

We create a separate CMake target google-test compile it as a library. We include googletest folder to our source tree so that our project and Google Test stay together.

In your main CMakeLists you do add_subdirectory(googletest)

googletest folder has its own CMakeLists.txt file and include/ and src/ folders (no need to store full googletest repo!).

tree googletest/

googletest/
├── CMakeLists.txt
├── include
│   └── gtest
│       ├── gtest-death-test.h
        ...
└── src
    ├── gtest-all.cc
    ├── gtest.cc
    └── gtest_main.cc
    ...

In your googletest/CMakeLists.txt you do:

set(google_test_include_dirs
  "${CMAKE_CURRENT_SOURCE_DIR}"
  "${CMAKE_CURRENT_SOURCE_DIR}/include")
include_directories(${google_test_include_dirs})
file(GLOB_RECURSE google_test_headers ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
set(google_test_sources src/gtest-all.cc src/gtest_main.cc)
add_library(google-test STATIC ${google_test_sources} ${google_test_headers})

Then for your target with tests you do something like:

add_executable(MyTests ${my_unittests_sources})
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
include_directories("${CMAKE_SOURCE_DIR}/googletest/include")

target_link_libraries(MyTests google-test)

See CMakeLists.txt, googletest/CMakeLists.txt and unittests/CMakeLists.txt in the project I have linked above.

Upvotes: 7

Related Questions