CmakeList教程
一、CmakeList介绍:
cmake 是一个跨平台、开源的构建系统。它是一个集软件构建、测试、打包于一身的软件。它使用与平台和编译器独立的配置文件来对软件编译过程进行控制。它会通过写的语句自动生成一个MakeFile,从而实现高效编译
二、CmakeList的常用指令
1.指定 cmake 的最小版本(可选)
cmake_minimum_required(VERSION 2.8)
这条语句规定了执行这个cmake的版本不能低于2.8,否则会报错,要求升级cmake版本
2.设置项目名称(可选)
project(HELLO)
这个命令不是强制性的,但最好都加上。它会引入两个变量 HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR,同时,cmake 自动定义了两个等价的变量 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR
3.添加生成的二进制文件
add_executable(name source…)
参数解释:
(1)name为需要生成的可执行文件名,也就是例如gcc demo.c -o demo,-o生成的demo就是这里的参数name,生成后就可以在可执行文件目录执行./demo运行
(2)第二个参数source为源文件,也就是.c或者.cpp文件,这个参数可以有多个,实现多个源文件一起编译
知道了上面三个指令,我们就可以写一个简单的CmakeList文件啦,先写一个小demo试试水~
在当前目录下,有一个function的文件夹,里面存放着一个叫fun.cpp的文件,文件中有一个add的函数,实现的是对输入的两数相加并返回。function文件夹外面存放着CmakeList.txt与我们的主函数demo.cpp。
现在编写CmakeList.txt:
cmake_minimum_required(VERSION 2.8)
project(HELLO)
add_executable(hello ./demo.cpp function/fun.cpp)
接着在CmakeList.txt所在的目录下执行
cmake .
就会生成几个文件以及文件夹,其中的MakeFile就是我们需要的
接着执行
make
就可以看到目录下出现了我们需要的可执行文件hello,运行./hello 可以看到成功打印出了结果15
4. 收集指定目录下的源码文件
很多时候我们构建一个二进制文件的时候,可能有几十或上百个.c或.cpp源码参与编译,如果我们在add_executable后一个个指定,效率非常低下,这时候就可以使用aux_source_directory
aux_source_directory(<dir> <variable>)
5.生成库文件
add_library(library_name [STATIC | SHARED | MODULE] EXCLUDE_FROM_ALL source_files)
library_name为要生成库的名称,例如生成一个名为libadd.so的动态库时,填add就行,lib与后面的.so会自动生成
STATIC表示生成静态库,SHARED表示生成动态库,MODULE表示生成一个模块,这是可选参数,但是最好根据需要生成的库类型都加上
使用 EXCLUDE_FROM_ALL 选项时,库目标将不会被自动构建,而是需要通过其他目标或手动指令进行显式构建。这个选项通常用于一些可选的或测试相关的库,它们不需要作为构建过程的一部分,但可以在需要时手动构建。这个也是可选参数
source_files为生成库的源文件
6. 指定连接库
这里有两种方式,第一种为link_directories与link_libraries搭配使用,还有一种是find_library与target_link_libraries搭配,更加推荐使用第二种,因为可读性更好,可以让我们更好的了解代码的依赖关系,并且可以确保在构建过程中只链接指定的库文件
第一种方式
link_directories(directory1 directory2 …)
添加库的查找路径
其中directory1、directory2等是你要添加的附加库文件目录。
需要注意的是link_directories默认路径在当前目录下,也就是说如果不提供绝对路径的话,只能在当前目录的子目录下找
link_libraries(library1 library2 …)
设置需要链接的文件
其中,library1、library2等参数是要链接的库文件名。
link_libraries可以把库链接到后续所有的目标中,库名以libpthread为例,可以写libpthread.so、pthread,都可以识别
第二种方式(推荐使用)
find_library(LIBRARY_PATH mylibrar PATHS /path/to/library/directory1 /path/to/library/directory2)
LIBRARY_PATH为一个变量,find_library会把找到的库存到这个变量中。可以供下面target_link_libraries使用
mylibrar为需要查找的库名称
PATHS为开始的字段不是必须的,它可以指定除当前目录下的其他路径,后面跟的都是需要查找的路径
target_link_libraries(target [item1] [item2] …)
其中 <target> 是要链接库文件的目标(例如可执行文件、静态库等),[item1]、[item2] 等是要链接到目标的库文件或目标。
item1的设置方式:
- 可以是写死的库,例如库名为libadd.so,可以写成target_link_libraries(demo add)
- 使用set设置变量的方式,set(LIBRARY_PATH /path/to/library),item1使用${LIBRARY_PATH}代替
- add_library(my_library STATIC my_library.cpp) 这种方式会生成一个新的库供使用
- 使用find_library设置的变量来链接
7.添加编译宏
很多时候我们的代码中存在类似#ifdef XXX 这样的编译宏,可以决定代码编译出不同功能或架构的代码,例如gcc编译时为gcc demo.c -DDEBUG,这时候如果代码中存在DEBUG这样的宏,就会编译被ARM宏包着的那段代码,设置宏与库一样,也有两种方式
第一种:add_definitions
add_definitions(-DXXX)
-D为必须的,XXX为需要设置的宏,这样设置会让下面所有构建的目标都带上这个宏参与编译,同样不推荐使用
第二种:target_compile_definitions (推荐使用)
target_compile_definitions(<target> <DEFINE1> <DEFINE2> …)
<target> 是要添加宏定义的目标(例如可执行文件、静态库等)
<scope> 是定义的作用范围(例如 PUBLIC、PRIVATE 或 INTERFACE)
<DEFINE1>、<DEFINE2> 等是要添加的宏定义。
需要注意的是,target_compile_definitions需要写在已经构建的目标后,例如target是demo这个可执行文件,那么在target前需要首先调用add_executable,在有demo这个目标后再再调用target_compile_definitions,否则会出现构建报错
8. 检查软件包
find_package( [version] # 指定要查找的库或者模块(版本号可选)
[EXACT] # 要求version完全匹配
[QUIET] # 无论找到与否,都不产生任何提示性消息
[REQUIRED] # 要求必须找到 xxx.cmake,找不到就提示报错
[[COMPONENTS] [components…]] 查找 Package 中的指定模块,COMPONENTS 跟的是一个列表,只要列表中任意一个模块没有被找到,则认为整个 Package 没有被找到,即 <PackageName>_FOUND 为 false(如果存在REQUIRED选项,则可以省略COMPONENTS关键字)
[OPTIONAL_COMPONENTS [components…]]
[MODULE] # 仅使用模块模式
[CONFIG|NO_MODULE] # 仅使用配置模式(两种写法是等效的)
[GLOBAL]
[NO_POLICY_SCOPE]
[BYPASS_PROVIDER]
)
find_package 一般都内置了一些变量:
_FOUND:可以判断是否找到对应的包或者模块
_INCLUDE_DIR:表示头文件目录(前提是包被找到才会被自动设置)
_LIBRARIES:表示库文件
以opencv为例
# 检索OpenCV库
find_package(OpenCV REQUIRED)add_executable(main src/main.cpp)
if(OpenCV_FOUND)# 引入头文件目录include_directories(${OpenCV_INCLUDE_DIRS})# 链接库文件target_link_libraries(main ${OpenCV_LIBRARIES})
else(OpenCV_FOUND)message(FATAL_ERROR "OpenCV library not found")
endif()
9.添加头文件搜索路径
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 …])
AFTER|BEFORE: 指定添加的搜索路径的位置,默认是 AFTER,即添加到已有的搜索路径之后。可以使用 BEFORE 将搜索路径添加到已有的搜索路径之前。
SYSTEM: 表示目录是系统目录,编译器会忽略其中的头文件的警告。可以不加
dir1 [dir2 …]: 要添加到搜索路径的目录列表。
10.构建带有层级目录的工程
如果我们想编译一个二进制文件,而这个二进制文件需要链接一个动态库,这个动态库也是需要实时编译出来给二进制使用的,这时候我们就可以使用add_subdirectory、add_dependencies来建构
add_subdirectory(subdirectory_path binary_output_path)
subdirectory_path为子目录的路径:指定要添加的子目录的路径。
binary_output_path为二进制输出目录:指定生成的二进制文件(库或可执行文件)的输出路径。
当我们执行cmake 时,它会进入指定的子目录中,执行该子目录下的 CMakeLists.txt 文件,并将生成的二进制文件输出到指定的二进制输出目录。
add_dependencies(target_name dependency_target_name)
target_name为目标名称:指定当前目标的名称。
dependency_target_name为依赖目标名称:指定当前目标所依赖的目标的名称。
当运行 cmake 构建项目时,如果当前目标依赖于另一个目标,则会先构建所依赖的目标,然后再构建当前目标。这可以确保在构建当前目标之前,其所依赖的目标已经被正确地构建完成。
下面是示例:
这是主目录与子目录的CMakeList内容
主目录cat CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(DEMO)include_directories(./include)# 添加可执行文件目标
add_executable(demo ./demo.c)# 将 demo 目标与 lib 目标链接
target_link_libraries(demo add)add_subdirectory(lib ./lib/)
add_dependencies(demo add)子目录:cat lib/CMakeLists.txt
cmake_minimum_required(VERSION 2.8project)
project(ADD)
add_library(add SHARED add.c)
下面是目录结构
.
├── CMakeLists.txt
├── demo.c
├── include
│ └── add.h
└── lib├── add.c└── CMakeLists.txt
10:30 上午 cmake cat demo.c
#include <stdio.h>
#include "add.h"int main()
{printf("%d\n",add(1,2));return 0;
}10:31 上午 cmake cat lib/add.c
int add(int a,int b)
{return a+b;
}
在主目录下执行cmake. && make,发现lib下生成了libadd.so,并且主目录下生成了我们需要的demo可执行文件,运行结果为3
11.设置二进制的生成路径
当我们执行add_executable后,通常需要把二进制放到指定的目录,这时候就可以通过install来实现,相当于操作了make install
install([Target | File | Directory | Script] my_executable DESTINATION you_path)
目标(Target):可以使用构建生成的目标名称作为第一个参数。
文件(File):可以使用文件路径作为第一个参数。
目录(Directory):可以使用目录路径作为第一个参数。
脚本(Script):可以使用脚本文件路径作为第一个参数。
示例:
install(TARGETS my_executable
DESTINATION bin)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/README.md
DESTINATION share)
示例中,my_executable 是一个已经定义的可执行目标,它将被安装到 bin 目录中。同时,项目根目录下的 README.md 文件将被安装到 share 目录中。
相关文章:

