我是 Cmake 和 Gtest 的新手。我在 CMake 中有问题
find_package(GMock REQUIRED)
Run Code Online (Sandbox Code Playgroud)
和
target_link_libraries(runtest ${GMOCK_BOTH_LIBRARIES} pthread).
Run Code Online (Sandbox Code Playgroud)
当我构建项目时,CMake 找不到 GMock 包。
但是当我提到库的绝对路径时,它工作正常。
例如:
set(GMOCK_INCLUDE_DIRS /usr/local/include/gmock)
set(GMOCK_BOTH_LIBRARIES /usr/local/lib/libgmock.a /usr/local/lib/libgmock_main.a /usr/local/lib/libgtest.a /usr/local/lib/libgtest_main.a)
Run Code Online (Sandbox Code Playgroud)
现在的问题是我的主管建议我找到仅使用查找包来运行代码的解决方案。在做了一些研究之后,我才知道FindGMock.cmakeCmake 模块中缺少该文件。我添加了它并使用 再次运行代码find_package(),但它仍然无法正常工作。
错误是对 Gmock 和 Gtest 功能的未定义引用。
例如 :
undefined reference to `testing::Message::Message()'.
undefined reference to testing::internal::GetBoolAssertionFailureMessage.
undefined reference totesting::internal::AssertHelper::~AssertHelper()'
Run Code Online (Sandbox Code Playgroud)
这样的错误太多了。
谁能解释一下,如何让 CMake 自动找到 GMock 包?
以下是从 Linux 上的 CMake 项目从头开始构建并链接到 GMock 的分步示例。步骤 0-4 涵盖了构建和安装 GMock,而步骤 5 及后续步骤则解决了这个问题。
这些步骤相当通用,对于任何提供自己的 CMake 包的项目来说,只需进行很少的修改即可工作。
在我的主文件夹中,我创建了一个名为的空白目录test:
alex:~$ mkdir test
alex:~$ cd test
alex:~/test$ ls
Run Code Online (Sandbox Code Playgroud)
GMock 包含在Google 测试存储库中,因此我们克隆该存储库。
alex:~/test$ git clone https://github.com/google/googletest
Cloning into 'googletest'...
remote: Enumerating objects: 24427, done.
remote: Counting objects: 100% (92/92), done.
remote: Compressing objects: 100% (45/45), done.
remote: Total 24427 (delta 44), reused 72 (delta 38), pack-reused 24335
Receiving objects: 100% (24427/24427), 10.32 MiB | 2.68 MiB/s, done.
Resolving deltas: 100% (18062/18062), done.
Run Code Online (Sandbox Code Playgroud)
我们将使用以下命令来构建googletest存储库;默认情况下包含 GMock。
$ cmake -S googletest/ -B _build/googletest -DCMAKE_BUILD_TYPE=RelWithDebInfo
Run Code Online (Sandbox Code Playgroud)
该-S标志将源目录设置为我们刚刚克隆的 Google 测试存储库的根目录。这告诉 CMake 它正在构建哪个项目。该-B标志将二进制目录设置为~/test/_build/googletest,这是 CMake 在安装之前存储中间构建输出的位置。这应该始终与源目录不同。最后,由于我们使用的是单配置生成器(Make 是 Linux 上的默认生成器),因此此时我们必须指定构建类型。我选择RelWithDebInfo保持调试简单,同时也启用优化。
一般来说,您应该始终使用与其依赖项相同的配置来构建项目,因此我们RelWithDebInfo稍后将再次使用。
有关如何配置通用 CMake 项目的更多详细信息,我将向您推荐此问题/答案:如何构建 CMake 项目?
最后,这是运行命令的输出:
alex:~/test$ cmake -S googletest/ -B _build/googletest -DCMAKE_BUILD_TYPE=RelWithDebInfo
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Python: /usr/bin/python3.10 (found version "3.10.4") found components: Interpreter
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/googletest
Run Code Online (Sandbox Code Playgroud)
现在我们将继续运行构建。以下命令适用于任何单配置生成器:
alex:~/test$ cmake --build _build/googletest/
[ 12%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 25%] Linking CXX static library ../lib/libgtest.a
[ 25%] Built target gtest
[ 37%] Building CXX object googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o
[ 50%] Linking CXX static library ../lib/libgmock.a
[ 50%] Built target gmock
[ 62%] Building CXX object googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.o
[ 75%] Linking CXX static library ../lib/libgmock_main.a
[ 75%] Built target gmock_main
[ 87%] Building CXX object googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
[100%] Linking CXX static library ../lib/libgtest_main.a
[100%] Built target gtest_main
Run Code Online (Sandbox Code Playgroud)
构建应该相对较快地完成。
此时,您可以运行sudo cmake --install _build/googletest/将其全局安装到/usr/local,但我不推荐这样做。最好将经常更新的依赖项(例如 Google Test/GMock)与使用它的项目关联起来。
相反,我们将其安装到项目本地前缀,如下所示:
alex:~/test$ cmake --install _build/googletest/ --prefix _local
-- Install configuration: "RelWithDebInfo"
-- Installing: /home/alex/test/_local/include
-- Installing: /home/alex/test/_local/include/gmock
-- Installing: /home/alex/test/_local/include/gmock/gmock-matchers.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-function-mocker.h
-- Installing: /home/alex/test/_local/include/gmock/internal
-- Installing: /home/alex/test/_local/include/gmock/internal/gmock-pp.h
-- Installing: /home/alex/test/_local/include/gmock/internal/gmock-internal-utils.h
-- Installing: /home/alex/test/_local/include/gmock/internal/gmock-port.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/gmock-port.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/gmock-matchers.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/gmock-generated-actions.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/README.md
-- Installing: /home/alex/test/_local/include/gmock/gmock-more-actions.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-more-matchers.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-nice-strict.h
-- Installing: /home/alex/test/_local/include/gmock/gmock.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-cardinalities.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-spec-builders.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-actions.h
-- Installing: /home/alex/test/_local/lib/libgmock.a
-- Installing: /home/alex/test/_local/lib/libgmock_main.a
-- Installing: /home/alex/test/_local/lib/pkgconfig/gmock.pc
-- Installing: /home/alex/test/_local/lib/pkgconfig/gmock_main.pc
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets-relwithdebinfo.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfigVersion.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfig.cmake
-- Up-to-date: /home/alex/test/_local/include
-- Installing: /home/alex/test/_local/include/gtest
-- Installing: /home/alex/test/_local/include/gtest/gtest-param-test.h
-- Installing: /home/alex/test/_local/include/gtest/internal
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-port-arch.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-string.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-death-test-internal.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-type-util.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-port.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-internal.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-param-util.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-filepath.h
-- Installing: /home/alex/test/_local/include/gtest/internal/custom
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/README.md
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/gtest.h
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/gtest-port.h
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/gtest-printers.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-matchers.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-death-test.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-spi.h
-- Installing: /home/alex/test/_local/include/gtest/gtest.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-test-part.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-typed-test.h
-- Installing: /home/alex/test/_local/include/gtest/gtest_prod.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-assertion-result.h
-- Installing: /home/alex/test/_local/include/gtest/gtest_pred_impl.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-message.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-printers.h
-- Installing: /home/alex/test/_local/lib/libgtest.a
-- Installing: /home/alex/test/_local/lib/libgtest_main.a
-- Installing: /home/alex/test/_local/lib/pkgconfig/gtest.pc
-- Installing: /home/alex/test/_local/lib/pkgconfig/gtest_main.pc
Run Code Online (Sandbox Code Playgroud)
该--prefix标志告诉cmake --install将项目安装到哪个目录。在这里,我们选择了一个_local在我们的工作目录中命名的目录。该文件夹的名称是任意的。我选择这个名称是为了反映/usr/local前缀命名,并很好地利用.gitignore忽略带有前缀和下划线的顶级目录的常见策略。
注意命令输出中正在安装的内容。标头、GTest 和 GMock 静态库,是的,还有 pkg-config 文件,最重要的是 CMake 包文件:
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets-relwithdebinfo.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfigVersion.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfig.cmake
Run Code Online (Sandbox Code Playgroud)
这些文件find_package(很快)将用于将 GTest 加载到依赖项目中。这两个标准文件是GTestConfig.cmake和GTestConfigVersion.cmake。第一个是最重要的,它负责实际实现 CMake 包。它最终将加载GTestTargets.cmake和GTestTargets-relwithdebinfo.cmake,这是特定于 GTest 的。另请注意RelWithDebInfo生成的文件名中如何再次出现;这是因为特定于配置的信息存储在那里。如果您想支持多个配置,则需要使用新的配置重做步骤 2-4 CMAKE_BUILD_TYPE(例如Debug, Release, MinSizeRel)
现在让我们创建一个使用 GMock 的简单示例项目。首先,我们将为它创建一个目录:
alex:~/test$ mkdir example
Run Code Online (Sandbox Code Playgroud)
现在我们将进入并创建一些文件:
alex:~/test$ cd example/
alex:~/test/example$ touch CMakeLists.txt main.cpp
Run Code Online (Sandbox Code Playgroud)
使用您最喜欢的文本编辑器,将以下内容添加到main.cpp:
#include <gmock/gmock.h>
using namespace testing;
struct Example : public Test {};
TEST_F(Example, AlwaysPass) { ASSERT_THAT(0, Eq(0)); }
TEST_F(Example, AlwaysFail) { ASSERT_THAT(0, Eq(1)); }
Run Code Online (Sandbox Code Playgroud)
这是我能想到的 GMock 的基本“hello world”。它有一个测试总是通过,而另一个测试总是失败(这样我们就可以看到各种输出)。
现在我们将在以下位置编写构建脚本CMakeLists.txt:
cmake_minimum_required(VERSION 3.23)
project(example)
find_package(GTest REQUIRED)
add_executable(example main.cpp)
target_link_libraries(example PRIVATE GTest::gmock_main)
Run Code Online (Sandbox Code Playgroud)
再说一遍,这就是尽可能简单的事情。
前两行是必需的样板。它们必须始终按顺序显示为项目的前两行,前面或中间没有任何内容。
第一个命令告诉 CMake要启用cmake_minimum_required哪一组向后兼容策略。它不会将CMake 置于模拟模式或类似模式。您必须使用此处编写的版本来测试您的构建,因为 CMake 不会阻止您使用对于声明的最低版本来说太新的功能。
第二个命令project为您的项目命名并启动 CMake 的编译器检测例程。
接下来,我们通过发出 来告诉 CMake 该项目依赖于该GTest包find_package(GTest REQUIRED)。REQUIRED如果找不到包,该参数将终止配置步骤。该名称GTest源自该GTestConfig.cmake文件。对于任何 CMake 项目XYZ,其主包文件必须命名为XYZConfig.cmake或XYZ-config.cmake。
最后,我们添加测试可执行文件example并将其链接到目标GTest::gmock_main。该目标提供了main除 GMock 标准库之外的功能。如果您想编写自己的main,请链接到GTest::gmock。
1. 除了极少数不值得一提的例外
现在我们终于准备好构建并运行该示例了。让我们回到我们的工作目录:
alex:~/test/example$ cd ..
alex:~/test$
Run Code Online (Sandbox Code Playgroud)
现在我们将继续配置构建:
alex:~/test$ cmake -S example -B _build/example -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=$PWD/_local
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found GTest: /home/alex/test/_local/lib/cmake/GTest/GTestConfig.cmake (found version "1.11.0")
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/example
Run Code Online (Sandbox Code Playgroud)
注意-DCMAKE_PREFIX_PATH=$PWD/_local标志。这告诉 CMake 还有其他库和 CMake 包$PWD/_local,因此find_package其他find_*命令应该在那里查找。如果您没有传递此标志,您可能会看到如下错误:
CMake Error at /usr/share/cmake-3.23/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find GTest (missing: GTEST_LIBRARY GTEST_INCLUDE_DIR
GTEST_MAIN_LIBRARY)
Call Stack (most recent call first):
/usr/share/cmake-3.23/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
/usr/share/cmake-3.23/Modules/FindGTest.cmake:270 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
CMakeLists.txt:4 (find_package)
-- Configuring incomplete, errors occurred!
See also "/home/alex/test/_build/example/CMakeFiles/CMakeOutput.log".
Run Code Online (Sandbox Code Playgroud)
现在我们已经配置完毕,我们可以构建示例:
alex:~/test$ cmake --build _build/example/
[ 50%] Building CXX object CMakeFiles/example.dir/main.cpp.o
[100%] Linking CXX executable example
[100%] Built target example
Run Code Online (Sandbox Code Playgroud)
然后运行它:
alex:~/test$ _build/example/example
Running main() from gmock_main.cc
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from Example
[ RUN ] Example.AlwaysPass
[ OK ] Example.AlwaysPass (0 ms)
[ RUN ] Example.AlwaysFail
/home/alex/test/example/main.cpp:8: Failure
Value of: 0
Expected: is equal to 1
Actual: 0 (of type int)
[ FAILED ] Example.AlwaysFail (0 ms)
[----------] 2 tests from Example (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
[ FAILED ] 1 test, listed below:
[ FAILED ] Example.AlwaysFail
1 FAILED TEST
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,正如预期的那样,我们的合格测试通过了,而我们的失败测试失败了!
如果我们愿意,我们可以将其与 CTest 集成,以便更轻松地运行多个 GMock 二进制文件。这是新的CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(example)
enable_testing() # ------------------------ ADDED 1
find_package(GTest REQUIRED)
include(GoogleTest) # ------------------------ ADDED 2
add_executable(example main.cpp)
target_link_libraries(example PRIVATE GTest::gmock_main)
gtest_discover_tests(example) # ------------------------ ADDED 3
Run Code Online (Sandbox Code Playgroud)
除了标记的三行之外ADDED,没有任何变化。添加的第一行只是启用 CTest 支持。添加的第二行导入CMake对 Google Test 的本机支持。最后,第三行告诉 CTest 该example可执行文件包含 GTest 测试。
进行这些编辑后,增量构建将自动重新运行 CMake。
alex:~/test$ cmake --build _build/example/
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/example
Consolidate compiler generated dependencies of target example
[ 50%] Linking CXX executable example
[100%] Built target example
Run Code Online (Sandbox Code Playgroud)
现在我们可以在构建目录中使用 CTest 运行程序:
alex:~/test$ ctest --test-dir _build/example/
Internal ctest changing into directory: /home/alex/test/_build/example
Test project /home/alex/test/_build/example
Start 1: Example.AlwaysPass
1/2 Test #1: Example.AlwaysPass ............... Passed 0.00 sec
Start 2: Example.AlwaysFail
2/2 Test #2: Example.AlwaysFail ...............***Failed 0.00 sec
50% tests passed, 1 tests failed out of 2
Total Test time (real) = 0.00 sec
The following tests FAILED:
2 - Example.AlwaysFail (Failed)
Errors while running CTest
Output from these tests are in: /home/alex/test/_build/example/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
Run Code Online (Sandbox Code Playgroud)
再一次,我们可以看到我们的通过测试通过了,而我们的失败测试失败了。万岁!
| 归档时间: |
|
| 查看次数: |
5589 次 |
| 最近记录: |