開發與維運

現代cmake–閱讀筆記

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)

Leave a Reply

Your email address will not be published. Required fields are marked *