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 目录中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/243747.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iphone5s基带部分电源部分主主电源供电及

时序: 1.,基带电源的供电&#xff0c;基带电源也叫pmu。 首先时序图说电池提供供电&#xff0c;电池是J6接口&#xff0c;视频习惯把接口称之为座子。查U2_RF芯片&#xff0c;发现供电信号为PP_BATT_VCC_CONN&#xff0c;但是没查到跟电池座子有关系&#xff0c;电池座子写的是…

回溯算法篇-01:全排列

力扣46&#xff1a;全排列 题目分析 这道题属于上一篇——“回溯算法解题框架与思路”中的 “元素不重复不可复用” 那一类中的 排列类问题。 我们来回顾一下当时是怎么说的&#xff1a; 排列和组合的区别在于&#xff0c;排列对“顺序”有要求。比如 [1,2] 和 [2,1] 是两个不…

电脑磁盘格式化了怎么恢复里面文件?多个方法任你选

在日常生活中&#xff0c;我们可能会遇到由于误操作、病毒攻击等原因导致电脑磁盘被格式化的情况。一旦发生这种情况&#xff0c;我们可能会失去重要的文件&#xff0c;给工作和生活带来很大的困扰。但是&#xff0c;不必过于担心&#xff0c;本文将为您详细介绍如何在电脑磁盘…

Python 什么是点积注意力机制;点击注意力机制代码实现;Dot-Product Attention代码实战;超详细代码实现点积注意力

1.点积注意力机制简介 点积注意力机制&#xff08;Dot-Product Attention&#xff09;是一种常用的注意力机制之一&#xff0c;通常与Seq2Seq模型中的自注意力&#xff08;Self-Attention&#xff09;机制一起使用。它用于计算查询&#xff08;Query&#xff09;和键&#xff0…

Buildroot显示uboot logo

根据之前的开机现象&#xff0c;uboot部分没有开机logo 1、Makefile配置 查看一下u-boot/tools/Makefile是否都有如下配置 # Enable all the config-independent tools ifneq ($(HOST_TOOLS_ALL),) CONFIG_LCD_LOGO y CONFIG_CMD_LOADS y CONFIG_CMD_NET y CONFIG_XWAY_SW…

一.初识Linux 1-3操作系统概述Linux初识虚拟机介绍

目录 一.初识Linux 1.操作系统概述 计算机组成 硬件&#xff1a; 软件&#xff1a; 操作系统&#xff1a; 操作系统工作流程 操作系统作用 常见的操作系统 PC端&#xff1a; 移动端&#xff1a;&#xff08;掌上操作系统&#xff09; 一.初识Linux 2.Linux初识 linu…

分布式websocket即时通信(IM)系统保证消息可靠性【第八期】

b站上面本期视频版本&#xff0c;观看视频食用更佳&#xff01;点击即可跳转,找不到视频可以直接搜索我 目前叫 呆呆呆呆梦 目前已经写的文章有。并且有对应视频版本。 git项目地址 【IM即时通信系统&#xff08;企聊聊&#xff09;】点击可跳转 sprinboot单体项目升级成sprin…

Ubuntu用gparted重新分配空间

ubuntu系统使用过程中安装系统时预先留的空间不够使用怎么办&#xff1f; 这么办&#xff01; 首先 使用df -h 查看当前空间使用情况 已经分配的空间重新规划 &#xff1f; 先将已分配的空间中的多余空间分离出来&#xff1b; 假设我想将挂载点/home下的一部分空间分给挂载…

《WebKit 技术内幕》学习之八(1):硬件加速机制

《WebKit 技术内幕》之八&#xff08;1&#xff09;&#xff1a;硬件加速机制 1 硬件加速基础 1.1 概念 这里说的硬件加速技术是指使用GPU的硬件能力来帮助渲染网页&#xff0c;因为GPU的作用主要是用来绘制3D图形并且性能特别好&#xff0c;这是它的专长所在&#xff0c;它…

matlab模型变量一般说明,标定和显示量,以及产生a2l文件,自动填充a2l地址,并使用标定工具ati进行标定(推荐重要)

