1. Running cmake
1.1. cmake選項
–build 指定輸出目錄
-j 指定並行度
–target 指定編譯目標
1.2. 選擇編譯器
EXPORT CC=clang CXX=clang++ cmake ..
1.3. 選擇生成器
默認為make 通過cmake -G Ninja指定ninja
1.4. 指定編譯選項
cmake -DXXX=YYY
cmake會將各種編譯選項緩存到一個文件中,即CMakeCache.txt
1.5. 調試
調試makefile: VERBOSE=1 make
調試cmake:
- cmake –trace, 打印出cmake運行的每一行腳本
- cmake –trace-source= 打印出中運行的每一行腳本
1.6. 指定編譯類型
-DCMAKE_BUILD_TYPE:Debug或Release或RelWithDebInfo
-DCMAKE_INSTALL_PREFIX: 指定安裝路徑,默認為/usr/local
-DBUILD_SHARED_LIBS: 是否編譯共享庫,ON or OFF
-DBUILD_TESTING: 是否編譯tests
2. Do's and Don'ts
2.1. 不要做
- 不要使用全局函數: link_directories, include_libraries等
- 非必要不使用PULIBC限制
- 不要用glob匹配文件:當新增文件時,除非重新跑一遍cmake, make或其他編譯工具將不會感知到新文件
- lib不要直接link到最終的target
- link lib時不要忽略PUBLIC/PRIVATE關鍵字
2.2. 要做
- 把cmake當做正經代碼維護
- 站在target的角度思考
- 善用alias
- 將通用功能抽象成函數或宏
- 函數名統一小寫
- 善用cmake_policy
2.3. 選擇cmake版本
2.3.1. os支持
- 3.4: The bare minimum. Never set less.
- 3.7: Debian old-stable.
- 3.10: Ubuntu 18.04.
- 3.11: CentOS 8 (use EPEL or AppSteams, though)
- 3.13: Debian stable.
- 3.16: Ubuntu 20.04.
- 3.19: First to support Apple Silicon.
- latest: pip/conda-forge/homebew/chocolaty, ect.
筆者目前用的是3.16
2.3.2. 特性
- 3.8: C++ meta features, CUDA, lots more
- 3.11:
IMPORTED INTERFACE
setting, faster, FetchContent,COMPILE_LANGUAGE
in IDEs
- 3.12: C++20,
cmake --build build -j N
,SHELL:
, FindPython
- 3.14/3.15: CLI, FindPython updates
- 3.16: Unity builds / precompiled headers, CUDA meta features
- 3.17/3.18: Lots more CUDA, metaprogramming
3. What's new in in CMake
- cmake 3.0: interface libraries, 允許將一組頭文件抽象成一個lib
- cmake 3.1: 支持c++11和compile features
- cmake 3.2: 支持UTF-8
- cmake 3.4: 支持swift語言,支持ccache
- cmake 3.5: 支持ARM平臺
- cmake 3.6: 支持clang-tidy
- 其他:略
4. 基礎知識
指定最小版本
cmake_minimum_required(VERSION 3.1)
創建工程
project(MyProject VERSION 1.0 DESCRIPTION "Very nice project" LANGUAGES CXX)
新增executable
add_executable(one two.cpp three.h)
新增library
add_library(one STATIC two.cpp three.h)
用戶可指定STATIC、SHARED、MODULE 。缺省使用BUILD_SHARED_LIBS選項。
INTERFAC用於創建頭文件庫
ALIAS用於指定庫的別名.
綁定頭文件路徑
target_include_directories(one PUBLIC include)
PUBLIC表示所有依賴lib的target都自動綁定了該頭文件路徑
PRIVATE表示該頭文件路徑僅對本target有效
INTERFACE表示該頭文件路徑僅對依賴該lib的target生效
PUBLIC = PRIVATE + INTERFACE
5. 變量和cache
定義變量
set(MY_VARIABLE "value")
訪問變量時使用${MY_VARIABLE}
變量僅在當前作用域內有效。
定義變量(多個值)
set(MY_LIST "one" "two")
等效於
set(MY_LIST "one;two")
屬性
set_property(TARGET TargetName PROPERTY CXX_STANDARD 11) set_target_properties(TargetName PROPERTIES CXX_STANDARD 11)
get_property(ResultVariable TARGET TargetName PROPERTY CXX_STANDARD)