CMake
1. 极简模板 (Hello World)
这是运行一个 C++ 项目所需的最小化配置。
cmake_minimum_required(VERSION 3.10) # 指定 CMake 最低版本
project(MyProject) # 项目名称
# 设置 C++ 标准 (推荐 C++14 或 C++17)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 添加可执行文件 (Target)
# 语法: add_executable(程序名 源文件)
add_executable(main main.cpp)
2. 核心指令详解 (构建工具箱)
A. 管理源文件
对于小项目,手动列出文件最安全;对于大项目,可以使用搜索命令。
-
手动指定(推荐):
add_executable(main main.cpp src/helper.cpp src/network.cpp ) -
自动搜索(方便但有副作用):
# 将 src 目录下所有 .cpp 文件存入 SRC_LIST 变量 aux_source_directory(./src SRC_LIST) add_executable(main ${SRC_LIST})
B. 处理头文件路径 (Include)
现代 CMake 强调作用域。不要使用全局的 include_directories,而应针对具体的 Target 使用 target_include_directories。
# 假设头文件在 include/ 目录下
target_include_directories(main PRIVATE ${CMAKE_SOURCE_DIR}/include)
C. 生成库文件 (Library)
如果你要写一个库而不是可执行程序:
# 生成静态库 libutils.a (Linux) 或 utils.lib (Windows)
add_library(utils STATIC src/utils.cpp)
# 生成动态库 libutils.so (Linux) 或 utils.dll (Windows)
add_library(utils SHARED src/utils.cpp)
D. 链接库文件 (Link)
将库链接到你的可执行文件上。
# 将 utils 库链接到 main 程序
target_link_libraries(main PRIVATE utils)
3. 现代 CMake 的核心概念:作用域
在 target_... 系列命令中(如 include 或 link),你会看到 PRIVATE、PUBLIC、INTERFACE 三个关键字,它们的区别非常重要:
| 关键字 | 含义 | 场景举例 |
|---|---|---|
| PRIVATE | 独享。只有我自己编译时需要,依赖我的人不需要。 | main.cpp 里面用了某个库,但头文件没暴露给别人。 |
| INTERFACE | 传递。我自己编译不需要,但依赖我的人需要。 | 纯头文件库 (Header-only library)。 |
| PUBLIC | 共享。我自己需要,依赖我的人也需要。 | 我的头文件里包含了别人的头文件。 |
示例:
target_include_directories(my_lib PUBLIC include/private_headers)
4. 引入第三方库 (find_package)
这是 CMake 最强大的功能之一,用于查找系统中已安装的库(如 OpenCV, Boost, Qt 等)。
# 1. 查找包
find_package(OpenCV 4.0 REQUIRED)
# 2. 包含头文件 (现代 CMake 中,很多库会自动处理这一步,无需手动写)
# target_include_directories(main PRIVATE ${OpenCV_INCLUDE_DIRS})
# 3. 链接库
if(OpenCV_FOUND)
target_link_libraries(main PRIVATE ${OpenCV_LIBS})
endif()
5. 典型的多目录结构实战
一个标准的 C++ 工程目录结构通常如下:
Project/
├── CMakeLists.txt (主 CMake)
├── include/ (头文件)
├── src/ (源代码)
│ ├── CMakeLists.txt (子 CMake)
│ └── main.cpp
└── lib/ (存放生成的库或第三方库)
根目录 CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(MyComplexProject)
# 添加子目录,CMake 会去 src 目录下找 CMakeLists.txt 运行
add_subdirectory(src)
src 目录 CMakeLists.txt:
# 这里的路径通常用相对路径
add_executable(app main.cpp)
# 引用上级目录的 include
target_include_directories(app PRIVATE ${PROJECT_SOURCE_DIR}/include)
6. 常用辅助设置
把这些放在主 CMakeLists.txt 的顶部,可以让开发更顺手:
-
指定输出目录 (让生成的 .exe 和 .so 都在 bin 目录下,而不是散落在 build 文件夹里):
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -
开启调试模式:
set(CMAKE_BUILD_TYPE Debug) # 或者 Release -
打印日志:
message(STATUS "当前源码路径: ${CMAKE_SOURCE_DIR}")
总结:一份完整的参考模板
你可以直接复制这份模板用于中型项目:
cmake_minimum_required(VERSION 3.15)
project(DemoProject VERSION 1.0)
# --- 1. 设置标准 ---
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# --- 2. 设置输出路径 ---
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# --- 3. 查找第三方库 (例如线程库) ---
find_package(Threads REQUIRED)
# --- 4. 定义库 Target ---
add_library(my_math_lib STATIC src/math.cpp)
target_include_directories(my_math_lib PUBLIC include) # PUBLIC 因为使用者需要引用 include/math.h
# --- 5. 定义可执行文件 Target ---
add_executable(app src/main.cpp)
# --- 6. 链接 ---
# app 需要链接 my_math_lib 和 系统线程库
target_link_libraries(app PRIVATE
my_math_lib
Threads::Threads
)
浙公网安备 33010602011771号