Googletest (gtest) seems to be an immensely popular unit test framework and I'd like to learn how to build it stand-alone on the g++ compiler, simply and easily, so I can test small libraries and one-off files with it.
I've read the official documentation and readmes here:
...but I still can't figure it out.
How can I just build and test with gtest using the gcc/g++ compiler, or the g++-compatible LLVM clang compiler?
I know I can do the following to use cmake, but it doesn't give me the level of granular control I desire, and it still doesn't answer the mystical question of "how do I use these .a static library files when done?".
From: https://github.com/google/googletest/tree/main/googletest#generic-build-instructions
git clone https://github.com/google/googletest.git
cd googletest # Main directory of the cloned repository.
mkdir build # Create a directory to hold the build output.
cd build
time cmake .. # Generate native make build scripts for GoogleTest.
time make # Run those makefiles just autogenerated by cmake above.
You'll now have the following 4 library files built with whatever build settings were pre-specified for you in the cmake files, but I still don't know how to use them:
googletest/build/lib/libgmock.a
googletest/build/lib/libgmock_main.a
googletest/build/lib/libgtest.a
googletest/build/lib/libgtest_main.a
If you're on Windows, you can run Bash and gcc
and g++
build commands inside an MSYS2 terminal. See my full setup and installation instructions here: Installing & setting up MSYS2 from scratch, including adding all 7 profiles to Windows Terminal. git
commands, however, should still be run inside the Git Bash terminal in Windows which comes with Git for Windows.
For Linux, just use your regular Bash-based terminal for everything.
For my brand-new answer 1 year later, see here: The "easy" way: install gtest's headers and .a static library files system-wide into /usr/local/include
and /usr/local/lib
, respectively
g++
directly without a build systemI finally figured it out! The key reference is this one, which has some excellent build command examples I studied to figure it all out: https://ethz-adrl.github.io/ct/ct_core/doc/html/md__home_adrl_code_src_control-toolbox_ct_core_build_test_googletest-src_googletest_README.html
Here are the steps:
Tested on Linux Ubuntu.
I first documented this entire process, and more, in my eRCaGuy_hello_world repo in my main C++ readme file here: cpp/README.md.
*.a
files# Clone the repo
git clone https://github.com/google/googletest.git
# Build all of gtest and gmock as static library archive `*.a` files
time g++ -Wall -Wextra -Werror -O3 -std=c++17 -pthread -c \
-I"googletest/googletest/include" -I"googletest/googletest" \
-I"googletest/googlemock/include" -I"googletest/googlemock" \
googletest/googletest/src/gtest-all.cc \
googletest/googletest/src/gtest_main.cc \
googletest/googlemock/src/gmock-all.cc \
googletest/googlemock/src/gmock_main.cc
# move all of the object files just created to a "bin" dir
mkdir -p bin
mv -t bin gtest-all.o gtest_main.o gmock-all.o gmock_main.o
# Use the `ar` "archive" utility to create the *.a static library archive files
# from the 4 object files above
time ar -rv bin/libgtest.a bin/gtest-all.o
time ar -rv bin/libgtest_main.a bin/gtest_main.o
time ar -rv bin/libgmock.a bin/gmock-all.o
time ar -rv bin/libgmock_main.a bin/gmock_main.o
You now have:
bin/libgtest.a
bin/libgtest_main.a
bin/libgmock.a
bin/libgmock_main.a
See these sample tests here: https://github.com/google/googletest/tree/main/googletest/samples.
googletest/googletest/samples/sample1_unittest.cc
:
time ( \
time g++ -Wall -Wextra -Werror -O3 -std=c++17 -pthread \
-I"googletest/googletest/include" -I"googletest/googlemock/include" \
googletest/googletest/samples/sample1_unittest.cc \
googletest/googletest/samples/sample1.cc \
bin/libgtest.a bin/libgtest_main.a \
-o bin/a \
&& time bin/a \
)
googletest/googletest/samples/sample2_unittest.cc
:
time ( \
time g++ -Wall -Wextra -Werror -O3 -std=c++17 -pthread \
-I"googletest/googletest/include" -I"googletest/googlemock/include" \
googletest/googletest/samples/sample2_unittest.cc \
googletest/googletest/samples/sample2.cc \
bin/libgtest.a bin/libgtest_main.a \
-o bin/a \
&& time bin/a \
)
etc.
Sample build and run command and output of building sample1_unittest.cc
above:
eRCaGuy_hello_world/cpp$ time ( \
> time g++ -Wall -Wextra -Werror -O3 -std=c++17 -pthread \
> -I"googletest/googletest/include" -I"googletest/googlemock/include" \
> googletest/googletest/samples/sample1_unittest.cc \
> googletest/googletest/samples/sample1.cc \
> bin/libgtest.a bin/libgtest_main.a \
> -o bin/a \
> && time bin/a \
> )
real 0m1.787s
user 0m1.375s
sys 0m0.165s
Running main() from googletest/googletest/src/gtest_main.cc
[==========] Running 6 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 3 tests from FactorialTest
[ RUN ] FactorialTest.Negative
[ OK ] FactorialTest.Negative (0 ms)
[ RUN ] FactorialTest.Zero
[ OK ] FactorialTest.Zero (0 ms)
[ RUN ] FactorialTest.Positive
[ OK ] FactorialTest.Positive (0 ms)
[----------] 3 tests from FactorialTest (0 ms total)
[----------] 3 tests from IsPrimeTest
[ RUN ] IsPrimeTest.Negative
[ OK ] IsPrimeTest.Negative (0 ms)
[ RUN ] IsPrimeTest.Trivial
[ OK ] IsPrimeTest.Trivial (0 ms)
[ RUN ] IsPrimeTest.Positive
[ OK ] IsPrimeTest.Positive (0 ms)
[----------] 3 tests from IsPrimeTest (0 ms total)
[----------] Global test environment tear-down
[==========] 6 tests from 2 test suites ran. (0 ms total)
[ PASSED ] 6 tests.
real 0m0.003s
user 0m0.000s
sys 0m0.002s
real 0m1.790s
user 0m1.375s
sys 0m0.166s
-I"googletest/googletest"
required when building the googletest library?
googletest/googletest/src/gtest-all.cc
includes all other source files as src/name_of_file.cc
, here: https://github.com/google/googletest/blob/main/googletest/src/gtest-all.cc#L41-L49. That means that the parent dir which contains the src
dir must be an "include folder". That parent dir is googletest/googletest
, so we mark it as an include dir with -I"googletest/googletest"
.extern "C" { }
trick when including C headers in C++ to prevent name-mangling. You then link to the C-built object *.o
files, while including the non-name-mangled headers in the C++ googletest unit tests.Happy building! Now I/we can finally use gtest easily in our own personal projects!
time
cmd wrapper things to time sub-components of a larger multi-line command, as well as the entire multi-line command: How to run time on multiple commands AND write the time output to file?-l
(lowercase "L") flags in gcc/g++
gtest
) and Google Mock (gmock
) as shared, static .a
libraries, system-wide, on Linux/Unix:
This includes a lot about gcc/g++ libraries, installing libraries, naming .a statically-linked library files, where g++ searches for includes, etc.