CMakeList学习笔记

news2024/9/22 5:41:23

设置项目:project

        

project(planning VERSION 1.0.0 LANGUAGES CXX) # 项目的名字 版本 1.1.0 编程语言 CXX

设置包含目录:include_directories、targer_include_directories

 

设置编译类型:add_executable、add_library

        add_executable(demo demo.cpp) #生成可执行文件
        add_library(common STATIC util.cpp) #生成静态库
        add_libary(common SHARED util.cpp) #生成动态库

add_library默认生成静态库,通过以上命令生成文件名称

在Linux平台:

        demo (可执行文件)

        libcommon.a (静态库)

        libcommon.so (动态库)

在window平台:

        demo.exe (可执行文件)

        common.lib (静态库)

        common.dll (动态库)

静态库与动态库的区别看Cmakelist知识总结-CSDN博客,这个博主讲的清楚。

总计如下:两者区别在链接阶段,静态链接器会将程序中使用到函数的代码从库文件中拷贝到应用程序中,即在内存中拷贝一份;动态链接在内存中只有一份,但仍需要共享库的支持。

设置变量的值 :set(变量名 变量值) 

        例:set(SRC_LIST main.cpp)  设置SRC_LIST的值为main.cpp

        例:set( CMAKE_BUILD_TYPE “Debug” ) 设置 cmake 编译模式

添加可执行文件或库:add_executable

        例:add_executable(my_program main.cpp)

        可结合set使用

        

添加依赖项和链接库:target_link_libraries和include_libraries

两个命令的作用对象不同:

include_libraries 命令用于指定项目中所有目标(包括可执行文件和库)的头文件搜索路径。

target_include_libraries 命令用于指定特定的目标(target)(可执行文件或库)的头文件搜索路径。

target_link_libraries(库文件名称/可执行文件名称 链接的库文件名称)

方法一:通过绝对路径指定链接库的位置

        例:target_link_libraries(MyTarget PUBLIC path1 path2 ...)

        PRIVATE:私有的,其他链接到my_program的库无法使用

        PUBLIC:公有的,其他链接到my_program的库可以使用

        命令中未指定任何限定符,默认情况下将应用 PUBLIC 限定符

方法二:通过相对路径指定链接库的位置

        target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.a)

        # ${CMAKE_CURRENT_SOURCE_DIR}/libs/mylibrary.lib 是相对于当前源代码目录的相对路径,指定了要链接的库文件位置

方法三(比较常用):使用自定义变量指定链接库的位置

        set(MY_LIBRARY_PATH /path/to/custom/lib)

        target_link_libraries(MyExecutable PRIVATE ${MY_LIBRARY_PATH}/libmylibrary.so)

方法四:使用 find_library() 命令查找链接库并且进行链接接操作

         #find_library() 命令用于在指定的路径 /path/to/custom/lib 中查找名为 mylibrary 的库文件libmylibrary.so,并将结果保存在变量 MY_LIBRARY 中。然后,可以使用该变量来链接库。
        find_library(MY_LIBRARY NAMES mylibrary PATHS /path/to/custom/lib)
        target_link_libraries(MyExecutable PRIVATE ${MY_LIBRARY})

link_libraries(library1 library2)

link_libraries 命令的语法是直接列出需要链接的库的名称,多个库之间用空格分隔。

更适用于一次性链接多个库,并且不需要精细的目标控制的情况。它适用于简单的项目或需要快速链接库的情况。

# 记住唯一一种就行,target_link_libraries万能链接,要写在add_executable之后,作用于指定的目标。

添加子目录 :add_subdirectory

        add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

查找指定依赖库文件:find_xxx

find_library() 用于查找库文件的路径 

# 用于在系统或用户指定的路径 /path/to/custom/lib 中查找指定的库文件 libmylibrary.so,并将结果保存在变量 MY_LIBRARY中
# 通常用于查找并指定需要链接的库文件的路径,以便在后续的链接阶段使用
# NAMES 可选参数
find_library(MY_LIBRARY NAMES mylibrary PATHS /path/to/custom/lib)
 
# 使用 MY_LIBRARY 作为默认的库文件名称进行查找,使用默认的系统搜索路径 /usr/lib, /usr/local/lib, /lib(/lib待验证)
find_library(MY_LIBRARY)

find_path() 用于查找头文件或文件夹的路径 

