跳到正文

Wiki

CMake工程模板

約 7 分鐘閱讀

本文由簡體中文內容確定性轉換,並受版本化術語表保護。

本章用一個 Linux-only 的 CMake 工程模板來講解 C++ 專案如何組織、構建、安裝和引入第三方庫。

這個模板的目標不是把 CMake 所有語法一次講完,而是圍繞一個真實可執行的工程,理解現代 CMake 最常用的一套寫法:

  1. 頂層 CMakeLists.txt 只做工程總控。
  2. CMakePresets.json 固化 Debug / Release 構建配置。
  3. cmake/ProjectOptions.cmake 儲存專案公共編譯選項。
  4. src/CMakeLists.txt 管理主程式。
  5. 每個庫目錄自己管理原始碼、標頭檔案、安裝規則和第三方依賴。
  6. 第三方庫採用"誰使用,誰 find_package"的方式。

1.模板目錄結構

模板的核心目錄如下:

.
├── CMakeLists.txt
├── CMakePresets.json
├── cmake/
│   └── ProjectOptions.cmake
└── src/
    ├── CMakeLists.txt
    ├── main.cpp
    ├── lib1/
    │   ├── CMakeLists.txt
    │   ├── inc/
    │   │   └── lib1/
    │   │       └── eigen3_test.hpp
    │   └── src/
    │       └── eigen3_test.cpp
    └── lib2/
        ├── CMakeLists.txt
        ├── inc/
        │   └── lib2/
        │       └── eigen3_test.hpp
        └── src/
            └── eigen3_test.cpp

其中:

檔案 職責
CMakeLists.txt 頂層入口,宣告專案、載入公共配置、進入 src
CMakePresets.json 儲存構建預設,例如 linux-debuglinux-release
cmake/ProjectOptions.cmake 儲存 C/C++ 標準、公共 warning 等配置
src/CMakeLists.txt 建立最終執行檔,並連結 lib1lib2
src/lib1/CMakeLists.txt 建立 lib1_src_lib,管理 lib1 自己的 include、依賴、安裝
src/lib2/CMakeLists.txt 建立 lib2_src_lib,管理 lib2 自己的 include、依賴、安裝

2.構建命令

這個模板使用 CMakePresets + Ninja。

Debug 構建:

cmake --preset linux-debug
cmake --build --preset linux-debug
cmake --install build/linux-debug
./install/linux-debug/bin/cmake_template

Release 構建:

cmake --preset linux-release
cmake --build --preset linux-release
cmake --install build/linux-release
./install/linux-release/bin/cmake_template

這幾條命令分別做了四件事:

命令 作用
cmake --preset linux-debug 配置工程,生成 Ninja 構建檔案
cmake --build --preset linux-debug 編譯原始碼並連結目標
cmake --install build/linux-debug 把執行檔、庫、標頭檔案安裝到 install/linux-debug
./install/linux-debug/bin/cmake_template 執行安裝後的程式

日常開發時,不需要每次都安裝。編譯後可以直接執行 build 目錄裡的程式:

./build/linux-debug/src/cmake_template

install 更適合用來驗證"安裝後的目錄結構和動態庫路徑是否正確"。

3.configure、build、install 的區別

CMake 工程一般有三個階段:

3.1.configure

cmake --preset linux-debug

這個階段讀取所有 CMakeLists.txtCMakePresets.json,檢查編譯器、第三方庫、變數,並生成構建系統檔案。

使用 Ninja 時,會在 build/linux-debug 下生成 build.ninja

3.2.build

cmake --build --preset linux-debug

這個階段呼叫 Ninja 編譯 .cpp 檔案,生成 .o.so、執行檔等構建產物。

3.3.install

cmake --install build/linux-debug

這個階段按照 install(...) 規則,把構建產物複製到安裝目錄。

在本模板中,Debug 安裝到:

install/linux-debug/

Release 安裝到:

install/linux-release/

安裝後的典型結構如下:

install/linux-debug/
├── bin/
│   └── cmake_template
├── include/
│   ├── lib1/
│   │   └── eigen3_test.hpp
│   └── lib2/
│       └── eigen3_test.hpp
└── lib64/
    ├── liblib1_src_lib.so
    └── liblib2_src_lib.so

有些 Linux 發行版會使用 lib,有些會使用 lib64。本模板通過 GNUInstallDirs 讓 CMake 自動選擇合適目錄。

4.為什麼不用手寫 build/install/log 指令碼

舊式模板裡常見這種做法:

  1. 自己建立 build 目錄。
  2. build 裡執行 cmake ..
  3. 手寫 make install
  4. 手寫指令碼設定 LD_LIBRARY_PATH
  5. 自己維護日誌目錄。

這個模板改成 CMakePresets 後,這些內容都不再需要:

舊做法 新做法
手動 cd build CMakePresets.json 統一設定 binaryDir
手動設定 Debug / Release preset 裡設定 CMAKE_BUILD_TYPE
手動設定安裝路徑 preset 裡設定 CMAKE_INSTALL_PREFIX
手動呼叫 Makefile preset 指定 Ninja
手動設定動態庫路徑 安裝目標設定 INSTALL_RPATH
手寫 VSCode task VSCode CMake Tools 直接讀取 preset
手寫複雜除錯指令碼 VSCode CMake Tools 直接執行或除錯當前 CMake target

5.VSCode CMake Tools 執行與除錯

這個模板不需要額外寫 VSCode 除錯配置。安裝 CMake Tools 後,VSCode 可以直接識別 CMake 裡的可執行 target,並對當前 target 執行執行或除錯。

圖形化流程可以理解成命令列流程的按鈕版本:

命令列 VSCode CMake Tools
cmake --preset linux-debug 選擇 Linux Debug preset 後 Configure
cmake --build --preset linux-debug 點選 Build
./build/linux-debug/src/cmake_template 選擇 cmake_template target 後點擊執行按鈕
用 GDB 除錯 build 目錄產物 選擇 cmake_template target 後點擊 Debug 按鈕

CMake Tools 執行或除錯的通常是 build 目錄裡的執行檔:

build/linux-debug/src/cmake_template

因此日常開發不需要每次 install。install 主要用於驗證安裝佈局、標頭檔案安裝、動態庫 RPATH 等內容。

推薦流程:

  1. 安裝 VSCode CMake Tools 擴充套件和 Microsoft C/C++ 擴充套件。
  2. 選擇 linux-debug configure preset。
  3. Configure。
  4. Build。
  5. 選擇 cmake_template 作為執行/除錯 target。
  6. 點選 CMake Tools 提供的執行按鈕或 Debug 按鈕。

更詳細的圖形介面操作步驟見 CMakePresets與構建安裝

6.本章建議閱讀順序

  1. CMakePresets與構建安裝:先理解 preset 工作流。
  2. 頂層CMake與公共編譯選項:理解頂層入口和公共配置。
  3. src與lib模組CMake詳解:理解執行檔、庫、include、install。
  4. 第三方庫依賴寫法:學習 Eigen、OpenCV、Boost、PCL 等庫如何引入。

學完後,你應該能做到:

  1. 新建一個 C++ 工程並用 preset 構建。
  2. 新增新的庫目錄。
  3. 新增新的執行檔。
  4. 正確管理標頭檔案 include 路徑。
  5. 在模組內部引入第三方庫。
  6. 安裝後直接執行程式,不依賴手寫指令碼。