iT邦幫忙

2023 iThome 鐵人賽

DAY 4
0

本日內容

  • Predefined variables
  • Normal variables
  • Cache variables
  • Environment variables
  • 這麼多種類, 我該用哪一個😕

連結: Day 4 - Colab

寫在前

以下所講的內容在 Colab 都有對應的 code, 具體範例可以到今天的 Colab 看噢噢

Predefined Variables

CMake 在執行的時候會產生一堆預先定義好的變數
這邊只會先介紹 Day 9 專案需要用到的幾個變數
並比較一下各自的差別, 並說明哪些變數不建議使用

有些變數會在之後隨著專案變得複雜陸續介紹, 若對其他變數有興趣可以參考官方文件
cmake-variables(7)

*_SOURCE_DIR*_BINARY_DIR

* 代表 wildcard, 表示 CMake 提供了很~多有關 source directory 和 binary directory 的變數

可以和今日的 Colab 對照會比較好懂~

記得 [Day 3] 提過 cmake 需要這兩個路徑才能找到 source file 和輸出檔案的路徑

其中 CMake 的 build script (CMakeLists.txt) 的位置決定了該檔案中的 相對路徑 會如何被 CMake 解讀

具體來說如下所示

  • Source directory (src)
    • 用來當作 source files 路徑的前綴, 在寫 CMake 的時候, 相對路徑 (非 / 開頭)
      都會被加上該前綴, 比如 main.cpp, 在 CMake 處理的時候會被解讀成 /path/to/project-root/src/main.cpp
  • Binary directory (build)
    • 用來當作執行 CMake 過程中 "產出的檔案" 路徑的前綴, 這會在之後詳細介紹, 這裡先理解為最終產出的可執行檔即可
      總之, 和 src 類似, 只要寫 CMake 時, 有關產出檔案的指令, 預設都會將相對路徑加上該前綴
      比如 /path/to/project-root/build/main

聽起來蠻直覺的, 就是要讓 CMake 找到檔案嘛

那麼, 為什麼需要這麼多有關 src, build directories 的變數呢?

各種代指 srcbuild 的變數

先來看看有哪些和路徑有關的變數吧

  • 會隨 project() 指令改變的變數, 如果我們的 project 會給其他 CMake 專案使用就會有影響, Day 9 會詳細介紹
    • PROJECT_SOURCE_DIR
    • PROJECT_BINARY_DIR
  • 專屬於我們專案的變數, 只有 project(projectName) 會影響, 所以 projectName 最好不要撞名
    • <PROJECT-NAME>_SOURCE_DIR
    • <PROJECT-NAME>_BINARY_DIR
  • add_subdirectory() 影響的變數, 當我們的專案有很多 subfolder, 且每個 subfolder 都需要 build code 的時候會用到
    • CMAKE_CURRENT_SOURCE_DIR
    • CMAKE_CURRENT_BINARY_DIR
  • 執行 CMake 時, 所在路徑的 CMakeLists.txt 的路徑, 可以簡單認知是 project root 就好
    • 不建議用, 如果我們的 project 會被其他 CMake 專案使用, 此路徑就會變成是別人專案的 project root
    • CMAKE_SOURCE_DIR
    • CMAKE_BINARY_DIR

其他還有一些很重要的變數, 會再後面幾天陸續介紹
目前只需要了解這幾個就好

Normal Variables

我們在 CMake 中自己定義的變數就叫做 normal variables
指令是

set(varName value)

可以用以下指令取值

${varName}

和一般程式語言類似, 這邊就不多做介紹
比較值得注意的是 CMake 如何存 List 和字串到變數

List 和字串

如果有多個值, 並且用空白分隔的話, CMake 會將該值用分號 ; 分隔後合併成一個字串, 比如

set(myVar a b c) # myVar = "a;b;c"

除非空白分隔的值本身是一個字串, 否則都會被 CMake 用分號合併, 比如