CmakeList教程
一、CmakeList介绍: cmake 是一个跨平台、开源的构建系统。它是一个集软件构建、测试、打包于一身的软件。它使用与平台和编译器独立的配置文件来对软件编译过程进行控制。它会通过写的语句自动生成一个MakeFile,从而实现高效编译 二、CmakeList的常用指令 1.指定…...

JavaWeb之JavaScript-Vue --黑马笔记
什么是JavaScript? JavaScript(简称:JS) 是一门跨平台、面向对象的脚本语言。是用来控制网页行为的,它能使网页可交互。 JavaScript 和 Java 是完全不同的语言,不论是概念还是设计。但是基础语法类似。 …...

pikachu_ssrf攻略
ssrf(curl): 打开pikachu靶场: http://127.0.0.1/pikachu-master/vul/ssrf/ssrf_curl.php?urlhttp://127.0.0.1/pikachu-master/vul/ssrf/ssrf_info/info1.php 发现URL地址最后面是info1.php 猜测一下有没有可能存在info2.php?…...
门面模式 Facade Pattern
门面模式 门面模式(Facade Pattern),也称之为外观模式,其核心为:外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用。 在软件开发领域有这样一句话:计算机科学领域…...

Linux基础指令大汇总
Linux的指令比较多,在学习的过程中要学会总结和归纳,同时结合实践多多使用,就像学数学一样,不是背过公式就等于掌握的,而是要知道在什么时候用,怎么用才是关键。 这篇文章会列举一系列常用的指令࿰…...