注意我是用的是matlab2019b 1&#xff0c;输入标定量&#xff0c;使用constant&#xff0c;用cal函数包裹 2&#xff0c;输出显示量&#xff0c;在划线上标注&#xff0c;然后用display函数包裹&#xff0c; 第一步和第二步完成以后&#xff0c;生产标定量a2l 3&#xff0c;输入…

常规二分查找中遇到的问题

以前我们写二分查找的时候&#xff0c;是这么写的&#xff1a; public static int binarySearch2(int []a,int target){int i0,ja.length-1;while(i<j){int mid(ij)/2;if(a[mid]target){return mid;}else if(a[mid]<target){imid1;}else {jmid-1;}}return -1;} 这么写&…

conda环境下OSError: We couldn‘t connect to ‘https://huggingface.co‘问题解决

1 问题描述 (dreamtalk) [rootlocalhost dreamtalk]# python inference_for_demo_video.py --wav_path data/audio/acknowledgement_english.m4a --style_clip_path data/style_clip/3DMM/M030_front_neutral_level1_001.mat --pose_path data/pose/RichardShelby_front_neutr…

【分布式技术专题】「分布式技术架构」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)

探索Tomcat技术架构设计模式的奥秘 Tomcat系统架构分析Tomcat 整体结构Tomcat总体结构图以 Service 作为“婚姻”1) Service 接口方法列表 2) StandardService 的类结构图方法列表 3) StandardService. SetContainer4) StandardService. addConnector 以 Server 为“居”1) Ser…

性能优化-OpenCL 介绍

「发表于知乎专栏《移动端算法优化》」 本文首先对 GPU 进行了概述&#xff0c;然后着重地对移动端的 GPU 进行了分析&#xff0c;随后我们又详细地介绍了 OpenCL 的背景知识和 OpenCL 的四大编程模型。希望能帮助大家更好地进行移动端高性能代码的开发。 &#x1f3ac;个人简介…

OpenCV——Scharr边缘检测

目录 一、Scharr算法1、算法概述2、主要函数 二、C代码三、python代码四、结果展示1、灰度图2、X方向一阶边缘2、Y方向一阶边缘3、整幅图像的一阶边缘 五、相关链接 OpenCV——Scharr边缘检测由CSDN点云侠原创&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&…

MODNet 剪枝再思考: 优化计算量的实验历程分享

目录 1 写在前面 2 模型分析 3 遇到问题 4 探索实验一 4.1 第一部分 4.2 第二部分 Error 1 Error 2 4.3 实验结果 ①参数量与计算量 ②模型大小 ③推理时延 5 探索实验二 5.1 LR Branch 5.2 HR Branch 5.2.1 初步分析 5.2.2 第一部分 enc2x 5.2.3 第二部分 en…

【算法分析与设计】二叉树的层序遍历

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xf…

2017年认证杯SPSSPRO杯数学建模B题(第二阶段)岁月的印记全过程文档及程序

2017年认证杯SPSSPRO杯数学建模 B题 岁月的印记 原题再现&#xff1a; 对同一个人来说&#xff0c;如果没有过改变面容的疾病、面部外伤或外科手术等经历&#xff0c;年轻和年老时的面容总有很大的相似性。人们在生活中也往往能够分辨出来两张不同年龄段的照片是不是同一个人…

3D应用开发工具HOOPS引领数字化工厂浪潮:制造业转型的关键角色!

随着科技的迅猛发展&#xff0c;制造业正经历着数字化转型的浪潮。在这一变革的前沿&#xff0c;Tech Soft 3D 的 HOOPS技术正扮演着关键的角色。 本文将深入研究HOOPS技术如何在数字化工作流程中发挥作用&#xff0c;以及它是如何引领制造业朝着更高效、智能的未来迈进的。 …

对读取的Excel文件数据进行拆分并发请求发送到后端服务器

首先&#xff0c;我们先回顾一下文件的读取操作&#xff1a; 本地读取Excel文件并进行数据压缩传递到服务器-CSDN博客 第一步&#xff1a;根据以上博客&#xff0c;我们将原先的handleFile方法&#xff0c;改为以下内容&#xff1a; const handleFile async(e) > {conso…