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
The "hard" way: manually build everything from scratch, using g++
directly without a build system
I 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.
1. Build all of gtest and gmock as static library archive *.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
2. Build and run some of the samples which come with googletest
See these sample tests here: https://github.com/google/googletest/tree/main/googletest/samples.
- For
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 \
)
- For
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
Notes
- Q: Why is the include dir
-I"googletest/googletest"
required when building the googletest library?
- A: Because
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"
.
- You can test C code with gtest too, using the
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!
Other references:
- my own answer where I figured out the
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?