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

FetchContentgoogletest

除了 googletest 以外, 我們將 Day 14fmt 也改由 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, 就可以看到在引入 fmtgoogletest 時做了哪些事

-- 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) }}
直播中

尚未有邦友留言

立即登入留言