当前位置: 首页 > news >正文

CMake⼯程指南-3

1.静态库(编译-链接-引⽤)

上⼀节,我们⽤⼀个简单的hello_world程序演⽰了如何使⽤cmake来构建⼀个⼆进制程序。这⼀
节,我们继续和⼤家⼀起学习,如何使⽤cmake⽣成和使⽤⼀个项⽬内部的静态库。
在最佳⼯程实践⾥,⼯程规模⼤⼀点的⼯程中,我们往往会把⼀些⽐较独⽴的功能(⽐如如⽹
络、数据库、算法,或者⼀些基础组件,redis-client, mysql-client,jsoncpp, libcurl)封装为独⽴
的库,由不同的团队来维护,在公司或者开源社区共享,达到复⽤⽬的。
本节我们把加法和减法函数2个函数 封装成⼀个MyMath的数学静态库,并在main⼆进制⾥引⽤我
们静态库⾥的加法和减法函数,来演⽰下如何使⽤CMake来管理这⼀场景。

2.单步实操

我们创建⼀个新的⼯程 my_math 来演⽰如何⽣成静态库。
首先我们预览一下工程的结构图(写完以后的),接下来我们一部一部去编写!

Step 1:新建⽂件-CMakeLists.txt

# 1 设置最低版本号
cmake_minimum_required(VERSION 3.18)
# 2 设置项⽬名称
project(TestMyMath
LANGUAGES CXX
)
# 3 添加⽬录层级
add_subdirectory(my_lib)
add_subdirectory(app)

Step 2:新建⽂件-my_lib/CMakeLists.txt

# 1 收集库的源代码
file(GLOB SRC_LISTS "src/*.cpp")
# 2 添加构建⽬标
add_library(MyMath STATIC ${SRC_LISTS})
# 3 设置库的使⽤要求
target_include_directories(MyMath
PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include
)
# 4 修改默认的输出路径
set_target_properties(MyMath PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
)

Step 3:新建⽂件-app/CMakeLists.txt

# 1 搜集⽂件列表
file(GLOB SRC_LISTS "*.cpp")
# 2 添加构建⽬标
add_executable(main ${SRC_LISTS})
# 3 添加依赖库列表
target_link_libraries(main PRIVATE MyMath)
# 4 设置输出路径
set_target_properties(main PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
# 5 打印库⽂件相对main的相对路径
add_custom_command(
TARGET main POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"$<PATH:RELATIVE_PATH,$<TARGET_FILE:MyMath>,${CMAKE_CURRENT_BINARY_DIR}>"
COMMENT "获取静态库的输出路径"
)

Step 4:新建⽂件-add.cpp

#include "math.h"
int add(int a, int b) {
return a + b;
}

Step 5:新建⽂件-sub.cpp

#include "math.h"
int sub(int a, int b) {
return a - b;
}

Step 6:新建⽂件-math.h

int add(int a, int b);
int sub(int a, int b);

Step 7:新建⽂件-main.cpp

#include <iostream>
#include "math.h"
int main()
{
std::cout << "3 + 4 = " << add(3, 4) << std::endl;
std::cout << "3 - 4 = " << sub(3, 4) << std::endl;
}

Step 8:运⾏cmake

mkdir build && cd build
cmake ../

Step 9:编译链接

cmake --build .

Step 10:运⾏

./app/main

3.CMake的 3⼤核⼼-⽬标-属性-API

3.1 ⽬标-Target

目标的种类

3.2 属性-Property

属性的种类

属性的作⽤域与传播范围(main ---->curl )

3.3 操作⽬标和属性的核⼼API

3.3.1 add_library

函数作⽤:
添加⼀个静态库或者动态库⽬标,让cmake 从指定的⽂件列表⽣成。
基本形式
add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [<source>...])
默认情况下,将在与调⽤命令的源树⽬录相对应的构建树⽬录中创建库⽂件。 可以使⽤
ARCHIVE_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY
RUNTIME_OUTPUT_DIRECTORY ⽬标属性修改默认的输出路径。
 参数解释:

3.3.2 target_include_directories

函数作⽤:
设置⽬标在开发和发布阶段的头⽂件搜索⽬录,可以传递性传播给下游的使⽤⽅。
基本形式
target_include_directories(<target>
[SYSTEM] # path 告诉编译器“这些是系统头⽂件”,GCC/Clang 会⽤ -isystem
⽽⾮ -I,从⽽ 抑制第三⽅头引出的警告。
[BEFORE] # 把路径插到已有列表最前⾯
<INTERFACE|PUBLIC|PRIVATE> path1 [path2 ...]
[<INTERFACE|PUBLIC|PRIVATE> pathN ...] …
)
参数解释:

3..3.3 target_link_libraries

