【C++开发】CMake构建工具

目录

1,CMake介绍

2,配置文件CMakeLists.txt


1,CMake介绍

CMake 是一个开源的、跨平台的自动化构建系统生成工具,广泛用于 C 和 C++ 项目的构建管理。它使用一个名为 CMakeLists.txt 的配置文件来定义如何构建项目,并能够生成适用于不同编译器和操作系统的构建文件(如 Makefile、Visual Studio项目等),从而实现跨平台的一致性构建。

2,配置文件CMakeLists.txt

CMakeLists.txt 是 CMake 的核心配置文件,存在于每个需要构建的目录中。配置指令常用的如下:

1,构建项目程序的简单配置指令。

# 声明cmake使用的最低版本
cmake_minimum_required(VERSION 3.20)

# 构建项目的信息。下面对应名称、版本、描述、项目使用的语言
project(TestProject VERSION 1.1.1 DESCRIPTION "This is a TestProject" LANGUAGES CXX)

# 设置使用C++11版本(14, 17, 20版本类似)
set(CMAKE_CXX_STANDARD 11)

# 指定头文件的搜索路径:有target_include_directories和include_directories
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)

# CMAKE_CURRENT_SOURCE_DI宏是表示CMakeLists.txt的路径

2,set() 和 file() 设置变量的值。它们用于将一个或多个值组合起来赋给自定义的变量。用途如下:

**# 指定编译的源文件(头文件不需要加入,cmake它不会让它参与编译)

方法一:指定有限个参与编译。自定义SRC保存找到源文件路径的变量名

set(SRC fun1.cpp fun2.cpp fun3.cpp main.cpp)**

# 方法二:将指定目录下的所有源文件参与编译(目录下非递归式,即子目录不包含)

# PROJECT_SOURCE_DIR宏本质是cmake后面根的路径名

