首页 > 其他分享 >Cmake使用

Cmake使用

时间:2023-04-23 22:44:07浏览次数:46  
标签:CMAKE NO 路径 Cmake 使用 PATH cmake Config

[待更新中]

find_package用法

必读:

注意,要想在自己的项目中使用find_package命令查找包的前提是:

包的开发者用CMake配置好了这个包,并提供了<PackageName>Config.cmakeFind<PackageName>.cmake的配置文件。

有2种搜包模式 ModuleConfig模式

默认采用 Module模式,找不到的时候转为 Config模式

Module模式

语法

find_package(<packageName> [version] [EXACT] [QUIET] [MODULE]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [NO_POLICY_SCOPE])

Module模式下会去查找名为Find<PackageName>.cmake的配置文件,查找路径为:

# Module模式只有两个查找路径:CMAKE_MODULE_PATH和CMake安装路径下的Modules目录,即
CMAKE_MODULE_PATH  # 默认为空,可以利用set命令赋值。
CMAKE_ROOT # 即cmake安装路径的根目录

Config模式

语法(Config模式的参数更多,也更复杂,但实际在使用过程中我们并不会用到所有参数,大部分参数都是可选的)

find_package(<package> [version] [EXACT] [QUIET]
             [REQUIRED] [[COMPONENTS] [components...]]
             [CONFIG|NO_MODULE]
             [NO_POLICY_SCOPE]
             [NAMES name1 [name2 ...]]
             [CONFIGS config1 [config2 ...]]
             [HINTS path1 [path2 ... ]]
             [PATHS path1 [path2 ... ]]
             [PATH_SUFFIXES suffix1 [suffix2 ...]]
             [NO_DEFAULT_PATH]
             [NO_CMAKE_ENVIRONMENT_PATH]
             [NO_CMAKE_PATH]
             [NO_SYSTEM_ENVIRONMENT_PATH]
             [NO_CMAKE_PACKAGE_REGISTRY]
             [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
             [NO_CMAKE_SYSTEM_PATH]
             [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
             [CMAKE_FIND_ROOT_PATH_BOTH |
              ONLY_CMAKE_FIND_ROOT_PATH |
              NO_CMAKE_FIND_ROOT_PATH])

CMake默认采取Module模式,如果Module模式未找到库,才会采取Config模式(也可显示使用CONFIG参数指定采用Config模式)。

Config模式会去查找名为<PackageName>Config.cmake<package-name>-config.cmake的模块文件,【查找路径】按优先级从高到低如下:

  1. 首先查找名为<PackageName>_DIR的CMake变量或环境变量路径,默认为空。
    这个路径是【非根目录】路径,要求该路径下存在<PackageName>Config.cmake<package-name>-config.cmake文件才可以找到。

  2. 其次查找名为CMAKE_PREFIX_PATHCMAKE_FRAMEWORK_PATHCMAKE_APPBUNDLE_PATH的CMake变量或环境变量路径

    这些路径为【根目录】,默认都为空。
    注意如果你电脑中安装了ROS并配置好之后,你在终端执行echo $CMAKE_PREFIX_PATH会发现ROS会将CMAKE_PREFIX_PATH这个变量设置为ROS中的库的路径,意思是会首先查找ROS安装的库,如果恰好你在ROS中安装了OpenCV库,就会发现首先找到的是ROS中的OpenCV,而不是你自己安装到系统中的OpenCV。

  3. 最后查找系统PATH环境变量路径

    可以用 echo %path% 查看系统环境变量设置的路径

查找到库后,通常XXXConfig.cmake文件内部会给 XXX_INCLUDE_DIRSXXX_LIBRARIES两个变量赋值,但这也不是一定的

上面提到的根目录通常是

<prefix>/(lib/<arch>|lib|share)/cmake/<name>*/
<prefix>/(lib/<arch>|lib|share)/<name>*/ 
<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/
# 注:*为通配符

建议

  1. 建议在Config模式下的时候,使用set设置 <PackageName>_DIR 变量来指定查找的路径,这样就不怕找不到了

  2. 如果你有多个包的配置文件需要查找,可以将这些配置文件都统一放在一个命名为cmake的文件夹下,然后设置变量CMAKE_PREFIX_PATH变量指向这个cmake文件夹路径,需要注意根据上述的匹配规则,此时每个包的配置文件需要单独放置在命名为包名的文件夹下(文件夹名不区分大小写),否则会提示找不到。

相对路径问题

问题描述

在代码中如果用【相对路径】打开一个文件a.txt,编译时可能没问题,但执行的时候可能就会出问题了,因为源代码与a.txt的相对位置关系,和可执行文件与a.txt之间的位置关系不一样。

比如main.cpp和a.txt都在src/目录下,而 main.exe 在build/目录下,如下所示:

build/
  - main.exe
src/
  - main.cpp
  - a.txt

因此要想让程序正常运行,需要在代码中把打开a.txt文件的路径由原来的"a.txt"修改为"../src/a.txt",即可。

然而,这样看上去很不舒服,因此不建议这样做。

绝对路径虽然没有这种问题,但绝对路径又臭又长,在代码中也不美观,而且如果把代码分享给别人,别人也要修改。

解决办法

本质上还是使用绝对路径,但这个绝对路径在cmake编译时生成。我们知道,cmake可以获取到项目的根目录所在路径PROJECT_SOURCE_DIR,因此如果可以在CPP代码中获取到PROJECT_SOURCE_DIR的值就好了。

cmake提供了一个configure_file函数:

configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])

