iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
Software Development

30 天 CMake 跨平台之旅系列 第 15 篇

[Day 15] 加入 Open source library

  • 分享至 

  • xImage
  •  

本日內容

  • FetchContent 與 Git
  • 來寫測試吧!
  • 預告

連結: Day 15 - Colab

記得在 Day 14 的範例中, 我們是先將套件下載到本地端, 在 local build 並安裝之後, 才將該套件拉進我們的 CMake 專案, 有點麻煩

今天會介紹 FetchContent 的第二種用法, 讓我們可以省略手動下載的步驟, 直接用 FetchContent_Declare(Git) 指定 tag 並下載 Github 的專案!

今天會延續 Day 14 的範例, 搭配 Day 12 介紹過的 Link Seams 技巧, 把使用 fmt 的功能單獨拆成一個 static library, 並在測試時將他 mock 掉, 也可以去今天的 Colab 看比較清楚

在開始之前, 先來引入 googletest 吧

FetchContent 與 googletest

除了 googletest 以外, 我們將 Day 14 的 fmt 也改由 FetchContent 加入

include(FetchContent)
set(FETCHCONTENT_QUIET OFF)
FetchContent_Declare(fmt
  GIT_REPOSITORY  https://github.com/fmtlib/fmt.git
  GIT_REMOTE_NAME origin
  GIT_TAG         10.1.1
  GIT_SHALLOW     TRUE
)
FetchContent_Declare(googletest
  GIT_REPOSITORY  https://github.com/google/googletest.git                                                       GIT_REMOTE_NAME origin
  GIT_TAG         v1.14.0
  GIT_SHALLOW     TRUE
)
FetchContent_MakeAvailable(fmt googletest)

我們在下載 (FetchContent_Declare()) 前, 先把 FETCHCONTENT_QUIET 設為 OFF, 就可以看到在引入 fmt 和 googletest 時做了哪些事

-- Populating fmt
-- Configuring done
-- Generating done
-- Build files have been written to: /content/cmake-example/build/_deps/fmt-subbuild
[ 11%] Creating directories for 'fmt-populate'
[ 22%] Performing download step (git clone) for 'fmt-populate'
Cloning into 'fmt-src'...
HEAD is now at f5e5435 Update version
[ 33%] Performing update step for 'fmt-populate'
[ 44%] No patch step for 'fmt-populate'
[ 55%] No configure step for 'fmt-populate'
[ 66%] No build step for 'fmt-populate'
[ 77%] No install step for 'fmt-populate'
[ 88%] No test step for 'fmt-populate'
[100%] Completed 'fmt-populate'
[100%] Built target fmt-populate
-- Version: 10.1.0
-- Populating googletest
-- Configuring done
-- Generating done
-- Build files have been written to: /content/cmake-example/build/_deps/googletest-subbuild
[ 11%] Performing update step for 'googletest-populate'
[ 22%] No patch step for 'googletest-populate'
[ 33%] No configure step for 'googletest-populate'
[ 44%] No build step for 'googletest-populate'
[ 55%] No install step for 'googletest-populate'
[ 66%] No test step for 'googletest-populate'
[ 77%] Completed 'googletest-populate'
[100%] Built target googletest-populate

可以看到兩個套件都成功產出 build scripts 了

Link External Targets

Day 14 已經提過如何 link fmt, 這裡我們需要知道 googletest 提供了哪些 targets 讓我們 link
首先, 去看看 官方文件, 可以在 Create and run a binary 的地方看到有提供範例

add_executable(
  hello_test
  hello_test.cc
)
target_link_libraries(
  hello_test
  GTest::gtest_main
)

include(GoogleTest)
gtest_discover_tests(hello_test)

如上所示, 我們需要 link GTest::gtest_main

來寫測試吧!

我們先建立一個測試並寫死 PASS() 直接通過
src/test/test_main.cpp

#include <gtest/gtest.h>

namespace {
TEST(UsageTest, CanUseGoogleTest) {
  SUCCEED();
}
}  // anonymous namespace

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

然後 build 該 test target
src/test/CMakeLists.txt

add_executable(TestMain
  test_main.cpp
)
target_link_libraries(TestMain PRIVATE
  GTest::gtest_main
)

include(GoogleTest)
gtest_discover_tests(TestMain)

然後執行測試 ctest --test-dir build, 可以看到我們的測試出現在 terminal 了🎉🎉🎉

Internal ctest changing into directory: /content/cmake-example/build
Test project /content/cmake-example/build
    Start 1: UsageTest.CanUseGoogleTest
1/1 Test #1: UsageTest.CanUseGoogleTest .......   Passed    0.00 sec

關於如何寫測試或是如何使用 GoogleTest 並不在本系列的介紹範圍
有興趣的話請參考 GoogleTest 官方文件

add_test()

如果不想用 googletest 的話, 也可以用 CMake 自己提供的 add_test() 來增加 test cases, 用法如下

add_test(NAME <name> COMMAND <command> [<arg>...]
         [CONFIGURATIONS <config>...]
         [WORKING_DIRECTORY <dir>]
         [COMMAND_EXPAND_LISTS])
  • NAME
    • Test name
  • COMMAND
    • 如果是 executable name 的話, 路徑會是在 build directory (CMAKE_CURRENT_BINARY_DIR) 底下
  • CONFIGURATIONS
    • 給 ctest -C <build-config> 使用, 可以指定 build type
  • WORKING_DIRECTORY
    • 指定 COMMAND 執行的路徑
  • COMMAND_EXPAND_LISTS
    • 會先將 COMMAND args 展開

所以我們可以將上面的測試改成這樣

add_executable(TestMain
  test_main.cpp
)
target_link_libraries(TestMain PRIVATE
  GTest::gtest_main
)

add_test(NAME TestMain COMMAND TestMain)

執行結果會和用 googletest 一樣

預告

了解了引入 libraries 的方法之後, 還需要了解日後該如何更新套件版本
除此之外, 如果我們想要將 library export 給其他人使用, 也需要設定好版本, 這些將在下一篇介紹


上一篇
[Day 14] 加入 System library
下一篇
[Day 16] 管理 Library 版本
系列文
30 天 CMake 跨平台之旅 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言