Unity配置表xlsx/xls打包后读取错误问题
前言 代码如下: //文本解析private void ParseText(){//打开文本 读FileStream stream File.Open(Application.streamingAssetsPath excelname, FileMode.Open, FileAccess.Read, FileShare.Read);//读取文件流IExcelDataReader excelRead ExcelReaderFactory…...

CSS基本知识总结
目录 一、CSS语法 二、CSS选择器 三、CSS样式表 1.外部样式表 2.内部样式表 3.内联样式 四、CSS背景 1.背景颜色:background-color 2.背景图片:background-image 3.背景大小:background-size 4.背景图片是否重复:backg…...

3dmax效果图渲染出现曝光怎么解决?
在使用3ds Max完成效果图渲染工作时,有时会遇到曝光过度的问题,这会使得渲染的图像出现光斑或者过亮,损害了效果的真实感和美观度。那么解决解决3dmax曝光问题呢?一起看看吧! 3dmax效果图渲染出现曝光解决方法 1、相机…...

科技、文化与旅游的融合创新:智慧文旅的未来之路
在当今社会,科技、文化与旅游的融合已经成为文旅产业转型升级的重要趋势。这种融合不仅有助于提升文旅产业的核心竞争力,更有助于推动产业的数字化转型和可持续发展。 本文将深入探讨科技、文化与旅游的融合创新,以及智慧文旅场景的解决方案…...