# 用于在系统或用户指定的路径 /path/to/include1 /path/to/include2 中查找指定的头文件 myheader.h(或文件夹),并将结果保存在变量HEADER_PATH中
#  通常用于查找所需的头文件路径,以便在编译阶段使用
find_path(HEADER_PATH myheader.h PATHS /path/to/include1 /path/to/include2)

find_package() 用于查找和导入外部包的配置信息。

find_package命令有两种工作模式,这两种工作模式的不同决定了其搜包路径的不同:

  • Module模式(默认工作模式

        # Module模式基本语法

        find_package(<package_name> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [COMPONENTS <component1> <component2> ...])

        <package_name> 必填参数;需要查找的包名,注意大小写。例如 OpenCV、Boost 等

version 可选参数;指定所需的版本号

常见选项包括:

        EXACT 可选参数;要求找到的包的版本与指定的版本完全匹配,必须完全匹配的版本而不是兼容版本

        QUIET 可选参数; 静默模式,不会显示详细的查找信息,表示如果查找失败,不会在屏幕进行输出

        REQUIRED 可选参数;要求找到指定的包,如果找不到会产生错误,停掉整个CMake。而如果不指定REQUIRED则CMake会继续执行,必须检查找到的包的版本是否和version兼容

        COMPONENTS 可选字段; 指定要加载的包的组件,如果有任何一个找不到就算失败

MODULE 可选字段;“如果Module模式查找失败则回退到Config模式进行查找”,但是假如设定了MODULE选项,那么就只在Module模式查找,如果Module模式下查找失败并不回落到Config模式查找。

  • Config模式(高级工作模式

        只有在find_package()中指定CONFIGNO_MODULE等关键字,或者Module模式查找失败后才会进入到Config模式

        # 其中具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由XXXConfig.cmake模块完成
        # 两种模式看起来似乎差不多,不过CMake默认采取Module模式,如果Module模式未找到库,才会采取Config模式。如果XXX_DIR路径下找不到XXXConfig.cmake文件,则会找/usr/local/lib/cmake/XXX/中的XXXConfig.cmake文件。总之,Config模式是一个备选策略。通常,库安装时会拷贝一份XXXConfig.cmake到系统目录中,因此在没有显式指定搜索路径时也可以顺利找到。
        # 具体查找顺序为:
        # 1、名为<PackageName>_DIR的CMake变量或环境变量路径默认为空。
        # 这个路径是非根目录路径,需要指定到<PackageName>Config.cmake文件所在目录才能找到。
        # 2、名为CMAKE_PREFIX_PATH、CMAKE_FRAMEWORK_PATH、CMAKE_APPBUNDLE_PATH的CMake变量或环境变量路径根目录,默认都为空。
        #注意如果你电脑中安装了ROS并配置好之后,你在终端执行echo $CMAKE_PREFIX_PATH会发现ROS会将CMAKE_PREFIX_PATH这个变量设置为ROS中的库的路径/opt/ros/noetic,意思是会首先查找ROS安装的库,如果恰好你在ROS中安装了OpenCV库,就会发现首先找到的是ROS中的OpenCV,而不是你自己安装到系统中的OpenCV。
        # 3、PATH环境变量路径根目录,默认为系统环境PATH环境变量值。
        # 其实这个路径才是Config模式大部分情况下能够查找到安装到系统中各种库的原因。
        # 这个路径的查找规则为:遍历PATH环境变量中的各路径,如果该路径如果以bin或sbin结尾,则自动回退到上一级目录得到根目录。

打印:message

message(打印内容)

message(STATUS "OpenCV library status:")

STATUS 是打印 -- 用来区分这是完整运行一条语句后的分割

例:find_package(Eigen3 REQUIRED)

        message(STATUS "Eigen3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}")

结果为:

        # 加了STATUS

        -- Eigen3_INCLUDE_DIR = /usr/include/eigen3

        # 没加STATUS

        Eigen3_INCLUDE_DIR = /usr/include/eigen3

添加编译选项

# 添加编译选项(add_definitions的功能和C/C++中的#define是一样的)
add_definitions(编译选项)
 
# 添加编译选项,包括使用C++11标准、启用调试信息和生成位置无关代码
add_compile_options(-std=c++11 -g -fPIC)

设定最低版本

        例:cmake_minimum_required(VERSION 3.4.0)

条件控制

 if…elseif…else…endif

逻辑判断和比较:
        if (expression):expression 不为空(0,N,NO,OFF,FALSE,NOTFOUND)时为真
        if (not exp):与上面相反
        if (var1 AND var2)
        if (var1 OR var2)
        if (COMMAND cmd):如果 cmd 确实是命令并可调用为真
        if (EXISTS dir) if (EXISTS file):如果目录或文件存在为真
        if (file1 ISNEWERTHAN file2):当 file1 比 file2 新,或 file1/file2 中有一个不存在时为真,文件名需使用全路径
        if (IS_DIRECTORY dir):当 dir 是目录时为真
        if (DEFINED var):如果变量被定义为真
        if (var MATCHES regex):给定的变量或者字符串能够匹配正则表达式 regex 时为真,此处 var 可以用 var 名,也可以用 ${var}
        if (string MATCHES regex)

数字比较:
        if (variable LESS number):LESS 小于
        if (string LESS number)
        if (variable GREATER number):GREATER 大于
        if (string GREATER number)
        if (variable EQUAL number):EQUAL 等于
        if (string EQUAL number)

字母表顺序比较:
        if (variable STRLESS string)
        if (string STRLESS string)
        if (variable STRGREATER string)
        if (string STRGREATER string)
        if (variable STREQUAL string)
        if (string STREQUAL string)

while ...endwhile 

        例:while(condition)
                ...
                endwhile

foreach...endforeach

        例:foreach(loop_var RANGE start stop [step])
                ...
                endforeach

        start 表示起始数,stop 表示终止数,step 表示步长

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VMware 上的 Debian Linux 虚拟机无法听到蓝牙耳机的声音解决方案

项目场景&#xff1a; 在Debian上安装QQ音乐&#xff0c;用来摸鱼 问题描述 在安装完QQ音乐后&#xff0c;发现虚拟机无法听到声音&#xff0c;音乐有在正常播放&#xff0c;但是蓝牙耳机没有听到任何声音&#xff1a; 原因分析&#xff1a; 感觉是虚拟机的声卡没有配置&…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 开源项目热度排行榜(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆Coding ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线评测,专栏文章质量平均 93 分 最新华为OD机试目录…

VScode 批量操作

VScode 批量操作 批量修改 按住 alt/option 键&#xff0c; 选择需要批量操作的位置 如果是多行&#xff0c;则按住 altshift 键 可以直接操作 但是有时候比如变量命名&#xff0c;可能需要递增操作的命名 需要下载插件 Increment Selection 按照1的方法多选光标之后&am…

Qemu virtio-blk 后端驱动开发 - PureFlash对接

本文以PureFlash为例&#xff0c;介绍了如何将一个新的存储类型对接到qemu虚拟化平台下&#xff0c;为虚机提供存储能力。 关于virtio-blk以及其工作原理这里就不介绍了&#xff0c;网上有很多分析的文章。总之就是如果我们想给虚机提供一种新的存储类型&#xff08;不同于标准…

解决显存不足问题:深度学习中的 Batch Size 调整【模型训练】

解决显存不足问题&#xff1a;深度学习中的 Batch Size 调整 在深度学习训练中&#xff0c;显存不足是一个常见的问题&#xff0c;特别是在笔记本等显存有限的设备上。本文将解释什么是 Batch Size&#xff0c;为什么调整 Batch Size 可以缓解显存不足的问题&#xff0c;以及调…

大数据-48 Redis 通信协议原理RESP 事件处理机制原理 文件事件 时间事件 Reactor多路复用

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

鸿蒙开发仓颉语言【Hyperion: 一个支持自定义编解码器的TCP通信框架】组件

Hyperion: 一个支持自定义编解码器的TCP通信框架 特性 支持自定义编解码器高效的ByteBuffer实现&#xff0c;降低请求处理过程中数据拷贝自带连接池支持&#xff0c;支持连接重建、连接空闲超时易于扩展&#xff0c;可以积木式添加IoFilter处理入栈、出栈消息 组件 hyperio…

c++ 求解质因数

定义 这里先来了解几个定义&#xff08;如已了解&#xff0c;可直接看下一个板块&#xff09; 因数&#xff1a;又称为约数&#xff0c;如果整数a除以整数b&#xff08;b0&#xff09;的商正好是是整数而没有余数&#xff0c;我们就说b是a的因数 质数&#xff1a;又称为素数…

我在Vscode学Java泛型(泛型设计、擦除、通配符)

Java泛型 一、泛型 Generics的意义1.1 在没有泛型的时候&#xff0c;集合如何存储数据1.2 引入泛型的好处1.3 注意事项1.3.1 泛型不支持基本数据类型1.3.2 当泛型指定类型&#xff0c;传递数据时可传入该类及其子类类型1.3.3 如果不写泛型&#xff0c;类型默认是Object 二、泛型…

Python酷库之旅-第三方库Pandas(044)

目录 一、用法精讲 151、pandas.Series.any方法 151-1、语法 151-2、参数 151-3、功能 151-4、返回值 151-5、说明 151-6、用法 151-6-1、数据准备 151-6-2、代码示例 151-6-3、结果输出 152、pandas.Series.autocorr方法 152-1、语法 152-2、参数 152-3、功能 …

c++树(三)重心

目录 重心的基础概念 定义&#xff1a;使最大子树大小最小的点叫做树的重心 树的重心求解方式 例题&#xff1a; 重心的性质 性质1&#xff1a;重心点的最大子树大小不大于整棵树大小的一半。 性质1证明&#xff1a; 性质1的常用推导 推导1&#xff1a; 推导2&#x…

《Milvus Cloud向量数据库指南》——开源许可证的范围:深入解析与选择指南

在开源软件的广阔天地中,开源许可证作为连接开发者与用户之间的重要法律桥梁,其类型多样且各具特色。每一种许可证都精心设计了特定的权限、限制和要求,旨在保护创作者的权益,同时促进软件的创新与共享。对于开发者和用户而言,深入理解并恰当选择适合的开源许可证,是确保…

C++树(四)二叉树

目录 二叉树的定义&#xff1a; 二叉树相关术语&#xff1a; 二叉树的概念与性质 二叉树基本性质 二叉树的节点数量 满二叉树概念&#xff1a; 完全二叉树概念&#xff1a; 完全二叉树性质&#xff1a; 二叉树的存储 二叉树的遍历 在此基础上&#xff0c;二叉树的遍历…

mac下010editor的配置文件路径

1.打开访达&#xff0c;点击前往&#xff0c;输入~/.config 2.打开这个文件夹 把里面的 010 Editor.ini 文件删除即可&#xff0c;重新安装010 Editor即可

有没有下面符合以下条件的电子时钟的代码

&#x1f3c6;本文收录于《CSDN问答解答》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&…

【React1】React概述、基本使用、脚手架、JSX、组件

文章目录 1. React基础1.1 React 概述1.1.1 什么是React1.1.2 React 的特点声明式基于组件学习一次,随处使用1.2 React 的基本使用1.2.1 React的安装1.2.2 React的使用1.2.3 React常用方法说明React.createElement()ReactDOM.render()1.3 React 脚手架的使用1.3.1 React 脚手架…

PostgreSQL使用(四)——数据查询

说明&#xff1a;对于一门SQL语言&#xff0c;数据查询是我们非常常用的&#xff0c;也是SQL语言中非常大的一块。本文介绍PostgreSQL使用中的数据查询&#xff0c;如有一张表&#xff0c;内容如下&#xff1a; 简单查询 --- 1.查询某张表的全部数据 select * from tb_student…

MSPM0G3507基于keil无法烧录的解决方法

在学习M0的板卡过程中&#xff0c;遇到了诸多玄学问题。网上的教学大多基于CCS开发&#xff0c;对keil的教学几乎没有。 一开始我以为这个问题是没添加这个&#xff0c;但其实并非如此 在群里的网友说的清除flash&#xff0c;插拔USB,这些都不管用,后面也发现先在CCS烧录一遍&…

前端开发知识(二)-css

<head> <style> div{ } </style> </head> div是布局标签&#xff0c; 一般放在head标签内&#xff0c;最下部。 若直接在在.css文件中写css,文件中&#xff0c;直接写就行&#xff0c;如下所示。 div{ }

VLLM代码解读 | VLLM Hack 3

在上一期&#xff0c;我们看到了多个输入如何被封装&#xff0c;然后被塞入llm_engine中&#xff0c;接下来&#xff0c;通过_run_engine,我们要进行输入的处理了。 def _run_engine(self, *, use_tqdm: bool) -> List[Union[RequestOutput, EmbeddingRequestOutput]]:# Ini…