CMake的作用和使用方式&&构建项目常用的CMakeLists模板

CMakeLists.txt 是 CMake 构建系统的核心配置文件,用于描述如何编译和构建 C/C++ 项目。它类似于传统的 Makefile,但更高级、跨平台且易于维护。

一、CMake 核心作用和使用方式的详细说明

1. CMake 是什么?
CMake 是一个跨平台的构建工具生成器,它本身不直接编译代码,而是生成特定平台的构建文件(如 Makefile、Visual Studio 项目文件等)。
优势:一次编写配置,跨平台生成对应构建文件,避免为不同平台维护多套 Makefile。
2. CMakeLists.txt 的核心作用
(1) 定义项目基本信息

cmake_minimum_required(VERSION 3.10)  # 最低 CMake 版本要求
project(MyProject VERSION 1.0.0)      # 项目名称和版本

(2) 设置编译选项和变量

set(CMAKE_CXX_STANDARD 17)           # C++ 标准
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")  # 编译选项
set(SOURCE_DIR "${CMAKE_SOURCE_DIR}/src")  # 自定义变量

(3) 添加源文件和头文件路径

# 自动收集 src 目录下的所有 .cpp 文件
file(GLOB_RECURSE SOURCES "${SOURCE_DIR}/*.cpp")

# 添加头文件搜索路径
include_directories("${CMAKE_SOURCE_DIR}/include")

(4) 定义目标(可执行文件或库)

# 添加可执行文件
add_executable(myapp ${SOURCES})

# 添加库(STATIC=静态库,SHARED=动态库)
add_library(mylib SHARED ${LIB_SOURCES})

(5) 链接外部库

# 查找系统库(如 pthread)
find_package(Threads REQUIRED)
target_link_libraries(myapp PRIVATE Threads::Threads)

# 链接自定义库
target_link_libraries(myapp PRIVATE mylib)

(6) 控制构建过程

# 设置输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")

# 添加自定义构建步骤
add_custom_command(TARGET myapp POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${CMAKE_SOURCE_DIR}/assets" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets"
)
  1. 项目结构示例
myproject/
├── CMakeLists.txt        # 主配置文件
├── src/                  # 源文件
│   ├── main.cpp
│   └── ...
├── include/              # 头文件
│   └── mylib/
│       └── myheader.h
├── lib/                  # 第三方库
└── build/                # 构建目录(建议外部构建)
  1. 典型工作流程
    (1)编写 CMakeLists.txt:定义项目结构和编译规则。
    (2)创建构建目录(建议)
mkdir build && cd build

(3)运行CMake生成构建文件:

cmake ..  # 生成 Makefile(Linux/macOS)或 VS 项目文件(Windows)

(4) 执行构建:

make  # Linux/macOS
# 或双击 .sln 文件(Windows)
  1. 高级特性
    (1) 条件编译
option(BUILD_TESTS "Build tests" ON)  # 可通过 cmake -DBUILD_TESTS=OFF 关闭

if(BUILD_TESTS)
    add_subdirectory(tests)
endif()

(2) 模块化设计
通过 add_subdirectory() 包含子目录的 CMakeLists.txt,实现模块化管理:

# 主 CMakeLists.txt
add_subdirectory(src)
add_subdirectory(lib)

# src/CMakeLists.txt
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE mylib)

# lib/CMakeLists.txt
add_library(mylib STATIC lib.cpp)

(3) 查找第三方库

# 查找 OpenCV
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(myapp PRIVATE ${OpenCV_LIBS})
  1. 常见命令速查表
    命令 作用
    project() 定义项目名称和版本
    add_executable() 添加可执行文件目标
    add_library() 添加库目标(STATIC/SHARED/MODULE)
    target_link_libraries() 链接库到目标
    include_directories() 添加头文件搜索路径
    set() 设置变量(如编译选项、路径)
    find_package() 查找并导入第三方库或工具
    add_subdirectory() 添加子目录,处理其中的 CMakeLists.txt
    file() 文件操作(如收集源文件、复制文件)
    option() 定义可配置选项(通过 cmake -D 传递)

  2. 推荐学习资源
    官方文档:CMake Documentation
    CMake 实践教程:Modern CMake Tutorial
    CMake 最佳实践:Effective CMake

通过合理使用 CMakeLists.txt,你可以高效管理复杂项目的构建过程,提升跨平台开发体验。

二、CMakeLists模板

新朋友构建新的CPP项目,都会觉得CMakeLists.txt难写,尤其是构建大型项目时,容易写错,如果有个CMake模板就好了,下面是我简单总结的常见模板:我将详细解释 QXlsx 项目的 CMakeLists.txt 文件的结构和各个部分的作用作为例子:

# 1. 基本项目设置
cmake_minimum_required(VERSION 3.16)  # 指定最低 CMake 版本要求
project(QXlsx                          # 定义项目名称
    VERSION 1.5.0                      # 项目版本号
    LANGUAGES CXX                      # 使用的编程语言(C++)

# 2. 基本配置
set(CMAKE_INCLUDE_CURRENT_DIR ON)      # 将当前目录添加到包含路径
set(CMAKE_AUTOMOC ON)                  # 启用 Qt 的 MOC 自动处理
include(GNUInstallDirs)               # 包含 GNU 标准安装目录定义

# 3. Qt 依赖配置
if(NOT DEFINED QT_VERSION_MAJOR)       # 如果没有指定 Qt 版本
    find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui REQUIRED)  # 查找 Qt6 或 Qt5
endif()
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui REQUIRED)  # 查找具体版本的 Qt
set(EXPORT_NAME QXlsxQt${QT_VERSION_MAJOR})  # 设置导出名称

# 4. C++ 标准设置
if (QT_VERSION_MAJOR EQUAL 6)          # 如果是 Qt6
    set(CMAKE_CXX_STANDARD 17)         # 使用 C++17
