目录

1.前言

2.FetchContent详解

2.1.FetchContent简介

2.2.FetchContent_Declare

2.2.1.简介

2.2.2.关键特性

2.2.3.常见示例

2.3.FetchContent_MakeAvailable

2.3.1.简介

2.3.2.核心功能与工作流程

2.3.3.示例用法

2.3.4.关键特性

2.3.5.常见问题与解决方案

3.FetchContent_MakeAvailable和FetchContent_Populate的区别

4.add_test

5.完整示例

5.1.项目结构

5.2.代码实现

5.3.运行项目

5.4.遇到的问题

5.5.完整代码下载

6.优势与适用场景

7.注意事项

8.总结

相关链接


1.前言

        在现代C++项目开发中,单元测试是确保代码质量和可维护性的关键环节。Google Test(GTest)作为一款功能强大、广受欢迎的C++测试框架,提供了丰富的断言、测试夹具和测试发现机制。本文演示如何利用CMake的FetchContent模块,优雅地集成和使用Google Test进行单元测试。不仅会展示具体步骤,还会深入探讨FetchContent的工作原理,帮助更好地理解其在项目管理中的优势。

        前面讲了gTest的安装与配置方法:

gTest测试框架的安装与配置_安装gtest-CSDN博客

这种方法是先安装好gTest,再利用CMake的find_package查找它,然后链接它,其实也比较简单,如有不理解的地方,可参考:

CMake指令:find_package_cmake find package-CSDN博客

下面来讲讲另外一种方法,用FetchContent引入gTest。

2.FetchContent详解

2.1.FetchContent简介

        FetchContent是定义在FetchContent.cmake当中的,FetchContent.cmake 是 CMake 3.11 及以上版本提供的一个内置模块,用于在配置阶段下载、配置和集成外部项目(如第三方库),无需用户手动安装依赖。它解决了传统依赖管理(如手动下载、ExternalProject)的繁琐问题,让外部项目的集成更简洁、高效。

      FetchContent 的核心是在 CMake 配置阶段(执行 cmake 命令时)自动完成以下操作:

  1. 下载外部项目(从 URL、Git 仓库等);
  2. 配置外部项目(生成其构建文件);
  3. 构建外部项目(可选,默认会构建);
  4. 将外部项目的目标(库、可执行文件)暴露给当前项目,方便直接链接使用。

相比传统的 ExternalProject(在构建阶段处理依赖),FetchContent 在配置阶段完成依赖准备,能更早地将外部项目的目标和变量融入当前项目,使用更灵活。

        基本用法:

1) FetchContent_Declare():声明外部项目的信息(名称、下载地址、版本等);

2) FetchContent_MakeAvailable():实际执行下载、配置、构建,并将项目纳入当前构建系统。

2.2.FetchContent_Declare

2.2.1.简介

  FetchContent_Declare 是 CMake 中 FetchContent 模块的核心命令之一,用于声明外部项目的元信息(如下载地址、版本、配置选项等)。它本身不会实际下载或构建项目,只是定义 “如何要获取什么、从哪里获取”,后续通过 FetchContent_MakeAvailable 才会执行实际的下载、配置和构建流程。

        基本语法:

FetchContent_Declare(<项目名称>  # 自定义名称(用于后续引用,如声明为"googletest",后续用该名称操作)[URL <下载地址>]  # 从压缩包下载(.zip/.tar.gz等)[URL_HASH <算法>=<哈希值>]  # 验证下载文件完整性(如SHA256=xxx)[GIT_REPOSITORY <Git仓库地址>]  # 从Git仓库克隆[GIT_TAG <标签/分支/commit哈希>]  # Git仓库的版本标识(必填,否则默认拉取所有历史)[GIT_SHALLOW ON]  # 浅克隆(仅拉取最新版本,加快下载速度)[CMAKE_ARGS <参数1> <参数2> ...]  # 传递给外部项目的CMake配置参数[SOURCE_DIR <本地目录>]  # 强制使用本地源码目录(替代下载)# 其他可选参数(如SVN仓库、本地文件等)
)

核心参数说明:

参数作用适用场景
<项目名称>自定义标识,后续通过该名称引用项目(如 googletestfmt)。所有场景,必须唯一。
URL外部项目压缩包的下载地址(如 .zip.tar.gz)。从静态压缩包获取(版本固定,适合稳定依赖)。
GIT_REPOSITORYGit 仓库地址(如 https://github.com/google/googletest.git)。从 Git 仓库获取(支持灵活选择版本)。
GIT_TAGGit 的版本标识(标签 tag、分支 branch 或 commit 哈希)。与 GIT_REPOSITORY 配合,固定依赖版本。
GIT_SHALLOW设为 ON 时,仅克隆最新版本(不包含完整历史),加快下载。从 Git 仓库获取时推荐使用,节省时间和空间。
URL_HASH验证下载文件的完整性(格式:<算法>=<哈希值>,如 SHA256=xxx)。从 URL 下载时,防止文件损坏或篡改。
SOURCE_DIR 强制使用本地源码目录使用URL下载不了源码的时候,强制使用本地源码目录特别好用
CMAKE_ARGS传递给外部项目的 CMake 配置参数(如 -DBUILD_TESTING=OFF)。需要自定义外部项目构建选项时。

2.2.2.关键特性

  1. 仅声明不执行FetchContent_Declare 只记录项目信息,不会实际下载或构建,需配合 FetchContent_MakeAvailable(<项目名称>) 才会执行后续操作。
  2. 顺序要求:必须在 FetchContent_MakeAvailable 之前声明,否则会报 No content details recorded 错误(如你之前遇到的问题)。
  3. 变量暴露:声明后,CMake 会自动创建 <项目名称>_SOURCE_DIR(源码目录)和 <项目名称>_BINARY_DIR(构建目录)变量,方便后续引用。

2.2.3.常见示例

示例 1:从 Git 仓库获取(推荐)

# 声明 googletest(从Git仓库获取release-1.12.1版本)
FetchContent_Declare(googletest# 外部项目的名称,后续会用到这个名称来引用它。GIT_REPOSITORY https://github.com/google/googletest.git# Git仓库URL。GIT_TAG  release-1.12.1# 指定要下载的Git标签或提交哈希,确保版本一致性。GIT_SHALLOW    ON       #可选:进行浅克隆,减少下载时间。
)

示例 2:从压缩包获取(带完整性验证)

# 声明 fmt 库(从压缩包获取10.2.1版本,带SHA256验证)
FetchContent_Declare(fmtURL           https://github.com/fmtlib/fmt/archive/refs/tags/10.2.1.zip  # 压缩包地址URL_HASH      SHA256=7a34cc45393a7ae957b29106dc2184411376d2b4ca289b1d64591481ca8e7  # 哈希值
)

示例 3:使用本地源码目录

FetchContent_Declare(googletestSOURCE_DIR  "C:/Users/Administrator/Desktop/googletest" #或 /usr/local/googletest
)

示例 4:传递自定义配置参数

# 声明 spdlog 并禁用其测试模块
FetchContent_Declare(spdlogGIT_REPOSITORY https://github.com/gabime/spdlog.gitGIT_TAG        v1.14.1CMAKE_ARGS     -DSPDLOG_BUILD_TESTING=OFF  # 传递给spdlog的CMake参数(禁用测试)
)

2.3.FetchContent_MakeAvailable

2.3.1.简介

        FetchContent_MakeAvailable 是 CMake 中 FetchContent 模块的核心执行命令,用于将通过 FetchContent_Declare 声明的外部项目实际下载、配置、构建并集成到当前项目中。它是连接 “声明依赖信息” 和 “实际使用依赖” 的关键步骤,简化了外部项目的引入流程。

        基本语法:

FetchContent_MakeAvailable(<项目名称1> <项目名称2> ...)
  • 参数:一个或多个通过 FetchContent_Declare 声明过的项目名称(如 googletestfmt)。
  • 作用:对每个指定的项目,依次执行以下操作:
    1. 下载项目(从 FetchContent_Declare 声明的来源,如 Git 仓库、压缩包);
    2. 配置项目(生成其构建文件,如 Makefile 或 Visual Studio 项目);
    3. 构建项目(编译生成库或可执行文件);
    4. 将项目的目标(如库目标 GTest::gtest)暴露给当前项目,允许直接链接使用。

2.3.2.核心功能与工作流程

FetchContent_MakeAvailable 是一个 “一站式” 命令,自动处理外部项目从获取到集成的全流程,无需手动调用其他命令(如旧版本的 FetchContent_Populate)。其内部流程可拆解为:

  1. 检查缓存:先检查项目是否已下载(在构建目录的 _deps 文件夹中,如 build/_deps/googletest-src)。若已存在且版本匹配,直接复用,避免重复下载。
  2. 下载项目:若未缓存或版本不匹配,根据 FetchContent_Declare 声明的来源(Git 仓库、URL 等)下载源码。
  3. 配置与构建:进入外部项目的构建目录(如 build/_deps/googletest-build),生成构建文件并编译,默认构建静态库(可通过 CMAKE_ARGS 调整)。
  4. 暴露目标:将外部项目的 CMake 目标(如 GTest::gtestfmt::fmt)注册到当前项目的构建系统,允许通过 target_link_libraries 直接链接。

2.3.3.示例用法

 示例 1:集成单个项目(Google Test)

# 1. 引入 FetchContent 模块
include(FetchContent)# 2. 声明项目(必须在 MakeAvailable 之前)
FetchContent_Declare(googletestGIT_REPOSITORY https://github.com/google/googletest.gitGIT_TAG        v1.14.0  # 固定版本GIT_SHALLOW    ON       # 浅克隆
)# 3. 执行下载、配置、构建(核心步骤)
FetchContent_MakeAvailable(googletest)# 4. 使用外部项目的目标(直接链接)
add_executable(my_test test.cpp)
target_link_libraries(my_test PRIVATE GTest::gtest_main)  # GTest 目标已暴露

示例 2:集成多个项目(fmt + spdlog)

include(FetchContent)# 声明第一个项目(fmt)
FetchContent_Declare(fmtGIT_REPOSITORY https://github.com/fmtlib/fmt.gitGIT_TAG        10.2.1
)# 声明第二个项目(spdlog,依赖 fmt)
FetchContent_Declare(spdlogGIT_REPOSITORY https://github.com/gabime/spdlog.gitGIT_TAG        v1.14.1CMAKE_ARGS     -DSPDLOG_FMT_EXTERNAL=ON  # 告诉 spdlog 使用外部 fmt
)# 同时处理多个项目(自动处理依赖顺序:先构建 fmt,再构建 spdlog)
FetchContent_MakeAvailable(fmt spdlog)# 使用目标
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE spdlog::spdlog)  # spdlog 自动链接 fmt

