[待更新中]
find_package用法
必读:
注意,要想在自己的项目中使用
find_package
命令查找包的前提是:包的开发者用CMake配置好了这个包,并提供了
<PackageName>Config.cmake
或Find<PackageName>.cmake
的配置文件。
有2种搜包模式 Module
和 Config
模式
默认采用 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
的模块文件,【查找路径】按优先级从高到低如下:
-
首先查找名为
<PackageName>_DIR
的CMake变量或环境变量路径,默认为空。
这个路径是【非根目录】路径,要求该路径下存在<PackageName>Config.cmake
或<package-name>-config.cmake
文件才可以找到。 -
其次查找名为
CMAKE_PREFIX_PATH
、CMAKE_FRAMEWORK_PATH
、CMAKE_APPBUNDLE_PATH
的CMake变量或环境变量路径这些路径为【根目录】,默认都为空。
注意如果你电脑中安装了ROS并配置好之后,你在终端执行echo $CMAKE_PREFIX_PATH会发现ROS会将CMAKE_PREFIX_PATH这个变量设置为ROS中的库的路径,意思是会首先查找ROS安装的库,如果恰好你在ROS中安装了OpenCV库,就会发现首先找到的是ROS中的OpenCV,而不是你自己安装到系统中的OpenCV。 -
最后查找系统PATH环境变量路径
可以用 echo %path% 查看系统环境变量设置的路径
查找到库后,通常
XXXConfig.cmake
文件内部会给XXX_INCLUDE_DIRS
和XXX_LIBRARIES
两个变量赋值,但这也不是一定的
上面提到的根目录通常是
<prefix>/(lib/<arch>|lib|share)/cmake/<name>*/
<prefix>/(lib/<arch>|lib|share)/<name>*/
<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/
# 注:*为通配符
建议
-
建议在Config模式下的时候,使用set设置
<PackageName>_DIR
变量来指定查找的路径,这样就不怕找不到了 -
如果你有多个包的配置文件需要查找,可以将这些配置文件都统一放在一个命名为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
标签:CMAKE,NO,路径,Cmake,使用,PATH,cmake,Config From: https://www.cnblogs.com/ajream/p/17348015.html小技巧:cpp中,相邻两个字符串常量(可以是宏定义的字符串)会自动合并,如:
"abc" "de"; //会合并为 "abcde"