How to start working with GTest and CMake
I have recently been sold on using CMake for compiling my C++ projects, and would now like to start writing some unit tests for my code. I have decided to use the Google Test utility to help with this, but require some help in getting started.
All day I have been reading various guides and examples include the Primer, an introduction at IBM and some questions on SO (here and here) as well as other sources I've lost track of. I realise there's plenty out there but somehow I am still having difficulties.
I'm currently trying to implement the most basic test, to confirm I've compiled/installed gtest right and it's not working. The only source file (testgtest.cpp) is taken almost exactly from this previous answer:
#include <iostream>
#include "gtest/gtest.h"
TEST(sample_test_case, sample_test)
{
EXPECT_EQ(1, 1);
}
and my associated CMakeLists.txt is as follows:
cmake_minimum_required(VERSION 2.6)
project(basic_test)
# Setup testing
enable_testing()
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIR})
# Add test cpp file
add_executable(runUnitTests
testgtest.cpp
)
# Link test executable against gtest & gtest_main
target_link_libraries(runUnitTests ${GTEST_LIBRARY_DEBUG} ${GTEST_MAIN_LIBRARY_DEBUG})
add_test(
NAME runUnitTests
COMMAND runUnitTests
)
Note that I have chosen to link against gtest_main instead of providing the main at the end of the cpp file as I believe this will allow me to scale testing up more easily to multiple files.
When building the generated .sln file (in Visual C++ 2010 Express) I unfortunately get a long list of errors of the form
2>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: virtual __thiscall std::basic_iostream<char,struct std::char_traits<char> >::~basic_iostream<char,struct std::char_traits<char> >(void)" (??1?$basic_iostream@DU?$char_traits@D@std@@@std@@UAE@XZ) already defined in gtestd.lib(gtest-all.obj)
which I think means that I'm not successfully linking to the gtest libraries. I have made sure that when linking against the debug libraries, I have then tried to build in debug mode.
EDIT
Having done some more digging, I think my issue is something to do with the type of library I am building gtest into. When building gtest with CMake, if BUILD_SHARED_LIBS
is un-checked, and I link my program against these .lib files I get the errors mentioned above. However, if BUILD_SHARED_LIBS
is checked then I produce a set of .lib and .dll files. When now linking against these .lib files the program compiles, but when run complains that it can't find gtest.dll.
What are the differences between a SHARED
and a not SHARED
library, and if I choose not shared, why doesn't it work? Is there an option in the CMakeLists.txt for my project that I am missing?
The solution involved putting the gtest source directory as a subdirectory of your project. I've included the working CMakeLists.txt below if it is helpful to anyone.
cmake_minimum_required(VERSION 2.6)
project(basic_test)
################################
# GTest
################################
ADD_SUBDIRECTORY (gtest-1.6.0)
enable_testing()
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
################################
# Unit Tests
################################
# Add test cpp file
add_executable( runUnitTests testgtest.cpp )
# Link test executable against gtest & gtest_main
target_link_libraries(runUnitTests gtest gtest_main)
add_test( runUnitTests runUnitTests )
Here is a complete working example that I just tested. It downloads directly from the web, either a fixed tarball, or the latest subversion directory.
cmake_minimum_required (VERSION 3.1)
project (registerer)
##################################
# Download and install GoogleTest
include(ExternalProject)
ExternalProject_Add(gtest
URL https://googletest.googlecode.com/files/gtest-1.7.0.zip
# Comment above line, and uncomment line below to use subversion.
# SVN_REPOSITORY http://googletest.googlecode.com/svn/trunk/
# Uncomment line below to freeze a revision (here the one for 1.7.0)
# SVN_REVISION -r700
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/gtest
INSTALL_COMMAND ""
)
ExternalProject_Get_Property(gtest source_dir binary_dir)
################
# Define a test
add_executable(registerer_test registerer_test.cc)
######################################
# Configure the test to use GoogleTest
#
# If used often, could be made a macro.
add_dependencies(registerer_test gtest)
include_directories(${source_dir}/include)
target_link_libraries(registerer_test ${binary_dir}/libgtest.a)
target_link_libraries(registerer_test ${binary_dir}/libgtest_main.a)
##################################
# Just make the test runnable with
# $ make test
enable_testing()
add_test(NAME registerer_test
COMMAND registerer_test)
Most likely, the difference in compiler options between your test binary and the Google Test library is to blame on such errors. That's why it's recommended to bring in Google Test in the source form and build it along with your tests. It's very easy to do in CMake. You just invoke ADD_SUBDIRECTORY
with the path to the gtest root and then you can use public library targets ( gtest
and gtest_main
) defined there. There is more background information in this CMake thread in the googletestframework group.
[edit] The BUILD_SHARED_LIBS
option is only effective on Windows for now. It specifies the type of libraries that you want CMake to build. If you set it to ON
, CMake will build them as DLLs as opposed to static libs. In that case you have to build your tests with -DGTEST_LINKED_AS_SHARED_LIBRARY=1 and copy the DLL files produced by the CMake to the directory with your test binary (CMake places them in a separate output directory by default). Unless gtest in static lib doesn't work for you, it's easier not to set that option.
上一篇: CMake和编译器警告
下一篇: 如何开始使用GTest和CMake