2.3.4.关键特性

1.自动处理依赖顺序:若多个项目存在依赖关系(如 spdlog 依赖 fmt),FetchContent_MakeAvailable 会自动按依赖顺序构建,无需手动指定。

2.与当前项目集成:外部项目的构建会融入当前项目的构建系统(如并行编译、构建类型同步),例如当前项目用 Release 模式,外部项目也会默认用 Release 模式构建。

3.暴露项目路径变量:执行后会自动定义变量:

  • <项目名>_SOURCE_DIR:外部项目的源码目录(如 fmt_SOURCE_DIR);
  • <项目名>_BINARY_DIR:外部项目的构建目录(如 fmt_BINARY_DIR)。
message("fmt 源码路径: ${fmt_SOURCE_DIR}")  # 输出外部项目源码位置

4.缓存机制:下载的源码会缓存到构建目录的 _deps 文件夹,删除构建目录会清除缓存,重新构建时会重新下载。

2.3.5.常见问题与解决方案

1.错误:No content details recorded for <项目名>

  • 原因:FetchContent_MakeAvailable 引用的项目未通过 FetchContent_Declare 声明,或声明在 MakeAvailable 之后。
  • 解决:确保先调用 FetchContent_Declare 声明项目,再调用 MakeAvailable

2.网络问题导致下载失败

解决:通过命令行指定本地源码目录,跳过下载(需提前手动下载源码):

# 例如指定本地 fmt 源码目录
cmake .. -DFETCHCONTENT_SOURCE_DIR_FMT=/path/to/local/fmt

3.需要自定义外部项目的构建选项

解决:在 FetchContent_Declare 中通过 CMAKE_ARGS 传递参数,例如禁用外部项目的测试:

FetchContent_Declare(spdlog# ... 其他参数 ...CMAKE_ARGS -DSPDLOG_BUILD_TESTING=OFF  # 禁用 spdlog 自身的测试
)

3.FetchContent_MakeAvailable和FetchContent_Populate的区别

        在 CMake 中,FetchContent_MakeAvailable 和 FetchContent_Populate 都是 FetchContent 模块中用于处理外部项目的命令,但它们的设计目标、功能流程和使用方式有显著区别,核心差异在于自动化程度推荐用法

1.历史与状态       

  • FetchContent_Populate
    是早期 FetchContent 模块的核心命令,在 CMake 3.11 引入,用于 “填充”(下载、解压)外部项目的源码,但不自动处理配置和构建,需要手动后续步骤。
    从 CMake 3.24 开始被标记为 ** deprecated(弃用)**,官方推荐使用 FetchContent_MakeAvailable 替代(对应政策 CMP0169)。

  • FetchContent_MakeAvailable
    在 CMake 3.14 引入,是对 FetchContent_Populate 的升级,一站式自动化处理外部项目的下载、配置、构建和集成,无需手动干预后续步骤,是当前推荐的用法。

2.功能与流程差异

两者的核心目标都是获取外部项目,但流程复杂度不同:

FetchContent_Populate 的流程(手动为主)

  1. 需先通过 FetchContent_Declare 声明项目信息(如下载地址);
  2. 调用 FetchContent_Populate(<项目名>) 下载并解压源码到本地(仅完成 “获取源码”);
  3. 需手动配置和构建外部项目
    • 通常需要调用 add_subdirectory(${<项目名>_SOURCE_DIR} ${<项目名>_BINARY_DIR}) 将外部项目添加到构建系统;
    • 可能需要手动传递配置参数(如编译选项)。

示例:

include(FetchContent)
# 1. 声明
FetchContent_Declare(fmtGIT_REPOSITORY https://github.com/fmtlib/fmt.gitGIT_TAG 10.2.1
)
# 2. 下载源码(仅这一步)
FetchContent_Populate(fmt)
# 3. 手动配置构建(必须手动添加子目录)
add_subdirectory(${fmt_SOURCE_DIR} ${fmt_BINARY_DIR})

FetchContent_MakeAvailable 的流程(全自动)

  1. 同样需先通过 FetchContent_Declare 声明项目信息;
  2. 调用 FetchContent_MakeAvailable(<项目名>) 后,自动完成:
    • 下载源码(若未缓存);
    • 配置外部项目(生成构建文件);
    • 构建外部项目(编译生成库);
    • 自动将外部项目的目标(如 fmt::fmt)暴露给当前项目,无需手动 add_subdirectory

示例:

include(FetchContent)
# 1. 声明
FetchContent_Declare(fmtGIT_REPOSITORY https://github.com/fmtlib/fmt.gitGIT_TAG 10.2.1
)
# 2. 全自动处理(下载+配置+构建+集成)
FetchContent_MakeAvailable(fmt)
# 直接使用目标,无需手动 add_subdirectory
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE fmt::fmt)

3.核心差异对比

维度FetchContent_PopulateFetchContent_MakeAvailable
自动化程度仅下载源码,配置 / 构建需手动(add_subdirectory全自动:下载→配置→构建→集成,无需手动步骤
依赖处理需手动管理多项目依赖顺序自动处理依赖顺序(如 A 依赖 B,则先构建 B)
目标暴露需外部项目自身支持 CMake 目标,且需手动链接自动暴露目标(如 GTest::gtest),直接链接
当前状态弃用(CMake 3.24+),不推荐新项目使用推荐使用,是 FetchContent 的主流命令
使用复杂度较高(多步骤,易出错)较低(单步命令,简化流程)

4.为什么 FetchContent_Populate 被弃用?

FetchContent_Populate 仅完成 “下载源码” 这一步,后续的配置、构建、目标集成需要手动处理,存在以下问题:

  • 流程繁琐,易遗漏步骤(如忘记 add_subdirectory);
  • 多项目依赖时,需手动维护构建顺序,容易出错;
  • 与现代 CMake 的 “目标驱动” 理念不符(需要显式处理路径和配置)。

而 FetchContent_MakeAvailable 通过自动化这些步骤,解决了上述问题,更符合 CMake 简化构建流程的设计目标。

4.add_test

CMake指令:add_test-CSDN博客

5.完整示例

以下是一个完整的 CMake 项目示例,展示如何结合 CTest 和 Google Test (GTest) 进行单元测试。示例包含项目结构、核心代码和使用方法。

5.1.项目结构

5.2.代码实现

1.根目录 CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(CalculatorDemo)# 启用 CTest(必须放在测试目标定义前)
enable_testing()# 添加主程序和测试子目录
add_subdirectory(src)
add_subdirectory(tests)

2.主程序 src/calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_H// 待测试的简单计算器函数
int add(int a, int b);
int multiply(int a, int b);
bool is_even(int n);#endif // CALCULATOR_H

3.主程序 src/calculator.cpp

#include "calculator.h"int add(int a, int b) {return a + b;
}int multiply(int a, int b) {return a * b;
}bool is_even(int n) {return n % 2 == 0;
}

4.主程序 src/CMakeLists.txt