**# 自定义SRC保存找到的所有源文件路径的变量名
aux_source_directories({PROJECT_SOURCE_DIR}/\*.cpp {PROJECT_SOURCE_DIR}/*.cc SRC)

方法三:目前最流行的file。GLOB 表示非递归查找;GLOB_RECURSE递归式查找

file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp *.cc)**

# 指定库的存放路径。其实这里就是把指定的传输路径的字符串设置到定义库路径的宏中

# CMAKE_LIBRARY_OUTPUT_DIRECTORY动态库(.so,.dll)输出路径

**# CMAKE_ARCHIVE_OUTPUT_DIRECTORY静态库(.a, .lib)输出路径

这里可以使用debug或release构建方式,即CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG 或 CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/lib) # 将生成的动态库传输到lib下 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/lib) # 将生成的静态库传输到lib下**

# 指定可执行文件的输出路径。CMAKE_RUNTIME_OUTPUT_DIRECTORY(现代写法)和EXECUTABLE_OUTPUT_PATH(过时写法)
set(EXECUTABLE_OUTPUT_PATH /root/Test)

#可选:分别设置 Debug/Release 输出路径
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG /root/Test/debug)
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE /root/Test/release)

# 拼接字符串。将字符串赋给tmp和tmp1

set(tmp Hello Cmake)
set(tmp1 {tmp} {CMAKE_CURRENT_SOURCE_DIR})

3,动静态库的相关指令配置。

# 把指定的源文件编译成一个库(静态库或动态库)
file(GLOB LIBS {CMAKE_CURRENT_SOURCE_DIR}/\*.cpp) add_library(myshared SHARED {LIBS}) # 定义动态库
add_library(mystatic STATIC ${LIBS}) # 定义静态库

# 指定库的存放路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/lib) # 将生成的动态库传输到lib下 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/lib) # 将生成的静态库传输到lib下

# 说明程序链接时,自定义库的路径
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib) # 指定自定义库的路径

# 链接自定义生成的库
# 方法一:古老用法。链接静态库时可以使用;链接动态库不推荐

link_libraries(mystatic) # 链接库mystatic

# 方法二:新用法。非常推荐。
target_link_libraries(test PRIVATE myshared) # 可执行程序test链接库myshared

4,可执行文件的相关指令配置。

# 指定可执行文件的输出路径。CMAKE_RUNTIME_OUTPUT_DIRECTORY(现代写法)和EXECUTABLE_OUTPUT_PATH(过时写法)
set(EXECUTABLE_OUTPUT_PATH /root/Test)

# 指定编译的源文件(头文件不需要加入,cmake它不会让它参与编译)
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp *.cc)

**# 通过源文件列表生成可执行文件目标,即告诉CMake把哪些源文件编译成一个可执行程序
add_executable(test ${SRC})

add_executable(test fun1.cpp fun2.cpp fun3.cpp main.cpp)**

5,message 输出日志。该命令用于在终端输出变量,以提示用户信息。

语法:

message([<mode>] "message text" ...)

参数说明:

<mode>(可选):指定消息的类型或行为。
"message text":要输出的消息内容,可以包含变量 ${VAR}。

消息类型(Mode)取值如下:

STATUS:输出状态信息(用 -- 前缀显示),不会中断构建。
WARNING:输出警告信息,不会中断构建,但会高亮显示。
SEND_ERROR:输出错误信息,并中断当前cmake构建阶段,但继续生成项目。
FATAL_ERROR:输出错误信息,并完全中断构建和生成的过程。

样例:
set(tmp Hello Cmake)
set(tmp1 {tmp} {CMAKE_CURRENT_SOURCE_DIR})
message(STATUS {tmp}) message(STATUS {tmp1})

message(STATUS "************************************")

6,list处理列表。列表是用分号 ";" 分隔的一系列字符串,尽管你可能会看到使用空格分隔的值,在内部它们会被转换成分号分隔的形式。该命令提供了一系列的操作来操作这些列表,包括添加、删除、搜索和排序等。这里说明添加和删除。

语法:

list(APPEND <list> [<element> ...]) # 将一个或多个元素追加到指定的列表末尾

list(REMOVE_ITEM <list> [<value> ...]) # 从列表中移除所有与给定值匹配的项

样例:
set(MY_LIST a b c) # 初始化一个列表MY_LIST
list(APPEND MY_LIST d e f) # 添加新元素到列表末尾
message("MY_LIST: ${MY_LIST}") # 输出结果MY_LIST: a;b;c;d;e;f

set(MY_LIST a b c b d b) # 初始化一个包含重复项的列表
list(REMOVE_ITEM MY_LIST b) # 移除所有等于 "b" 的项
message("MY_LIST: ${MY_LIST}") # 输出结果MY_LIST: a;c;d

list还有很多个模式运用,这里不做过多说明。明白原理后,在所需要的场景下自行查找即可

7,link_libraries() 和 target_link_libraries()。这两种指令都是用于链接指定的库。link_libraries()命令设置的是全局链接库,会影响后续定义的所有目标。

**link_libraries(mylib)

后续所有生成的可执行文件都会链接mylib库**

add_executable(myapp main.cpp)

target_link_libraries() 是现代 CMake 中用于为特定目标(可执行文件或库)指定链接库的方式。

语法:

target_link_libraries(<target-name> [PRIVATE|PUBLIC|INTERFACE] <library> ...)

参数说明:

<target-name>:之前通过 add_executable() 或 add_library() 定义的目标名称。
PRIVATE:仅当前目标使用此库。

PUBLIC:不仅当前目标使用此库,而且任何依赖于这个目标的其他目标也会继承这个 库。

INTERFACE:当前目标本身不需要这些库,但依赖它的目标需要。这点理解若困难可 直接看下面样例。

<library>:链接的库文件。

样例1:

// 可指定程序链接库

target_link_libraries(myapp PRIVATE /path/to/libmylib.a) # 静态库 target_link_libraries(myapp PRIVATE /path/to/libmylib.so) # 动态库

样例2:

# libA 库需要链接 libB,后面的目标不会链接 libB

add_library(libA STATIC a.cpp)

target_link_libraries(libA PRIVATE libB)

# libD 库需要链接 libE,并且它的使用者也需要链接 libE

add_library(libD STATIC d.cpp)

target_link_libraries(libD PUBLIC libE)

# libF 库的使用者需要链接 libG,但 libF 自身并不直接使用 libG

add_library(libF INTERFACE)

target_link_libraries(libF INTERFACE libG)

注意:可执行程序链接库的顺序是先生成可执行程序,在进行动静态库的链接。

8,add_subdirectory 嵌套 CMakeLists.txt 文件。add_subdirectory 用于向构建过程添加一个子目录。这个子目录应该包含自己的 CMakeLists.txt 文件,定义了如何编译该目录下的源代码以及如何将其链接到其他目标(如可执行文件或库,大多数情况是库文件)。

语法:

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

参数说明:

**source_dir:指定要添加的子目录路径,可以是相对路径也可以是绝对路径。

binary_dir\]可选参数:指定输出文件存放的目录。如果未指定,则默认为 source_dir 对应的构建目录。 \[EXCLUDE_FROM_ALL\]可选参数:暂时不做说明。**

假设你有一个项目结构如下:

/my_project
|------ CMakeLists.txt
|------ /src
| |------ main.cpp
|------ /lib
|------ CMakeLists.txt
|------ /math
|------ math.cpp
|------ math.h

/my_project 目录是项目的根目录,其中包含一个顶级 CMakeLists.txt 文件。/src 目录包含了项目的主源文件(如 main.cpp),而 /lib/math 则包含了一个数学库的实现(math.cpp 和 math.h)。

项目根目录下的 CMakeLists.txt 文件内容如下:

cmake_minimum_required(VERSION 3.10)

# 设置项目名称
project(MyProject)

# 添加 lib 目录中的子项目
add_subdirectory(lib)

# 添加 src 目录中的可执行文件
add_subdirectory(src)

lib 目录下的 CMakeLists.txt 文件内容如下:

**# 定义一个静态库
add_library(MathLib STATIC math/math.cpp)

包含头文件路径

target_include_directories(MathLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/math)**

在 src 目录下,这里可以创建另一个 CMakeLists.txt 文件来编译可执行文件,并链接之前定义的 MathLib 库:

**# 添加可执行文件
add_executable(MyExecutable main.cpp)

链接 MathLib 库

target_link_libraries(MyExecutable MathLib)**

通过这种方式,add_subdirectory 命令使得能够轻松地组织和管理复杂的项目结构。每个子目录可以有自己的 CMakeLists.txt 文件,从而让项目更加模块化和易于维护。


最后说明下Qt Creator中的CMake配置,Qt Creator环境中CMake配置

相关推荐
老神在在00128 分钟前
SpringMVC1
java·前端·学习·spring
程序猿小D1 小时前
[附源码+数据库+毕业论文+开题报告]基于Spring+MyBatis+MySQL+Maven+jsp实现的车辆运输管理系统,推荐!
java·数据库·mysql·spring·毕业设计·开题报告·车辆运输管理系统
Bug退退退1232 小时前
RabbitMQ 高级特性之消息分发
java·分布式·spring·rabbitmq
赵英英俊3 小时前
Python day15
开发语言·python
Jack_hrx3 小时前
基于 Drools 的规则引擎性能调优实践:架构、缓存与编译优化全解析
java·性能优化·规则引擎·drools·规则编译
zxsd_xyz4 小时前
基于LabVIEW与Python混合编程的变声器设计与实现
开发语言·python·labview
遇见尚硅谷4 小时前
C语言:20250712笔记
c语言·开发语言·数据结构
☞下凡☜4 小时前
C语言(20250711)
linux·c语言·开发语言
二进制person4 小时前
数据结构--准备知识
java·开发语言·数据结构
半梦半醒*4 小时前
H3CNE综合实验之机器人
java·开发语言·网络