c++ CMakeLists.txt详解

基本结构

  1. CMake 最低版本声明
    用于指定需要的最低 CMake 版本,确保兼容性。
cmake 复制代码
cmake_minimum_required(VERSION 3.10)
  • 指定 CMake 的最低版本。
  • 确保用户的 CMake 版本符合项目需求,否则报错。
  • 版本选择建议根据项目使用的功能决定。例如,3.10 引入了 target_link_directories
  1. 项目名称和语言定义
    定义项目的名称及支持的编程语言。
cmake 复制代码
project(ProjectName LANGUAGES C CXX)
  • ProjectName:项目名称,自动赋值给变量 ${PROJECT_NAME}
  • LANGUAGES:指定项目支持的语言,可以是 CCXX(C++)、Fortran 等。
  • 默认生成变量:
    • ${PROJECT_SOURCE_DIR}:项目根目录。
    • ${PROJECT_BINARY_DIR}:构建目录。
  1. 设置编译选项
    设置标准版本(如 C++17)或添加额外的编译器选项。
cmake 复制代码
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
  • CMAKE_CXX_STANDARD:设置 C++ 标准(如 11、14、17、20)。
  • CMAKE_CXX_STANDARD_REQUIRED:强制使用指定版本。
  • CMAKE_CXX_EXTENSIONS:是否使用非标准扩展(如 -std=gnu++17)。
  1. 定义源文件和头文件路径
    将源代码组织到变量中,或直接指定路径。
cmake 复制代码
set(SOURCES src/main.cpp src/foo.cpp)
set(INCLUDES include/)
  1. 生成可执行文件或库
    指定目标类型(可执行文件、静态库、动态库)。
cmake 复制代码
# 添加可执行文件
add_executable(MyApp ${SOURCES})

# 添加静态库
add_library(MyStaticLib STATIC src/foo.cpp src/bar.cpp)

# 添加动态库
add_library(MySharedLib SHARED src/foo.cpp src/bar.cpp)
  1. 设置目标的头文件路径
    将头文件目录添加到目标的构建路径中。
cmake 复制代码
target_include_directories(MyApp PRIVATE ${INCLUDES})
  1. 链接内部库
    链接外部依赖库或内部生成的库。
cmake 复制代码
target_link_libraries(MyApp PRIVATE MyLib)
  1. 查找外部库(可选)
    查找并使用外部库(如 Boost 或 OpenCV)。
cmake 复制代码
find_package(OpenCV REQUIRED)
target_link_libraries(MyApp PRIVATE ${OpenCV_LIBS})
  1. 安装规则
    指定生成的二进制文件、配置文件等的安装路径。
cmake 复制代码
install(TARGETS MyApp DESTINATION bin)
install(FILES config/settings.conf DESTINATION etc)
  • install() 定义安装文件的位置。
  • 常见用途:
    • 安装可执行文件到 bin
    • 安装库到 lib
    • 安装配置文件到 etc
  1. 测试支持(可选)
    启用单元测试功能。
cmake 复制代码
enable_testing()
add_test(NAME MyTest COMMAND MyApp --test)
  1. 子目录管理(可选)
    用于大型项目,将多个模块分割到不同的子目录。
cmake 复制代码
add_subdirectory(src/module1)
  • 对于大型项目,将代码分割到子目录中,通过 add_subdirectory() 引入。

子模块的 CMakeLists.txt

