Tuesday, 3 April 2012

Setting up googletest on Ubuntu

Google's C++ unit testing framework, GoogleTest (or simply gtest), is a pretty nifty tool if you write C++ a lot, and the convenience of having it packaged up in Ubuntu and Debian means that you can install and set it up with just a single command. At least it did until the static binary was removed from the package with this justification. All well and good, but it now means that instead of compiling the library once and linking it to each project, you should add it to your build system and compile it for each project, which should only be once each since the gtest source is unlikely to be changing very often.

Preparation

How you add gtest to your project will depend on your build system, but what will always be the same is the need to have the gtest source on your system. If you want the very latest source, you can get it from the gtest project page, either as a SVN checkout or a zip file. You'll be responsible for keeping it updated yourself, and I don't recommend this as it's too much hassle for a project that is very rarely updated anyway.

The easy way, and thus the Ubuntu way, is to install it from the package archives using
sudo apt-get install libgtest-dev
This will download the source files to /usr/src/gtest and the headers to /usr/include/gtest, and any time the source is updated, it will be downloaded automatically for you.

gtest is build with CMake, and you'll need to install that regardless of what build system you're using for your own project. It's possible you could go through and convert it to your chosen system, but that's time consuming, error prone and generaly a waste of time.

Adding gtest to a CMake-based project

Since gtest is already built with CMake, by far the easiest way to add it to you project while still staying clear of the One-Definition Rule is to use CMake to build the project you want to test. There are three lines that need to be added to your CMakeLists.txt files:
add_subdirectory( /usr/src/gtest ${PROJECT_BUILD_OUTPUT}/gtest )
include_directories( "/usr/include/gtest" )
target_link_libraries( test_executable ${TEST_SOURCES} gtest gtest_main pthread )
Using the add_subdirectory command will ensure that any changes to the gtest sources will automatically be detected and build which, when combined with the use of the Ubuntu package manager, means you should only ever have to configure the building of your tests once.

gtest and gtest_main are the two binaries produced by the gtest build which will be placed in ${PROJECT_BUILD_OUTPUT}/gtest. You don't need to specify the path to these when you link - as long as you've typed their names correctly in the link line, they'll be found automatically.

gtest has a dependency on pthread. Just link to it and don't ask questions.

Where these lines go depends entirely on how you've structured your project. For me, I added the first line to my root build file and the other two went into a file I was using to build my tests, which I build into a separate binary. At no point did I have to do anything to the build files for my project sources.

Adding gtest to a GNU Make project

Coming soon.

Adding gtest to a QMake project

Coming soon.

Build gtest to /usr/lib and be done (not recommended for the above reason)

These steps are provided here for completeness - I don't know what you're trying to acheive with you project so I'll offer all the options I know of and let you decide for yourself. This path will build the gtest library to /usr/lib and leave it there, reinstating the problem that not distributing the binary originally solved, so use it at your own risk.

1. Created a temp directory to hold the build data so you're not polluting /usr/src, and build the library using CMake
cd $(mktemp -d)
cmake /usr/src/gtest
make
2. Two static libraries (*.a files) will be build. Move these into the system library directory
sudo mv libgtest.a /usr/lib/
sudo mv libgtest_main.a /usr/lib
3.. Rejoice, and run your tests.