set(myVar "a b c") # myVar = "a b c"
set(myVar a b;c) # myVar = "a;b;c"
set(myVar a "b c") # myVar = "a;b c"

List 的用法之後會陸續介紹

Cache Variables

先來看看怎麼設定 cache variables, 有兩種方法

  • set(CACHE)
    set(varName value CACHE type "" [FORCE])
    
    • type
      • 可以參考官方文件 TYPE, 這邊先不多做介紹
  • 或是在執行 cmake 時加上 -D option
    cmake -D varName:type=value
    

取值的指令則是

$CACHE{varName}

和 normal variables 的差別在於, normal variable 在每次執行 cmake 指令時, 都會初始化新的變數
而 cache variables 則是只有在 第一次執行 cmake 指令 才會初始化變數, 之後每次執行都不會再更新了

...聽起來似乎蠻不方便的?

為什麼要需要 Cache Variables?

Cache variables 的使用情境是, 如果我們將專案分享給其他人, 且其他人想將我們的專案加入他們自己的專案中時, cache variables 就可以作為我們專案的 預設值, 讓用我們專案的人自行用 normal variables 覆蓋

沒錯! Cache variables 會被同名的 normal variables 覆蓋, 除非用 $CACHE{varName} 特別把 cache variable 取出來
但是要記得, normal variables 會在每次執行 cmake 指令都初始化一次
而 cache variables 則是初始化後就會一直存在, 執行結束後他的值並不會受到 normal variables 影響

所以, 用我們專案的人可以自由調整他們想要的設定, 我們則可以用 cache variables 提供他們這樣的自由度

但是, 如果還是想要更新 cache variables 要怎麼做呢?

如何更新 Cache Variables?

開發期間勢必會遇到需要調整 cache variables 的情況, 這時候有以下幾種方法可以做到

  • 加上 FORCE option
    • 不建議, 雖然用 FORCE 確實可以強制更新 cache variables, 但是這其實違背了 cache variables 作為 預設值 的設計理念
    set(varName value CACHE FORCE)
    
  • 每次 build code 前都先清掉舊的 cache variables
    • 這是比較建議的做法, 在開發時透過 CLI 指令將之前 build directories 底下的東西都清掉, 就不會讓之前殘留的產出影響到這次 build code, 缺點是因為把 cache 清空了, 沒辦法加速, 用法如下
    • --fresh
      cmake -S <source-dir> -B <build-dir> --fresh
      

Environment variables

通常使用 normal variables 和 cache variables 就夠了, 比較少用到環境變數, 這邊就不深入討論, 基本用法如下所示

設定的指令
set(ENV{PATH} "ENV{PATH}:/path/to/something")

取值的指令
$ENV{var}

這麼多種變數, 我該用哪一個😕

今天我們學到了 CMake 的幾種變數, 那麼, 我該怎麼知道何時該用哪種變數呢?
這邊有個很簡單的判斷方法, 根據各種變數的設計初衷可以知道

  • Predefined variables
    • 是 CMake 的預先建好的變數, 讓寫 CMake 的人使用, 除非有必要, 否則最好不要覆蓋他們, 之後會再細講
  • Normal variables
    • 是開發時首先要使用的變數, 用來在 這次 執行 cmake暫時 儲存一些值, 下一次執行 cmake 就會恢復
  • Cache variables
    • 主要是作為 預設值其他人 使用或覆蓋, 由於其會被 normal variables 覆蓋的特性, 即使專案不會給別人用, 也可以考慮將某些影響整個專案的設定存成 cache variables, 方便日後開發時調整

預告

學會了變數之後, 接下來介紹的 Functions 和 Modules 將會使用今日所學的內容, 忘記的話可以隨時回來看~


上一篇
[Day 3] CMake 介紹
下一篇
[Day 5] Functions 和 Modules
系列文
30 天 CMake 跨平台之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言