# 生成静态库(方便测试代码链接)
add_library(calculator STATIC calculator.cpp calculator.h)# 暴露头文件路径(测试代码需要包含 calculator.h)
target_include_directories(calculator PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

5.测试用例 tests/calculator_test.cpp

#include <gtest/gtest.h>
#include "calculator.h"  // 包含待测试的头文件// 测试 add 函数
TEST(CalculatorTest, Add) {EXPECT_EQ(add(2, 3), 5);       // 正常情况EXPECT_EQ(add(-1, 1), 0);      // 正负混合EXPECT_EQ(add(0, 0), 0);       // 零值
}// 测试 multiply 函数
TEST(CalculatorTest, Multiply) {EXPECT_EQ(multiply(3, 4), 12); // 正常情况EXPECT_EQ(multiply(-2, 5), -10); // 负数乘法EXPECT_EQ(multiply(0, 100), 0); // 乘以零
}// 测试 is_even 函数
TEST(CalculatorTest, IsEven) {EXPECT_TRUE(is_even(4));       // 偶数EXPECT_FALSE(is_even(7));      // 奇数EXPECT_TRUE(is_even(0));       // 零(视为偶数)EXPECT_TRUE(is_even(-6));      // 负偶数
}// GTest 提供默认 main 函数,无需手动实现

6.测试配置 tests/CMakeLists.txt

cmake_minimum_required(VERSION 3.14)# 引入 FetchContent 模块,自动下载 GTest
include(FetchContent)# 配置 GTest 下载(使用 v1.14.0 版本)
#FetchContent_Declare(#   googletest#  URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip#  URL_HASH SHA256=8ad598c73ad796e0d82c9be7c307668eaf10519ce3287a0161b7a8006cf3d
#)
FetchContent_Declare(googletest# 外部项目的名称,后续会用到这个名称来引用它。GIT_REPOSITORY https://github.com/google/googletest.git# Git仓库URL。GIT_TAG  release-1.12.1# 指定要下载的Git标签或提交哈希,确保版本一致性。GIT_SHALLOW    ON       #可选:进行浅克隆,减少下载时间。
)
#FetchContent_Declare(
#    googletest
#    SOURCE_DIR  "C:/Users/Administrator/Desktop/googletest"
#)if (MSVC)# 针对Visual Studio的特定配置:# 强制Google Test使用共享运行时库(CRT),以避免与主项目不一致。set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)# 禁用Google Test使用PThreads,避免潜在的冲突或不必要的依赖。set(gtest_disable_pthreads ON CACHE BOOL "" FORCE)
endif()# 完成 GTest 下载和配置
FetchContent_MakeAvailable(googletest)# 生成测试可执行文件
add_executable(calculator_test calculator_test.cpp)# 链接依赖:待测试的库 + GTest 框架
target_link_libraries(calculator_testPRIVATEcalculator          # 主程序的静态库GTest::gtest_main   # GTest 主程序(提供默认 main 函数)
)# 将测试注册到 CTest(名称为 calculator_test)
add_test(NAME calculator_test
#    COMMAND $<TARGET_FILE:calculator_test> # 运行测试的命令,这里使用CMake生成的可执行文件路径。COMMAND calculator_test
)

5.3.运行项目

1.构建项目

# 创建构建目录
mkdir build && cd build# 生成构建文件(自动下载 GTest)
cmake ..

当前CMakeLists.txt中配置是从网络上下载googletest,如果不出什么差错,会输出:

在./build/_deps就会有googletest的源码目录:

2.编译项目

可以用CMake命令直接构建(这个命令是跨平台的,Linux也可以):

cmake --build .  --config Release

如果是在windows的vs环境中,直接用vs打开编译即可。

3.运行测试

# 方法 1:使用 ctest 命令
ctest                  # 简洁输出
ctest -V               # 详细输出(推荐调试)
ctest -R calculator    # 仅运行名称包含 "calculator" 的测试
ctest -C Release -V    # 实际测试用的这个命令# 方法 2:使用 make 命令(等价于 ctest)
make test

 实际效果运行如下:

5.4.遇到的问题

1.FetchContent_MakeAvailable报错

PS D:\OpenProject\myUnitTestEx\build> cmake ..
-- Building for: Visual Studio 17 2022
-- The C compiler identification is MSVC 19.43.34810.0
-- The CXX compiler identification is MSVC 19.43.34810.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe - 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: C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at C:/Program Files/CMake/share/cmake-4.0/Modules/FetchContent.cmake:1263 (message):No content details recorded for googletest
Call Stack (most recent call first):C:/Program Files/CMake/share/cmake-4.0/Modules/FetchContent.cmake:2034 (__FetchContent_getSavedDetails)C:/Program Files/CMake/share/cmake-4.0/Modules/FetchContent.cmake:2384 (__FetchContent_Populate)tests/CMakeLists.txt:21 (FetchContent_MakeAvailable)-- Configuring incomplete, errors occurred!

当时调试的时候就一直报这个错误,也不知道是网络原因还是什么其它原因,于是我手动下载googletest。

https://github.com/google/googletest.git

在CMakeLists.txt中直接用本地的googletest,修改CMakeLists.txt

用同样的方法构建编译即可。

2.没有找到pthread_create

-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- 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 - not found
-- Found Threads: TRUE
-- Configuring done (7.9s)
-- Generating done (0.2s)
-- Build files have been written to: D:/OpenProject/myUnitTestEx/build

因为当前是Windows环境,默认是没有安装pthreads,于是在CMakeLists.txt配置不使用pthreads,在linux环境可以直接用pthreads,调整如下:

3.运行ctest报错

PS D:\OpenProject\myUnitTestEx\build> ctest
Test project D:/OpenProject/myUnitTestEx/buildStart 1: calculator_test
Test not available without configuration.  (Missing "-C <config>"?)
1/1 Test #1: calculator_test ..................***Not Run   0.00 sec0% tests passed, 1 tests failed out of 1Total Test time (real) =   0.01 secThe following tests FAILED:1 - calculator_test (Not Run)
Errors while running CTest
Output from these tests are in: D:/OpenProject/myUnitTestEx/build/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.

原因是使用的是多配置生成器(如 Visual Studio),这类生成器需要明确指定构建配置(如 Debug 或 Release)才能运行测试,否则 CTest 不知道要执行哪个版本的测试程序。

解决方法:运行 CTest 时指定配置

在多配置生成器(如 Visual Studio、Xcode)中,必须通过 -C <配置名> 参数指定测试的配置(与构建时的配置一致)。例如:

# 运行 Debug 配置的测试(最常用,默认构建通常是 Debug)
ctest -C Debug# 若构建了 Release 配置,运行 Release 版本的测试
ctest -C Release

如果需要查看详细的测试输出(方便调试),可以加上 -V 参数:

ctest -C Debug -V  # 详细输出 Debug 配置的测试过程

为什么会出现这个错误?

CMake 生成器分为两类:

  • 单配置生成器(如 Makefile、Ninja):一次只能生成一种配置(如默认 Debug 或 Release),运行 ctest 时无需指定配置。
  • 多配置生成器(如 Visual Studio、Xcode):一次可生成多种配置(同时支持 DebugRelease 等),测试程序会分别编译到 build/Debugbuild/Release 等目录。因此,运行 ctest 时必须用 -C 指定具体配置,否则 CTest 找不到对应的测试可执行文件。

4.CMake版本警告

CMake Deprecation Warning at build/_deps/googletest-src/CMakeLists.txt:4 (cmake_minimum_required):Compatibility with CMake < 3.10 will be removed from a future version ofCMake.Update the VERSION argument <min> value.  Or, use the <min>...<max> syntaxto tell CMake that the project requires at least <min> but has been updatedto work with policies introduced by <max> or earlier.CMake Deprecation Warning at build/_deps/googletest-src/googlemock/CMakeLists.txt:39 (cmake_minimum_required):Compatibility with CMake < 3.10 will be removed from a future version ofCMake.Update the VERSION argument <min> value.  Or, use the <min>...<max> syntaxto tell CMake that the project requires at least <min> but has been updatedto work with policies introduced by <max> or earlier.CMake Deprecation Warning at build/_deps/googletest-src/googletest/CMakeLists.txt:49 (cmake_minimum_required):Compatibility with CMake < 3.10 will be removed from a future version ofCMake.Update the VERSION argument <min> value.  Or, use the <min>...<max> syntaxto tell CMake that the project requires at least <min> but has been updatedto work with policies introduced by <max> or earlier.

        这些警告是由于你使用的 Google Test (GTest) 版本中,其内部 CMakeLists.txt 指定的最低 CMake 版本过低(低于 3.10),而你当前使用的 CMake 版本较新,提前提示 “未来版本将不再支持低版本 CMake 兼容”。

        解决方法可参考:

CMake进阶: CMake的策略和向后兼容-CSDN博客

整个示例代码,本人在麒麟操作系统下亲测也有效:

5.5.完整代码下载

通过网盘分享的文件:myUnitTestEx.zip 链接: https://pan.baidu.com/s/1stIRyqhUSDG4e3zcoAqudg?pwd=1234 提取码: 1234 

6.优势与适用场景

  1. 简化依赖管理:无需用户手动下载、安装外部库,CMake 自动处理,提升项目可移植性。
  2. 配置阶段完成:依赖在 cmake 配置时准备就绪,避免 ExternalProject 在构建阶段才下载导致的并行构建问题。
  3. 无缝集成目标:外部项目的目标(如 GTest::gtestfmt::fmt)可直接通过 target_link_libraries 链接,与本地目标用法一致。
  4. 适合第三方库:尤其适合集成开源库(如 GTest、spdlog、fmt 等),无需修改库源码即可使用。

7.注意事项

1.CMake 版本要求:需 CMake 3.11 及以上,部分高级特性(如 GIT_SHALLOW)需要更高版本(3.14+)。

2.网络依赖:构建项目时需要网络连接(首次下载),可通过 FETCHCONTENT_SOURCE_DIR_<项目名称> 变量指定本地目录,避免重复下载:

# 命令行指定本地目录(已提前下载的源码)
cmake .. -DFETCHCONTENT_SOURCE_DIR_GOOGLETEST=/path/to/local/gtest

3.缓存机制:下载的源码会缓存到构建目录的 _deps 文件夹(如 build/_deps/googletest-src),删除构建目录会触发重新下载。

8.总结

        FetchContent是现代 CMake 项目管理外部依赖的首选工具,通过简洁的配置即可自动下载、集成第三方库,大幅简化了跨平台项目的依赖管理流程。对于需要依赖多个开源库的项目,使用 FetchContent 能显著提升构建的便捷性和一致性。

相关链接

  • CMake 官网 CMake - Upgrade Your Software Build System
  • CMake 官方文档:CMake Tutorial — CMake 4.1.0-rc4 Documentation
  • CMake 源码:https://github.com/Kitware/CMake
  • CMake 源码:CMake · GitLab
  • 中文版基础介绍: CMake 入门实战 | HaHack
  • wiki: Home · Wiki · CMake / Community · GitLab
  • Modern CMake 简体中文版:  Introduction · Modern CMake

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/917577.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/917577.shtml
英文地址,请注明出处:http://en.pswp.cn/news/917577.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

亚马逊广告投放:如何减少无效曝光提高ROI

“为什么广告花费高但转化率低&#xff1f;”“如何判断关键词是否值得继续投放&#xff1f;”“曝光量暴涨但订单没增加怎么办&#xff1f;”“ACOS居高不下该如何优化&#xff1f;”“手动广告和自动广告的预算怎么分配&#xff1f;”如果你也在为这些问题头疼&#xff0c;说…

Ethereum:拥抱开源,OpenZeppelin 未来的两大基石 Relayers 与 Monitor

不知道大家是否注意到&#xff0c;OpenZeppelin 正在经历一次重大的战略转型。他们决定在 2026 年 7 月 1 日正式关闭其广受好评的 SaaS 平台——Defender&#xff0c;并将重心全面转向开源工具的建设。 这一举动在社区引发了广泛的讨论&#xff0c;也标志着 OpenZeppelin 希望…

HFSS许可监控与分析

在电磁仿真领域&#xff0c;HFSS&#xff08;High Frequency Structure Simulator&#xff09;因其卓越的性能和广泛的应用而受到用户的青睐。然而&#xff0c;随着企业和研究机构对HFSS使用需求的不断增长&#xff0c;如何有效监控和分析HFSS许可证的使用情况&#xff0c;以确…

【前端:Html】--1.3.基础语法

目录 1.Html--文件路径 2.Html--头部元素 2.1.head元素 2.2.title元素 2.3.style元素 2.4.link元素 2.5.meta元素 2.6.script元素 2.7.base 3.Html--布局技巧 3.1.CSS Float 浮动布局 3.2.CSS Flexbox 布局 3.3.CSS Grid 网格布局 3.Html--响应式web设计 3.1.设…

Java 中 Nd4j 中的 INDArray 经过 reshape 之后数据丢失(rank = 0)

问题&#xff1a; 数据经过&#xff1a; INDArray inputArray Nd4j.create(input); // 将整个输入数组转换为 INDArray INDArray accs inputArray.get(NDArrayIndex.interval(0, imuNum * 3)).reshape(imuNum, 3, 1); // 加速度部分 INDArray oris inputArray.get(NDArrayIn…

正点原子阿波罗STM32F429IGT6移植zephyr rtos(四)---在独立的应用工程里使用MPU6050

硬件平台&#xff1a;正点原子阿波罗STM32F429IGT6 zephyr版本&#xff1a;Zephyr version 4.2.0 开发环境&#xff1a;wsl ubuntu 24.4 前景提要&#xff1a; 正点原子阿波罗STM32F429IGT6移植zephyr rtos&#xff08;三&#xff09;---创建一个独立的应用工程-CSDN博客 一.修…

SAP_MMFI模块-质保金标准解决方案详解

一、业务背景 在许多企业的采购业务中,尤其是设备采购、工程项目或关键物料供应,通常会与供应商约定一笔质保金(或称保留金)。这笔款项在货物交付验收后并不会立即支付,而是会被扣留一段时间(如一年),作为供应商产品质量的保证。 核心业务痛点: 在没有系统化管理的…

Stanford CS336 assignment1 | Byte-Pair Encoding (BPE) Tokenizer

BPE一、 BPETrain1、 unicode standard and unicode encoding2、 子词分词(subword tokenization)3、 BPE的训练a、 Vocabulary initializationb、 Pre-tokenizationc、 Compute BPE merges4、 train_BPE更多实现上的细节二、 BPETokenizerinit函数from_filesencodedecodeencod…

RockAI 的破壁之战:Yan 架构如何啃下“端侧炼丹”硬骨头?

过去两年&#xff0c;AI 模型的发展叙事几乎被两大阵营主导&#xff1a;无所不能的云端模型与充满想象的端侧模型。行业曾描绘一个诱人蓝图&#xff1a;随着轻量化模型能力的提升&#xff0c;AI 终将摆脱云端束缚&#xff0c;在每个人的设备上实现永不离线的贴身智能。然而&…

交叉验证:原理、作用与在机器学习流程中的位置

交叉验证&#xff08;Cross-Validation&#xff09;是机器学习中评估模型性能、选择最优参数和防止过拟合的核心技术。它在整个机器学习流程中扮演着关键角色。一、为什么需要交叉验证&#xff1f;1. 解决训练/测试划分的局限性​​问题​​&#xff1a;随机单次划分训练集/测试…

js怎么判断一个未申明的变量?

在 JavaScript 中&#xff0c;判断一个变量是否未声明&#xff08;未定义&#xff09;需要特别注意&#xff0c;因为直接访问未声明的变量会抛出 ReferenceError 错误。 最安全的方式是使用 typeof 操作符&#xff0c;因为它对未声明的变量操作时不会报错&#xff0c;而是返回 …

C++进阶-封装红黑树模拟实现map和set(难度较高)

目录 1.预备知识 2.初步代码 3.对红黑树实现的代码进行改造 4.对map和set的改造 5.对RBTree::insert的改造 6.对RBTree::Find函数的改造 7.实现iterator(最重要) 8.实现const_iterator 9.完成set和map的key不能修改 10.实现map的operator[] 11.代码汇总 12.总结 1.预…

安装MySQL可视化管理工具DBeaver教程

系统&#xff08;kelin&#xff09;上安装MySQL可视化管理工具DBeaver教程 背景说明 在国产操作系统麒麟&#xff08;基于Debian/Ubuntu&#xff09;环境下&#xff0c;MySQL数据库管理常依赖命令行&#xff0c;效率较低且不便于直观操作。借助 DBeaver 这类跨平台的图形化数据…

非机动车乱停放识别准确率↑37%:陌讯多特征融合算法实战解析

一、行业痛点&#xff1a;非机动车治理的技术瓶颈根据《2023 城市静态交通治理报告》显示&#xff0c;国内一线城市非机动车乱停放占用人行道比例超 60%&#xff0c;传统监控方案存在三大技术难点&#xff1a;遮挡干扰&#xff1a;共享单车与私人电动车堆叠导致目标完整性缺失&…

Eclipse 安装插件指南

Eclipse 安装插件指南 引言 Eclipse 是一款强大的集成开发环境(IDE),广泛应用于Java、C/C++、PHP等多种编程语言。为了提高开发效率,Eclipse 支持通过插件来扩展其功能。本文将详细介绍如何在Eclipse中安装插件,帮助您快速提升开发体验。 插件概述 Eclipse 插件是用于…

区块链 和 一致性哈希的结合

怎么结合呢&#xff1f; 我们先来回顾一下一致性哈希代码实现里面的结构 // Consistent holds the information about the members of the consistent hash circle. type Consistent struct {mu sync.RWMutex // 读写锁&#xff0c;用于保护并发访问共享数据config Con…

使用yolo11训练智慧医疗-孤独症儿童行为检测数据集VOC+YOLO格式7295张34类别步骤和流程

【数据集介绍】数据集中有很多增强图片&#xff0c;也有很多视频连续截取图片请查看图片预览数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件)图片数量(jpg文件个数)&#xff1a;…

vim 组件 使用pysocket进行sock连接

vim组件实现 以下是使用 Vim 插件架构实现 Python Socket 客户端的完整方案&#xff0c;支持集成到 Vim 控件并实现双向通信&#xff1a; ~/.vim/plugin/socket_client.vim" 定义全局命令和快捷键 command! -nargs* SocketConnect call s:StartSocketClient(<f-args>…

FFmpeg+javacpp中纯音频播放

FFmpegjavacpp中纯音频播放1. Java Sound播放2、整合音频信息AudioInfo3、添加ExecutorService执行播放FFmpegjavacppjavacv使用 FFmpegjavacpp中FFmpegFrameGrabber FFmpegjavacpp中仿ffplay播放 JavaCV 1.5.12 API JavaCPP Presets for FFmpeg 7.1.1-1.5.12 API1. Java Soun…

洛谷P1036 [NOIP 2002 普及组] 选数

P1036 [NOIP 2002 普及组] 选数 题目描述 已知 nnn 个整数 x1,x2,⋯ ,xnx_1,x_2,\cdots,x_nx1​,x2​,⋯,xn​&#xff0c;以及 111 个整数 kkk&#xff08;k<nk<nk<n&#xff09;。从 nnn 个整数中任选 kkk 个整数相加&#xff0c;可分别得到一系列的和。例如当 n4n…