<input>表示输入文件,<output>表示输出文件。

输入文件内可以使用@VAR@${VAR}的方式获取到cmake变量值,在执行configure_file函数后,cmake会把@VAR@${VAR}替换为具体值后再把输入文件所有东西拷贝到输出文件(不存在的话会自动创建)

比如,设置输入文件为 ${PROJECT_SOURCE_DIR}/src/configPath.h.in,输出文件为 ${PROJECT_SOURCE_DIR}/src/configPath.h

并在 configPath.h.in写入下面的代码

#define PROJECT_ROOT_PATH ${PROJECT_SOURCE_DIR}

输出文件会自己创建,不用管。

然后在 main.cpp 中包含输出的头文件 #include "configPath.h"

接下来就能在 main.cpp 中使用变量 PROJECT_ROOT_PATH

cmake后的src文件结构如下

src/
  - main.cpp
  - a.txt
  - configPath.h.in
  - configPath.h

小技巧:cpp中,相邻两个字符串常量(可以是宏定义的字符串)会自动合并,如:

"abc" "de"; //会合并为 "abcde"

标签:CMAKE,NO,路径,Cmake,使用,PATH,cmake,Config
From: https://www.cnblogs.com/ajream/p/17348015.html

相关文章

  • 练习——泛型简单练习+JUnit的简单使用
    packagecom.generic;importorg.junit.jupiter.api.Test;importjava.util.*;/*定义个泛型类DAO<T>,在其中定义一个Map成员变量,Map的键为String类型,值为T类型分别创建以下方法:(1)publicvoidsave(Stringid,Tentity):保存T类型的对象到Map成员变量中(2)publicTg......
  • vi命令修改文件及保存的使用方法
    简单点:vi文件名,按"I"进入insert模式,可以正常文本编辑,编辑好之后按“esc”退出到“命令模式”,再按“shift+:”进入“底行模式”,按“:wq”保存退出!还一种:把文件复制到本地修改好上传上去!vi编辑器是所有Unix及Linux系统下标准的编辑器,介绍一下它的用法和一小部分指令。由于对Unix及L......
  • Mybatis中的<![CDATA[]]>标签在判断日期场景中的使用
    背景在使用mybatis时我们sql是写在xml映射文件中,如果写的sql中有一些特殊的字符的话,在解析xml文件的时候会被转义。如大于号>会被转义为>转义后的可读性不是很直观,如果想让其看起来更加直观可读性更强的话,则需要使用<![CDATA[]]>来圈起来不被转义的符号以此来解决这个问题。......
  • vue2源码-十三、nextTick在哪里使用?原理是什么?
    nextTick在哪里使用?原理是什么?nextTick内部采用了异步任务进行包装(多个nextTick调用会被合并成一次,内部会合并回调)最后在异步任务中批处理。主要应用场景就是异步更新(默认调度的时候就会添加一个·nextTick任务)用户为了获取最终的渲染结果需要在内部任务执行之后再执行用户逻......
  • mysql主从:mysql 主从、django使用多数据库做读写分离
    目录一、mysql主从介绍搭建步骤二、django使用多数据库做读写分离一、mysql主从介绍MySQL主从复制是一种常见的数据库复制技术,可以将一个MySQL数据库的数据复制到多个从库中,从而提高读取性能和数据可用性。在主从复制中,主库是数据的源头,从库是数据的副本,主库将数据变更记录......
  • 使用Docker安装Mysql
    mysql官方DockerHub地址:https://hub.docker.com/_/mysql可选的环境变量:MYSQL_ROOT_PASSWORDMYSQL_DATABASEMYSQL_USER,MYSQL_PASSWORDMYSQL_ALLOW_EMPTY_PASSWORDMYSQL_RANDOM_ROOT_PASSWORDMYSQL_ONETIME_PASSWORDMYSQL_INITDB_SKIP_TZINFO创建一个环境变量配置文件,vi......
  • mac:使用VLC播放纯视频YUV文件和纯音频pcm文件(命令行)
    一、使用vlc播放yuv有时候,我们需要播放一些纯视频文件,判断YUV数据是否可用。举个例子,我们使用命令行,播放/Users/domain/Desktop目录下的:test\_yuv420p\_320x180.yuv文件,命令如下:$/Applications/VLC.app/Contents/MacOS/VLC--demuxrawvideo--rawvid-fps15--rawvid-width320......
  • 【逆向】使用x64dbg实现qq私聊与群消息防撤回
    微信防撤回的实现比qq还要简单一些,因为它的私聊和群聊的撤回用的是一个call。。。微信本体是32位,所以我们直接用x32dbg去附加微信的撤回函数我们不知道在哪,所以先扫一下所有模块。然后搜索revoke用小号先给我们的微信发个消息,然后加断点,小号再撤回,从而定位撤回函数位置。......
  • JavaScript 使用 splice 方法删除数组元素可能导致的问题
    JavaScript使用splice方法删除数组元素可能导致的问题splice()方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。JavaScript遍历数组并通过splice方法删除该数组符合某些条件的元素将会导致哪些问题?导致......
  • 用友U8没有使用过往来两清,反结账后,作废凭证会提示:‘此凭证的分录有银行/往来两清标志,
    原因:年结转的时候,勾选了往来业务自动核销已两清业务解决办法:往来两清里面取消分录的往来两清,或者手工取消......