1## Using GoogleTest from various build systems
2
3GoogleTest comes with pkg-config files that can be used to determine all
4necessary flags for compiling and linking to GoogleTest (and GoogleMock).
5Pkg-config is a standardised plain-text format containing
6
7*   the includedir (-I) path
8*   necessary macro (-D) definitions
9*   further required flags (-pthread)
10*   the library (-L) path
11*   the library (-l) to link to
12
13All current build systems support pkg-config in one way or another. For all
14examples here we assume you want to compile the sample
15`samples/sample3_unittest.cc`.
16
17### CMake
18
19Using `pkg-config` in CMake is fairly easy:
20
21```cmake
22cmake_minimum_required(VERSION 3.0)
23
24cmake_policy(SET CMP0048 NEW)
25project(my_gtest_pkgconfig VERSION 0.0.1 LANGUAGES CXX)
26
27find_package(PkgConfig)
28pkg_search_module(GTEST REQUIRED gtest_main)
29
30add_executable(testapp samples/sample3_unittest.cc)
31target_link_libraries(testapp ${GTEST_LDFLAGS})
32target_compile_options(testapp PUBLIC ${GTEST_CFLAGS})
33
34include(CTest)
35add_test(first_and_only_test testapp)
36```
37
38It is generally recommended that you use `target_compile_options` + `_CFLAGS`
39over `target_include_directories` + `_INCLUDE_DIRS` as the former includes not
40just -I flags (GoogleTest might require a macro indicating to internal headers
41that all libraries have been compiled with threading enabled. In addition,
42GoogleTest might also require `-pthread` in the compiling step, and as such
43splitting the pkg-config `Cflags` variable into include dirs and macros for
44`target_compile_definitions()` might still miss this). The same recommendation
45goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which happens
46to discard `-L` flags and `-pthread`.
47
48### Help! pkg-config can't find GoogleTest!
49
50Let's say you have a `CMakeLists.txt` along the lines of the one in this
51tutorial and you try to run `cmake`. It is very possible that you get a failure
52along the lines of:
53
54```
55-- Checking for one of the modules 'gtest_main'
56CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:640 (message):
57  None of the required 'gtest_main' found
58```
59
60These failures are common if you installed GoogleTest yourself and have not
61sourced it from a distro or other package manager. If so, you need to tell
62pkg-config where it can find the `.pc` files containing the information. Say you
63installed GoogleTest to `/usr/local`, then it might be that the `.pc` files are
64installed under `/usr/local/lib64/pkgconfig`. If you set
65
66```
67export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig
68```
69
70pkg-config will also try to look in `PKG_CONFIG_PATH` to find `gtest_main.pc`.
71
72### Using pkg-config in a cross-compilation setting
73
74Pkg-config can be used in a cross-compilation setting too. To do this, let's
75assume the final prefix of the cross-compiled installation will be `/usr`, and
76your sysroot is `/home/MYUSER/sysroot`. Configure and install GTest using
77
78```
79mkdir build && cmake -DCMAKE_INSTALL_PREFIX=/usr ..
80```
81
82Install into the sysroot using `DESTDIR`:
83
84```
85make -j install DESTDIR=/home/MYUSER/sysroot
86```
87
88Before we continue, it is recommended to **always** define the following two
89variables for pkg-config in a cross-compilation setting:
90
91```
92export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=yes
93export PKG_CONFIG_ALLOW_SYSTEM_LIBS=yes
94```
95
96otherwise `pkg-config` will filter `-I` and `-L` flags against standard prefixes
97such as `/usr` (see https://bugs.freedesktop.org/show_bug.cgi?id=28264#c3 for
98reasons why this stripping needs to occur usually).
99
100If you look at the generated pkg-config file, it will look something like
101
102```
103libdir=/usr/lib64
104includedir=/usr/include
105
106Name: gtest
107Description: GoogleTest (without main() function)
108Version: 1.11.0
109URL: https://github.com/google/googletest
110Libs: -L${libdir} -lgtest -lpthread
111Cflags: -I${includedir} -DGTEST_HAS_PTHREAD=1 -lpthread
112```
113
114Notice that the sysroot is not included in `libdir` and `includedir`! If you try
115to run `pkg-config` with the correct
116`PKG_CONFIG_LIBDIR=/home/MYUSER/sysroot/usr/lib64/pkgconfig` against this `.pc`
117file, you will get
118
119```
120$ pkg-config --cflags gtest
121-DGTEST_HAS_PTHREAD=1 -lpthread -I/usr/include
122$ pkg-config --libs gtest
123-L/usr/lib64 -lgtest -lpthread
124```
125
126which is obviously wrong and points to the `CBUILD` and not `CHOST` root. In
127order to use this in a cross-compilation setting, we need to tell pkg-config to
128inject the actual sysroot into `-I` and `-L` variables. Let us now tell
129pkg-config about the actual sysroot
130
131```
132export PKG_CONFIG_DIR=
133export PKG_CONFIG_SYSROOT_DIR=/home/MYUSER/sysroot
134export PKG_CONFIG_LIBDIR=${PKG_CONFIG_SYSROOT_DIR}/usr/lib64/pkgconfig
135```
136
137and running `pkg-config` again we get
138
139```
140$ pkg-config --cflags gtest
141-DGTEST_HAS_PTHREAD=1 -lpthread -I/home/MYUSER/sysroot/usr/include
142$ pkg-config --libs gtest
143-L/home/MYUSER/sysroot/usr/lib64 -lgtest -lpthread
144```
145
146which contains the correct sysroot now. For a more comprehensive guide to also
147including `${CHOST}` in build system calls, see the excellent tutorial by Diego
148Elio Pettenò: <https://autotools.io/pkgconfig/cross-compiling.html>
149