从各种构建系统中使用 GoogleTest

GoogleTest 附带 pkg-config 文件,可用于确定编译和链接到 GoogleTest(和 GoogleMock)所需的所有标志。 Pkg-config 是一种标准化的纯文本格式,包含

所有当前的构建系统都以某种方式支持 pkg-config。 对于此处的全部示例,我们假定您想编译示例 samples/sample3_unittest.cc

CMake

在 CMake 中使用 pkg-config 非常容易

find_package(PkgConfig)
pkg_search_module(GTEST REQUIRED gtest_main)

add_executable(testapp)
target_sources(testapp PRIVATE samples/sample3_unittest.cc)
target_link_libraries(testapp PRIVATE ${GTEST_LDFLAGS})
target_compile_options(testapp PRIVATE ${GTEST_CFLAGS})

enable_testing()
add_test(first_and_only_test testapp)

通常建议您使用 target_compile_options + _CFLAGS 而不是 target_include_directories + _INCLUDE_DIRS,因为前者不仅包含 -I 标志(GoogleTest 可能需要一个宏来指示内部头文件,表明所有库都已启用线程进行编译。此外,GoogleTest 可能还需要在编译步骤中使用 -pthread,因此将 pkg-config Cflags 变量拆分为 include 目录和宏以用于 target_compile_definitions() 可能仍然会遗漏此标志)。 同样的建议也适用于使用 _LDFLAGS 而不是更常见的 _LIBRARIES,后者会丢弃 -L 标志和 -pthread

救命!pkg-config 找不到 GoogleTest!

假设您有一个类似于本教程中的 CMakeLists.txt,并且您尝试运行 cmake。 您很可能会遇到类似于以下的失败

-- Checking for one of the modules 'gtest_main'
CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:640 (message):
  None of the required 'gtest_main' found

如果您自己安装了 GoogleTest,并且没有从发行版或其他软件包管理器中获取它,则这些故障很常见。 如果是这样,您需要告诉 pkg-config 在哪里可以找到包含信息的 .pc 文件。 假设您将 GoogleTest 安装到 /usr/local,那么 .pc 文件可能会安装在 /usr/local/lib64/pkgconfig 下。 如果您设置了

export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig

pkg-config 还会尝试在 PKG_CONFIG_PATH 中查找 gtest_main.pc

在交叉编译设置中使用 pkg-config

Pkg-config 也可以用于交叉编译设置。 为此,让我们假设交叉编译安装的最终前缀将是 /usr,并且您的 sysroot 是 /home/MYUSER/sysroot。 使用以下命令配置并安装 GTest

mkdir build && cmake -DCMAKE_INSTALL_PREFIX=/usr ..

使用 DESTDIR 安装到 sysroot 中

make -j install DESTDIR=/home/MYUSER/sysroot

在我们继续之前,建议在交叉编译设置中始终为 pkg-config 定义以下两个变量

export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=yes
export PKG_CONFIG_ALLOW_SYSTEM_LIBS=yes

否则,pkg-config 将根据标准前缀(例如 /usr)过滤 -I-L 标志(有关为什么通常需要进行此剥离的原因,请参阅 https://bugs.freedesktop.org/show_bug.cgi?id=28264#c3)。

如果您查看生成的 pkg-config 文件,它看起来像

libdir=/usr/lib64
includedir=/usr/include

Name: gtest
Description: GoogleTest (without main() function)
Version: 1.11.0
URL: https://github.com/google/googletest
Libs: -L${libdir} -lgtest -lpthread
Cflags: -I${includedir} -DGTEST_HAS_PTHREAD=1 -lpthread

请注意,sysroot 未包含在 libdirincludedir 中! 如果您尝试使用正确的 PKG_CONFIG_LIBDIR=/home/MYUSER/sysroot/usr/lib64/pkgconfig 对此 .pc 文件运行 pkg-config,您将得到

$ pkg-config --cflags gtest
-DGTEST_HAS_PTHREAD=1 -lpthread -I/usr/include
$ pkg-config --libs gtest
-L/usr/lib64 -lgtest -lpthread

这显然是错误的,并指向 CBUILD 而不是 CHOST 根。 为了在交叉编译设置中使用它,我们需要告诉 pkg-config 将实际的 sysroot 注入到 -I-L 变量中。 现在让我们告诉 pkg-config 关于实际的 sysroot

export PKG_CONFIG_DIR=
export PKG_CONFIG_SYSROOT_DIR=/home/MYUSER/sysroot
export PKG_CONFIG_LIBDIR=${PKG_CONFIG_SYSROOT_DIR}/usr/lib64/pkgconfig

再次运行 pkg-config,我们得到

$ pkg-config --cflags gtest
-DGTEST_HAS_PTHREAD=1 -lpthread -I/home/MYUSER/sysroot/usr/include
$ pkg-config --libs gtest
-L/home/MYUSER/sysroot/usr/lib64 -lgtest -lpthread

现在包含正确的 sysroot。 有关在构建系统调用中也包括 ${CHOST} 的更全面指南,请参阅 Diego Elio Pettenò 的优秀教程:https://autotools.io/pkgconfig/cross-compiling.html