CMake工程模板
本章用一個 Linux-only 的 CMake 工程模板來講解 C++ 項目如何組織、構建、安裝和引入第三方庫。
這個模板的目標不是把 CMake 所有語法一次講完,而是圍繞一個真實可運行的工程,理解現代 CMake 最常用的一套寫法:
- 頂層
CMakeLists.txt只做工程總控。 CMakePresets.json固化 Debug / Release 構建配置。cmake/ProjectOptions.cmake保存項目公共編譯選項。src/CMakeLists.txt管理主程序。- 每個庫目錄自己管理源碼、頭文件、安裝規則和第三方依賴。
- 第三方庫採用"誰使用,誰
find_package"的方式。
模板目錄結構
模板的核心目錄如下:
.
├── 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-debug 和 linux-release |
cmake/ProjectOptions.cmake | 保存 C/C++ 標準、公共 warning 等配置 |
src/CMakeLists.txt | 創建最終可執行文件,並鏈接 lib1、lib2 |
src/lib1/CMakeLists.txt | 創建 lib1_src_lib,管理 lib1 自己的 include、依賴、安裝 |
src/lib2/CMakeLists.txt | 創建 lib2_src_lib,管理 lib2 自己的 include、依賴、安裝 |
構建命令
這個模板使用 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 更適合用來驗證"安裝後的目錄結構和動態庫路徑是否正確"。
configure、build、install 的區別
CMake 工程一般有三個階段:
configure
cmake --preset linux-debug
這個階段讀取所有 CMakeLists.txt 和 CMakePresets.json,檢查編譯器、第三方庫、變量,並生成構建系統文件。
使用 Ninja 時,會在 build/linux-debug 下生成 build.ninja。
build
cmake --build --preset linux-debug
這個階段調用 Ninja 編譯 .cpp 文件,生成 .o、.so、可執行文件等構建產物。
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 自動選擇合適目錄。
為什麼不用手寫 build/install/log 腳本
舊式模板裏常見這種做法:
- 自己創建
build目錄。 - 在
build裏執行cmake ..。 - 手寫
make install。 - 手寫腳本設置
LD_LIBRARY_PATH。 - 自己維護日誌目錄。
這個模板改成 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 |
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 等內容。
推薦流程:
- 安裝 VSCode CMake Tools 擴展和 Microsoft C/C++ 擴展。
- 選擇
linux-debugconfigure preset。 - Configure。
- Build。
- 選擇
cmake_template作為運行/調試 target。 - 點擊 CMake Tools 提供的運行按鈕或 Debug 按鈕。
更詳細的圖形界面操作步驟見 CMakePresets與構建安裝。
本章建議閲讀順序
- CMakePresets與構建安裝:先理解 preset 工作流。
- 頂層CMake與公共編譯選項:理解頂層入口和公共配置。
- src與lib模塊CMake詳解:理解可執行文件、庫、include、install。
- 第三方庫依賴寫法:學習 Eigen、OpenCV、Boost、PCL 等庫如何引入。
學完後,你應該能做到:
- 新建一個 C++ 工程並用 preset 構建。
- 添加新的庫目錄。
- 添加新的可執行文件。
- 正確管理頭文件 include 路徑。
- 在模塊內部引入第三方庫。
- 安裝後直接運行程序,不依賴手寫腳本。