CMakeLists.txt
CMAKE_<LANG>_STANDARD
, CMAKE_<LANG>_STANDARD_REQUIRED
, CMAKE_<LANG>_EXTENSIONS
連結: Day 9 - Colab
就如 Day 3 所說, CMake 將 build code 的流程分成 configure, build, test, install, package 幾個階段
我們會先著重在 configure 和 build 的部分, 先把最重要的可執行檔建出來
由於範例皆是在 Linux 開發, 對於 Linux 的檔案系統可以額外參考 Filesystem Hierarchy Standard (FHS)
可以大概知道常見的系統資料夾代表什麼意義, 這部分會在 Day 20 介紹
初期的專案架構會長這樣
cmake-example/
├─ CMakeLists.txt
├─ src/
│ ├─ CMakeLists.txt
│ ├─ main.cpp
非常陽春, 只有
CMakeLists.txt
src
cmake
執行時的 source files 的路徑src/main.cpp
Build directory 會在之後讓 CMake 自動幫我們產生
CMakeLists.txt
內容長這樣
cmake_minimum_required(VERSION 3.26)
project(HelloWorld
LANGUAGES C CXX
)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_subdirectory(src)
src/CMakeLists.txt
add_executable(HelloWorld_Main
main.cpp
)
以下簡單說明每行指令的意思
cmake_minimum_required()
cmake_minimum_required(VERSION major.minor[.patch[.tweak]])
project()
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[DESCRIPTION <project-description-string>]
[HOMEPAGE_URL <url-string>]
[LANGUAGES <language-name>...])
cmake_minimum_required()
下一行就執行
PROJECT-NAME
VERSION
LANGUAGES
C
, CXX
none
就不會檢查語言CMAKE_<LANG>_STANDARD
, CMAKE_<LANG>_STANDARD_REQUIRED
, CMAKE_<LANG>_EXTENSIONS
這三個 project-scope 變數通常是搭配使用的, 所以一起講 (variable scope 可以回去看 Day 4 介紹)
由於 C/C++ 版本需要有對應的 compiler / linker 版本, 最好在 CMakeLists.txt
一開始就設定好
也就是在 project()
下
比如以下範例 (Note: CXX
可以換成前面提過的其他語言, ex. C
)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
CMAKE_CXX_STANDARD
CMAKE_CXX_STANDARD_REQUIRED
設為 ON 才有強制力CMAKE_CXX_STANDARD_REQUIRED
CMAKE_CXX_STANDARD
CMAKE_CXX_EXTENSIONS
OFF
add_executable()
新增 executable target, Day 8 有介紹過, 這邊就不重複介紹了
add_subdirectory()
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL] [SYSTEM])
source_dir
source
directorybinary_dir
binary
directory 建立和 source_dir
相同名稱的 folderbinary
directorysource_dir
在 source tree 外才用EXCLUDE_FROM_ALL
ALL
targetSYSTEM
SYSTEM
會讓 subdirectory 的 non-imported targets 把該 subdirectory 加入 system header search paths我們會先用大家比較熟悉的 Makefile 作為 Generator
由於 Makefile 是 single-config generator, 我們一次只能 build 一種 config 的 binary
關於 single-config generators 和 multi-config generators 的比較在 Day 6 有詳細介紹
我們先 cd
到 cmake-example
底下, 執行
cmake -S src -B build -G "Unix Makefiles"
確認 build
底下有 config files 後, 就可以 build 了!
cmake --build build
為了之後 debug 方便, 我們來 build debug 版本, 關於 build config 請見 Day 7
我們指定一個新的 build directory build-Debug
重新 configure 一次 (因為是 single-config generator, 所以比較麻煩), 然後加上 CMAKE_BUILD_TYPE:BOOL=Debug
cmake -S src -B build-Debug -G "Unix Makefiles" -DCMAKE_BUILD_TYPE:BOOL=Debug
再 build 一次
cmake --build build-Debug
然後把原本的 build
directory 改成 build-Release
後再做一次
cmake -S . -B build-Release -G "Unix Makefiles" -DCMAKE_BUILD_TYPE:BOOL=Release
cmake --build build-Release
這樣我們就有 debug 和 release 版本了!
cmake-example/
├─ CMakeLists.txt
├─ build-Debug/
├─ build-Release/
├─ src/
│ ├─ CMakeLists.txt
│ ├─ main.cpp
對於目前的 single-config generator 來說, 可以先簡單用 CMAKE_BUILD_TYPE
確認即可
message(DEBUG "Build type: ${CMAKE_BUILD_TYPE}")
cmake -S . -B build-Debug -G "Unix Makefiles" -DCMAKE_BUILD_TYPE:BOOL=Debug --log-level=Debug
但是, 記得 Day 6 說過的, multi-config generators 是在 build
stage 才決定 build type
所以用 cache variable 這招會失敗QQ
那要怎麼辦呢?
本系列會在 Day 26 介紹比較可靠的 generator expression
用法大概如下, 搭配 add_custom_target()
(見 Day 8)
set(isDebug "$<IF:$<CONFIG:Debug>, is debug, not debug>")
add_custom_target(mytarget
COMMAND ${CMAKE_COMMAND} -E echo "isDebug? ${isDebug}"
VERBATIM
)
現在, 我們有了第一版簡單的 CMake 專案, 是時候自己寫一些 libraries 了
不過在那之前, 下一篇會先介紹 link libraries 時的一些注意事項