CMake進階: 使用FetchContent方法基于gTest的C++單元測試

目錄

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…