else()
    set(CMAKE_CXX_STANDARD 11)         # 使用 C++11
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)    # 强制要求使用指定的 C++ 标准

# 5. 路径设置
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)  # 设置 CMake 模块路径
# 设置各种路径变量
if(NOT DEFINED QXLSX_PARENTPATH)
    set(QXLSX_PARENTPATH ${CMAKE_CURRENT_SOURCE_DIR}/../)
endif()
if(NOT DEFINED QXLSX_HEADERPATH)
    set(QXLSX_HEADERPATH ${CMAKE_CURRENT_SOURCE_DIR}/../QXlsx/header/)
endif()
if(NOT DEFINED QXLSX_SOURCEPATH)
    set(QXLSX_SOURCEPATH ${CMAKE_CURRENT_SOURCE_DIR}/../QXlsx/source/)
endif()

# 6. 构建选项
option(BUILD_SHARED_LIBS "Build in shared lib mode" OFF)  # 设置是否构建动态库

# 7. 源文件列表
set(SRC_FILES ...)                     # 设置源文件列表
set(QXLSX_PUBLIC_HEADERS ...)          # 设置公共头文件列表

# 8. 创建库目标
add_library(QXlsx                      # 创建库目标
    ${SRC_FILES}                       # 源文件
    ${QXLSX_PUBLIC_HEADERS}            # 公共头文件
)
add_library(QXlsx::QXlsx ALIAS QXlsx)  # 创建别名目标

# 9. 编译定义
target_compile_definitions(QXlsx PRIVATE  # 添加编译定义
    QT_NO_KEYWORDS
    QT_NO_CAST_TO_ASCII
    # ... 其他 Qt 相关的编译定义
)

# 10. 平台特定设置
if (NOT WIN32)                         # 非 Windows 平台特定设置
    target_compile_definitions(QXlsx PRIVATE QT_STRICT_ITERATORS)
endif()

# 11. 编译特性设置
target_compile_features(QXlsx INTERFACE cxx_std_11)  # 设置 C++ 标准特性

# 12. 动态库特定设置
if (BUILD_SHARED_LIBS)
    target_compile_definitions(QXlsx PUBLIC QXlsx_SHAREDLIB)
endif()

# 13. 链接依赖
target_link_libraries(${PROJECT_NAME}   # 链接 Qt 库
   Qt${QT_VERSION_MAJOR}::Core
   Qt${QT_VERSION_MAJOR}::GuiPrivate
)

# 14. 包含目录设置
target_include_directories(QXlsx        # 设置包含目录
PRIVATE
    ${QXLSX_HEADERPATH}                # 私有包含目录
PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/header>  # 公共包含目录
    $<INSTALL_INTERFACE:include/QXlsxQt${QT_VERSION_MAJOR}>
)

# 15. 目标属性设置
set_target_properties(QXlsx PROPERTIES  # 设置目标属性
    OUTPUT_NAME ${EXPORT_NAME}          # 输出文件名
    VERSION ${PROJECT_VERSION}          # 版本号
    SOVERSION ${PROJECT_VERSION_MAJOR}  # 主版本号
    PUBLIC_HEADER "${QXLSX_PUBLIC_HEADERS}"  # 公共头文件
)
### CMakeLists.txt 文件概述 CMakeLists.txt 是用于描述 CMake 构建过程项目配置的文件[^2]。该文件包含一系列命令、变量设置以及流程控制结构,旨在指导 CMake 生成适用于特定平台编译器的构建系统文件。 #### 创建简单的 CMakeLists.txt 文件 对于初学者而言,可以从一个简易版本入手: ```cmake # 设置最低支持的 CMake 版本 cmake_minimum_required(VERSION 3.10) # 定义项目名称及其默认语言 project(MyProject VERSION 1.0 LANGUAGES CXX) # 添加可执行文件 target 名称为 myapp, 使用 main.cpp 源码文件 add_executable(myapp src/main.cpp) ``` 此段代码展示了如何创建最基础的 `CMakeLists.txt` 文件来定义最小化的 C++ 工程[^1]。 #### 配置并生成动态库 当目标是生成共享库而非独立的应用程序时,则需调整上述脚本如下所示: ```cmake # 设定所需的最低 cmake 版本号 cmake_minimum_required(VERSION 3.10) # 初始化工程名为 MyLibrary 并指定其主要编程语言为 C++ project(MyLibrary VERSION 1.0 LANGUAGES CXX) # 将源文件列表赋给变量 SOURCES set(SOURCES src/hello.cpp) # 声明要创建的名字叫 hello 的共享库 (即 .so 或者 .dll),并将 SOURCES 中列出的所有 cpp 文件作为输入传递给这个新库 add_library(hello SHARED ${SOURCES}) ``` 这段脚本不仅指定了项目的元数据,还通过调用 `add_library()` 函数告知 CMake构建的是一个共享库而不是应用程序,并且给出了构成该库的具体实现文件路径[^3]。 #### 整合第三方依赖项 如果项目依赖于外部库或其他资源,在 `CMakeLists.txt` 中也需要相应声明这些关系: ```cmake find_package(MathAPI REQUIRED) # 查找 MathAPI 库的位置;如果没有找到则报错退出 include_directories(${MathAPI_INCLUDE_DIRS}) # 向编译器提供头文件所在目录的信息 target_link_libraries(myapp PRIVATE MathAPI::MathAPI) # 把链接到 mathapi 这个库的任务分配给了 myapp 可执行文件的目标对象 ``` 这里展示了一个典型场景下引入第三方组件的方式——先利用 `find_package()` 寻址所需库的确切位置,再经由 `include_directories()` `target_link_libraries()` 来完成实际集成工作[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值