函数作⽤:
设置⼆进制⽬标的依赖库列表,相当于使⽤通⽤的set属性设置函数设置了LINK_LIBRARIES或者
INTERFACE_LINK_LIBRARIES这个属性,在cmake源代码⾥这2个属性是2个 vector<string> 成员。最终以-l的形式出现在gcc参数⾥。
target_link_libraries(<target>
<PRIVATE|PUBLIC|INTERFACE> <item>...
[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
set_target_properties(<target> PROPERTIES
LINK_LIBRARIES|INTERFACE_LINK_LIBRARIES <item>...
)
PRIVATE 关键字:相当于使⽤set_target_properties 设置了LINK_LIBRARIES属性,设置的库列表 只 会写进⽬标的LINK_LIBRARIES列表⾥。
INTERFACE 关键字:相当于使⽤set_target_properties 设置了INTERFACE_LINK_LIBRARIES,只会 写进⽬标的INTERFACE_LINK_LIBARIERS列表⾥。
PUBLIC 关键字设置的列表会同时写进LINK_LIBRARIES和INTERFACE_LINK_LIBRARIES⾥。
INTERFACE_LINK_LIBRARIES 列表出现的库会被传播给这个⽬标的使⽤⽅。
通过 target_link_libraries最终是通过gcc 的-l 选项传递给链接器的。

3.3.4 set_target_properties和 get_target_properties

函数作⽤:

设置/查询 ⽬标(如可执⾏⽂件、库)的各种属性,控制编译、链接、安装等⾏为

基本形式

set_target_properties(<target1> <target2> ...
PROPERTIES <prop1> <value1>
<prop2> <value2> ...)
get_target_property(<variable> <target> <property>)

3.3.5 add_subdirectory

函数作⽤:
添加⼦⽬录到构建树,cmake会⾃动进⼊到源码树⼦⽬录,执⾏位于⼦⽬录⾥的CMakeLists.txt⽂
件。
基本形式
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL] [SYSTEM])
关键⾏为
1. 处理顺序
CMake 会⽴即处理 source_dir 中的 CMakeLists.txt,当前⽂件的处理会暂停,直到⼦⽬录
处理完毕,在继续处理当前⽂件add_subdirectory之后的命令。
2. 路径解析
source_dir 相对路径:相对于当前 CMakeLists.txt ⽂件所在⽬录。
binary_dir 相对路径:相对于当前构建⽬录(不指定,则使⽤ source_dir )。
3. 变量作⽤域
⼦⽬录中定义的变量默认是局部的,不会影响⽗⽬录。
可通过 set(xxx PARENT_SCOPE) 将变量传递到⽗⽬录。
缓存变量是全局的,⼦⽬录⾥设置的缓存变量,⽗⽬录也可以获取到
4. CMake 在当前上下⽂执⾏完add_subdirectory命令,进⼊到⼦⽬录之后,在开始执⾏
CMakeLists.txt时会修改的内置变量:

3.3.6 file

函数作⽤:
查看⽬录下的所有⽂件,如果匹配规则,则添加⽂件名字到⽂件列表中,是否需要递归,需要显
⽰指定。
基本形式
file(GLOB|GLOB_RECURSE <variable> [LIST_DIRECTORIES true|false]
[RELATIVE <path>] [CONFIGURE_DEPENDS] <globbing-expressions>...
)

至此,本节内容到此结束,感谢观看!

http://www.dtcms.com/a/360529.html

相关文章:

  • 手写MyBatis第45弹:动态代理在MyBatis插件内核是如何织入扩展逻辑的
  • Linux软件升级方法总结
  • CF每日3题(1500-1600)
  • 在windows系统下安装Docker Desktop后迁移镜像位置
  • 科普:requirements.txt 和 environment.yml
  • 【系统分析师】高分论文:论面向服务方法在信息系统开发中的应用
  • 一些八股总结
  • Langflow Agents 技术深度分析
  • OpenCL C 平台与设备
  • (附源码)基于Vue的教师档案管理系统的设计与实现
  • 【开题答辩全过程】以 基于Java的网络购物平台设计与实现为例,包含答辩的问题和答案
  • LeetCode 3665. 统计镜子反射路径数目
  • react-virtualized React 应用中高效渲染大型列表和表格数据的库
  • Synchronized 概述
  • 【LeetCode】18、四数之和
  • LeeCode 37. 解数独
  • 并发编程——10 CyclicBarrier的源码分析
  • Selenium 等待机制:编写稳定可靠的自动化脚本
  • spi总线
  • 7.2elementplus的表单布局与模式
  • MCP SDK 学习二
  • 艾体宝案例 | 数据驱动破局:DOMO 如何重塑宠物零售门店的生存法则
  • Python 2025:AI代理、Rust与异步编程的新时代
  • 张柏芝亮相林家谦演唱会 再次演绎《任何天气》
  • Spring MVC 九大组件源码深度剖析(五):HandlerAdapter - 处理器的执行引擎
  • 三、环境搭建之Docker安装mysql
  • 一、计算机系统知识
  • Springcloud-----Nacos
  • 【influxdb】InfluxDB 2.x 线性写入详解
  • 层次分析法