cmake 复制代码
add_library(Module1 STATIC module1.cpp)
target_include_directories(Module1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
  1. 添加自定义命令和目标(可选)
  • 添加自定义命令
cmake 复制代码
add_custom_command(
    OUTPUT generated.cpp
    COMMAND python generate.py > generated.cpp
    DEPENDS generate.py
)
  • 添加自定义目标
cmake 复制代码
add_custom_target(GenerateCode ALL DEPENDS generated.cpp)
  1. 使用变量和条件(动态配置)
  • 条件语句
cmake 复制代码
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    message("Debug build")
endif()
  • 变量替换
cmake 复制代码
set(VERSION "1.0.0")
message("Project version: ${VERSION}")

示例1:单模块(c++)

项目结构

css 复制代码
MyProject/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   ├── foo.cpp
├── include/
│   └── foo.h
└── config/
    └── settings.conf

代码文件

  • src/main.cpp:
c++ 复制代码
#include <iostream>
#include "foo.h"

int main() {
    std::cout << "Sum of 3 and 5 is: " << add(3, 5) << std::endl;
    return 0;
}
  • src/foo.cpp:
c++ 复制代码
#include "foo.h"

int add(int a, int b) {
    return a + b;
}
  • include/foo.h:
c++ 复制代码
#ifndef FOO_H
#define FOO_H

int add(int a, int b);

#endif
  • config/settings.conf:
txt 复制代码
# This is a placeholder configuration file

CMakelist.txt

cmake 复制代码
# 设置 CMake 最低版本
cmake_minimum_required(VERSION 3.10)

# 定义项目名称和语言
project(MyProject LANGUAGES CXX)

# 设置编译选项
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 定义源文件和头文件目录
set(SOURCES
    src/main.cpp
    src/foo.cpp
)

set(INCLUDES
    include/
)

# 添加可执行目标
add_executable(MyApp ${SOURCES})

# 配置头文件路径
target_include_directories(MyApp PRIVATE ${INCLUDES})

# 安装规则
install(TARGETS MyApp DESTINATION bin)
install(FILES config/settings.conf DESTINATION etc)

# 启用测试支持
enable_testing()
add_test(NAME RunTests COMMAND MyApp)

构建和运行

1. 创建构建目录

为了保持源文件清晰,推荐在源代码目录外创建构建目录:

bash 复制代码
mkdir build
cd build

2. 运行 CMake

使用 CMake 生成构建文件:

bash 复制代码
cmake ..

3. 编译项目

使用 CMake 的构建命令:

bash 复制代码
cmake --build .

4. 运行程序

bash 复制代码
./MyApp

5. 安装程序

将可执行文件和配置文件安装到指定目录:

bash 复制代码
cmake --install .

示例2:多模块(c++)

项目结构

css 复制代码
MyProject/
├── CMakeLists.txt         # 顶层 CMakeLists.txt
├── module1/               # 模块1
│   ├── CMakeLists.txt     # 模块1的 CMakeLists.txt
│   ├── module1.cpp
│   └── module1.h
├── module2/               # 模块2
│   ├── CMakeLists.txt     # 模块2的 CMakeLists.txt
│   ├── module2.cpp
│   └── module2.h
├── app/                   # 主程序
│   ├── CMakeLists.txt     # 主程序的 CMakeLists.txt
│   ├── main.cpp
└── build/                 # 构建目录

顶层 CMakeLists.txt

顶层的 CMakeLists.txt 文件负责整体项目的配置,包括引入各个模块、设置编译选项以及定义最终的构建目标。

cmake 复制代码
# 设置最低 CMake 版本
cmake_minimum_required(VERSION 3.10)

# 定义项目名称和语言
project(MyProject LANGUAGES CXX)

# 设置编译选项
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 添加子模块目录
add_subdirectory(module1)
add_subdirectory(module2)
add_subdirectory(app)

模块1的 CMakeLists.txt

模块1构建为一个静态库,提供对其他模块的功能支持。

cmake 复制代码
# 定义模块1的库
add_library(Module1 STATIC module1.cpp)

# 指定模块1的头文件路径
target_include_directories(Module1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

# 可选:设置特定的编译选项(如果模块需要)
target_compile_options(Module1 PRIVATE -Wall -Wextra)

模块2的 CMakeLists.txt

模块2构建为一个动态库,并依赖模块1。

cmake 复制代码
# 定义模块2的库
add_library(Module2 SHARED module2.cpp)

# 指定模块2的头文件路径
target_include_directories(Module2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

# 链接模块1
target_link_libraries(Module2 PUBLIC Module1)

主程序的 CMakeLists.txt

主程序依赖模块1和模块2,并最终生成可执行文件。

cmake 复制代码
# 定义主程序的可执行目标
add_executable(MyApp main.cpp)

# 链接模块1和模块2
target_link_libraries(MyApp PRIVATE Module1 Module2)

# 指定主程序的头文件路径(如果需要)
target_include_directories(MyApp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

示例代码

  • module1/module1.h
c++ 复制代码
#ifndef MODULE1_H
#define MODULE1_H

int add(int a, int b);

#endif
  • module1/module1.cpp
c++ 复制代码
#include "module1.h"

int add(int a, int b) {
    return a + b;
}
  • module2/module2.h
c++ 复制代码
#ifndef MODULE2_H
#define MODULE2_H

int multiply(int a, int b);

#endif
  • module2/module2.cpp
c++ 复制代码
#include "module2.h"
#include "module1.h"

int multiply(int a, int b) {
    return a * add(a, b);  // 使用模块1的功能
}
  • app/main.cpp
c++ 复制代码
#include <iostream>
#include "module1.h"
#include "module2.h"

int main() {
    int a = 3, b = 5;
    std::cout << "Add: " << add(a, b) << std::endl;
    std::cout << "Multiply: " << multiply(a, b) << std::endl;
    return 0;
}

功能扩展

  • 模块化管理 : 将子模块组织到不同目录,并通过 add_subdirectory() 引入。

  • 外部库集成 : 使用 find_package()target_link_libraries() 管理外部库。

  • 生成静态库 : 使用 add_library() 定义静态库目标,并链接到其他可执行文件。

  • 跨平台支持: CMake 支持跨平台构建(如 Makefile、Visual Studio 项目文件等)。

相关推荐
F永12 分钟前
C语言专题之文件操作(巨详细)
c语言·c++·学习·青少年编程
迈克柯里喵20 分钟前
CUDA算子手撕与面试指南
c++·算法·面试·职场和发展·性能优化·求职招聘·gpu算力
h^hh21 分钟前
6 C/C++输⼊输出(下)(未完续)
c++
chengf22326 分钟前
visual studio code配置windows c++运行调试环境
c++·windows·vscode
是阿建吖!1 小时前
【优选算法】字符串
c++·算法
杨德杰1 小时前
QT图像处理:QImage与QPixmap
c++·图像处理·qt·qimage
奶油泡芙9312 小时前
Making Anti-Palindromes制作反回文
c++
好好学习++3 小时前
【HF设计模式】03-装饰者模式
java·c++·设计模式·装饰器模式
黄亚磊113 小时前
C++ 中动态绑定、内存管理
c++