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)

将库链接到你的可执行文件上。

# 将 utils 库链接到 main 程序
target_link_libraries(main PRIVATE utils)

3. 现代 CMake 的核心概念:作用域

target_... 系列命令中(如 include 或 link),你会看到 PRIVATEPUBLICINTERFACE 三个关键字,它们的区别非常重要:

关键字 含义 场景举例
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
)
posted @ 2025-12-18 14:36  belief73  阅读(3)  评论(0)    收藏  举报