【第四天】蓝桥杯备战
题 1、求和2、天数3、最大缝隙 1、求和 https://www.lanqiao.cn/problems/1442/learning/ 解法:字符串方法的应用 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scann…...

计算机服务器中了halo勒索病毒怎么办,halo勒索病毒解密处理流程
计算机技术的发展与应用为企业的生产生活提供了坚实基础,但同时也为网络安全威胁制造了有利条件。近期,网络上的勒索病毒非常嚣张,给企业的计算机服务器带来严重威胁。近日,云天数据恢复中心接到山东某制造公司的求助,…...

基于LSTM的负荷预测,基于BILSTM的负荷预测,基于GRU的负荷预测,基于BIGRU的负荷预测,基于BP神经网络的负荷预测
目录 背影 摘要 代码和数据下载:基于LSTM的负荷预测,基于BILSTM的负荷预测,基于GRU的负荷预测,基于BIGRU的负荷预测,基于BP神经网络的负荷预测资源-CSDN文库 https://download.csdn.net/download/abc991835105/8876806…...
Linux命令-apachectl命令(Apache服务器前端控制工具)
apachectl命令 是Apache的Web服务器前端控制工具,用以启动、关闭和重新启动Web服务器进程。 语法 apachectl (参数)参数 configtest:检查设置文件中的语法是否正确;fullstatus:显示服务器完整的状态信息;graceful&a…...

5.【SpringBoot3】文件上传
1. 文件上传到本地 需求分析 在用户更换头像或发布文章时,需要携带一个图片的 url 地址,该 url 地址是当用户访问文件上传接口,将图片上传成功后,服务器返回的地址。所以,后台需要提供一个文件上传接口,用…...
网络安全态势感知平台概述
网络安全态势感知平台 文章目录 网络安全态势感知平台网络安全态势感知平台是什么一、网络安全态势感知平台是什么?二、网络安全态势感知很重要三、网络安全态势感知基础功能以某公司态势平台产品为例具体功能有以下: 网络安全态势感知平台是什么 网络安…...
PHP导出csv文件格式(最快捷的方式导出Excel文件)
php导出csv文件格式比起用PHPExcel插件导出excel文件速度快100倍! 以下是几种不同的PHP导出CSV文件的方法: 方法一(php://output方式用fputcsv函数格式化成csv数据): ----------------------------------------------…...
vue3常用代码
文章目录 监听路由vue3 警告Feature flag __VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined.mitt、project/inject 无效解决方案 菜鸟做项目时发现很多 vue3 常用的代码,所以来总结一下! 监听路由 import { useRoute } from "…...

【技术】SpringBoot 接口怎么加密解密
1. 介绍 在我们日常的Java开发中,免不了和其他系统的业务交互,或者微服务之间的接口调用 如果我们想保证数据传输的安全,对接口出参加密,入参解密。 但是不想写重复代码,我们可以提供一个通用starter,提…...

SqlAlchemy使用教程(六) -- ORM 表间关系的定义与CRUD操作
SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门 本章内容,稍微有…...
嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM平台编程第五天-kernel配置(物联技术666)
链接:https://pan.baidu.com/s/1eb94AaDM-cIZsbr929Isbw?pwd1688 提取码:1688 上午:linux内核介绍 徐登伟老师 下午:linux的配置 教学内容: 一、基本kernel的制作: 1、去开源社区下载原…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...