CMake中find_file的使用

      CMake中的命令find_file用于查找指定文件(named file)的完整路径,其格式如下:将创建一个由<VAR>命名的缓存条目即cache变量,将<VAR>的值存入CMakeCache.txt中);或如果指定了NO_CACHE,由<VAR>命名的普通变量来存储此命令的结果,这种情况下,<VAR>的值将不会存入CMakeCache.txt中。如果找到文件的完整路径,则结果将存储在<VAR>中,除非清除<VAR>,否则不会重复搜索。如果没找到,结果将为<VAR>-NOTFOUND

find_file (
          <VAR>
          name | NAMES name1 [name2 ...]
          [HINTS [path | ENV var]... ]
          [PATHS [path | ENV var]... ]
          [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)]
          [PATH_SUFFIXES suffix1 [suffix2 ...]]
          [DOC "cache documentation string"]
          [NO_CACHE]
          [REQUIRED]
          [NO_DEFAULT_PATH]
          [NO_PACKAGE_ROOT_PATH]
          [NO_CMAKE_PATH]
          [NO_CMAKE_ENVIRONMENT_PATH]
          [NO_SYSTEM_ENVIRONMENT_PATH]
          [NO_CMAKE_SYSTEM_PATH]
          [NO_CMAKE_INSTALL_PREFIX]
          [CMAKE_FIND_ROOT_PATH_BOTH |
           ONLY_CMAKE_FIND_ROOT_PATH |
           NO_CMAKE_FIND_ROOT_PATH]
)

      选项包括:
      (1).NAMES:为文件的完整路径指定一个或多个可能的名字。当使用它来指定带有和不带有版本后缀的名称时,建议首先指定不带版本控制的名字,以便在发行版(distributions)提供的软件包之前找到本地构建的软件包。示例代码段如下:

unset(var CACHE) # 清除变量,带有CACHE也从缓存文件CMakeCache.txt中清除,若不带CACHE则缓存文件CMakeCache.txt中仍然存在var的值
find_file(var NAMES opencv.hpp HINTS /opt/opencv3.1/include/opencv2)
message("var: ${var}") # var: /opt/opencv3.1/include/opencv2/opencv.hpp

unset(var CACHE)
find_file(var string.h) # 最简格式:find_file(<VAR> name),查找默认路径
message("var: ${var}") # var: /usr/include/string.h

# 如果找到目录,则结果将存储在变量中,除非清除变量,否则不会重复搜索
find_file(var NAMES opencv.hpp HINTS /opt/opencv3.1/include/opencv2) # 注意:未清除变量,不会重复搜索,最终结果是不对的,并没有查找opencv.hpp文件的完整路径
message("var: ${var}") # var: /usr/include/string.h

unset(var) # 若不带CACHE,则var是/usr/include/string.h而不是/opt/opencv3.1/include/opencv2/opencv.hpp
find_file(var NAMES opencv.hpp HINTS /opt/opencv3.1/include/opencv2)
message("var: ${var}") # var: /usr/include/string.h

unset(var CACHE)
find_file(var NAMES opencv.hpp) # 如果没找到目录,结果将为<VAR>-NOTFOUND
message("var: ${var}") # var: var-NOTFOUND
if(${var} STREQUAL "var-NOTFOUND")
	message(WARNING "the specified directory was not found")
endif()
if(NOT var) # 注意这里是var不是${var}
	message(WARNING "the specified directory was not found")
endif()

unset(var) # 不带CACHE则缓存文件CMakeCache.txt中仍然存在var的值

      (2).HINTS, PATHS:指定除默认位置外还要搜索的目录。"ENV var"子选项从系统环境变量读取路径。注意HINTS与PATHS区别:HINTS是在搜索系统路径之前先搜索HINTS指定的路径。PATHS是先搜索系统路径,然后再搜索PATHS指定的路径。示例代码段如下:

# 手动在/opt目录下建了个空的string.h文件
unset(var CACHE)
find_file(var NAMES string.h PATHS /opt) # PATHS:先搜索系统路径,然后再搜索PATHS指定的路径
message("var: ${var}") # var: /usr/include/string.h

unset(var CACHE)
find_file(var NAMES string.h HINTS /opt) # HINTS:先搜索HINTS指定的路径,然后再搜索系统路径
message("var: ${var}") # var: /opt/string.h

      (3).REGISTRY_VIEW:3.24版本中引入。指定必须要查询的注册表视图(registry views)。此选项仅在Windows平台上有意义,在其它平台上将被忽略。
      (4).PATH_SUFFIXES:若在PATHS或HINTS指定的路径中没有找到,则会在PATHS/PATH_SUFFIXES或HINTS/PATH_SUFFIXES指定的路径中继续搜索。示例代码段如下:

unset(var CACHE)
find_file(var NAMES opencv.hpp PATHS /opt/opencv3.1/ NO_DEFAULT_PATH) # 仅搜索:/opt/opencv3.1/ 
message("var: ${var}") # var: var-NOTFOUND

unset(var CACHE)
find_file(var NAMES opencv.hpp PATHS /opt/opencv3.1 PATH_SUFFIXES include/opencv2 NO_DEFAULT_PATH) # 搜索:(1)/opt/opencv3.1/; (2)/opt/opencv3.1/include/opencv2/
message("var: ${var}") # var: /opt/opencv3.1/include/opencv2/opencv.hpp

unset(var CACHE)
find_file(var NAMES opencv.hpp PATHS /opt/opencv3.4.2/ NO_DEFAULT_PATH) # 仅搜索:/opt/opencv3.4.2/ 
message("var: ${var}") # var: var-NOTFOUND

unset(var CACHE)
find_file(var NAMES opencv.hpp HINTS /opt/opencv3.4.2 PATH_SUFFIXES include/opencv2 NO_DEFAULT_PATH) # 搜索:(1)/opt/opencv3.4.2/; (2)/opt/opencv3.4.2/include/opencv2/
message("var: ${var}") # var: /opt/opencv3.4.2/include/opencv2/opencv.hpp

      (5).DOC:指定由<VAR>命名的缓存条目的文档字符串,即在CMakeCache.txt文件中会增加对<VAR>的描述。示例代码段如下:

unset(var CACHE)
find_file(var NAMES opencv.hpp HINTS /opt/opencv3.1/include/opencv2 DOC "opencv head file") # CMakeCache.txt中会对var增加注释说明
message("var: ${var}") # var: /opt/opencv3.1/include/opencv2/opencv.hpp

      在没有添加DOC选项时,CMakeCache.txt中var内容为:

//Path to a file.
var:FILEPATH=/opt/opencv3.1/include/opencv2/opencv.hpp

      添加DOC选项后,CMakeCache.txt中var内容变为:

//opencv head file
var:FILEPATH=/opt/opencv3.1/include/opencv2/opencv.hpp

      (6).NO_CACHE:3.21版本中引入。搜索结果将存储在普通变量中而不是缓存条目中。如果变量在调用之前已经设置(作为普通变量或缓存变量),则搜索将不会发生。应谨慎使用此选项,因为它会大大增加重复配置步骤的成本。示例代码段如下:

unset(var1 CACHE)
find_file(var1 NAMES string.h NO_CACHE) # 带有NO_CACHE后,var1的值将不会存入CMakeCache.txt中
message("var1: ${var1}") # var1: /usr/include/string.h

unset(var2 CACHE)
find_file(var2 NAMES string.h) # 不带NO_CACHE,var2的值将写入CMakeCache.txt中
message("var2: ${var2}") # var2: /usr/include/string.h

      (7).REQUIRED:3.18版本中引入。如果未找到任何内容,则停止处理并触发错误消息,否则下次使用相同的变量调用find_file时将再次尝试搜索。示例代码段如下:

unset(var CACHE)
find_file(var NAMES opencv.hpp) # 找不到会继续后续的执行
message("var: ${var}") # var: var-NOTFOUND

unset(var CACHE)
find_file(var NAMES opencv.hpp REQUIRED) # 将触发error,停止后续的执行:CMake Error at test_find_file.cmake:76 (find_file): Could not find var using the following names: opencv.hpp

      (8).NO_DEFAULT_PATH:如果指定了此选项,则不会向搜索中添加其它路径。默认搜索路径将失效,只会搜索PATHS和HINTS指定的路径。示例代码段如下:

# 手动在/opt目录下建了个空的string.h文件
unset(var CACHE)
find_file(var NAMES string.h PATHS /opt NO_DEFAULT_PATH) # 指定不使用默认路径,path最后带不带"/"均可
message("var: ${var}") # var: /opt/string.h

unset(var CACHE)
find_file(var NAMES string.h NO_DEFAULT_PATH)
message("var: ${var}") # var: var-NOTFOUND

unset(var CACHE)
find_file(var NAMES string.h)
message("var: ${var}") # var: /usr/include/string.h

      如果未指定NO_DEFAULT_PATH选项,则搜索过程如下:
      (1).3.12版本中引入。如果调用来自于find module或通过调用find_package(<PackageName>)加载的任何其它脚本,搜索当前package唯一的前缀。具体来说,查看<PackageName>_ROOT CMake变量和<PackageName>_ROOT环境变量。package root变量作为堆栈维护,因此如果从嵌套的find modules或config packages中调用,则root paths from the parent's find module or config package will be searched after paths from the current module or package.换句话说,搜索顺序将是:<CurrentPackage>_ROOT, ENV{<CurrentPackage>_ROOT}, <ParentPackage>_ROOT, ENV{<ParentPackage>_ROOT}等。如果设置了NO_PACKAGE_ROOT_PATH或将CMAKE_FIND_USE_PACKAGE_ROOT_PATH设置为FALSE,则可以跳过此步骤。
      (2).在特定于cmake(cmake-specific)的缓存变量中指定的搜索路径。这些旨在通过-DVAR=value在命令行上使用。这些值被解释为分号分割的列表。如果设置了NO_CMAKE_PATH或将CMAKE_FIND_USE_CMAKE_PATH设置为FALSE,则可以跳过此步骤。
      (3).在特定于cmake(cmake-specific)的环境变量中指定的搜索路径。这些旨在用户的shell配置中设置。如果设置了NO_CMAKE_ENVIRONMENT_PATH或将CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH设置为FALSE,则可以跳过此步骤。
      (4).搜索由HINTS选项指定的路径。这些应该是系统introspection计算的路径。
      (5).在标准系统环境变量(standard system environment variables)中指定的搜索路径。如果设置了NO_SYSTEM_ENVIRONMENT_PATH或将CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH设置为FALSE,则可以跳过此操作。
      (6).搜索当前系统的Platform文件中定义的cmake变量。如果设置了NO_CMAKE_INSTALL_PREFIX或将CMAKE_FIND_USE_INSTALL_PREFIX设置为FALSE,则可以跳过搜索CMAKE_INSTALL_PREFIX和CMAKE_STAGING_PREFIX。如果设置了NO_CMAKE_SYSTEM_PATH或将CMAKE_FIND_USE_CMAKE_SYSTEM_PATH设置为FALSE,则可以跳过所有这些位置。The platform paths that these variables contain are locations that typically include installed software. An example being /usr/local for UNIX based platforms.
      (7).搜索由PATHS选项或in the short-hand version of the command指定的路径。These are typically hard-coded guesses.
      CMAKE_IGNORE_PATH, CMAKE_IGNORE_PREFIX_PATH, CMAKE_SYSTEM_IGNORE_PATH和CMAKE_SYSTEM_IGNORE_PREFIX_PATH变量也可能导致上述某些位置被忽略。

      以下测试代码搜索本机中的OpenCV头文件,本机中有多个版本的OpenCV库:
      (1).4.5.4:头文件存放路径,系统默认的安装路径,通过命令sudo apt install libopencv-dev安装:/usr/include/opencv4/; OpenCVConfig.cmake存放路径:/usr/lib/x86_64-linux-gnu/cmake/opencv4/
      (2).3.1:头文件存放路径:/opt/opencv3.1/include/; OpenCVConfig.cmake存放路径:/opt/opencv3.1/share/OpenCV/
      (3).3.4.2:头文件存放路径:/opt/opencv3.4.2/include/; OpenCVConfig.cmake存放路径:/opt/opencv3.4.2/share/OpenCV/

      执行上述测试代码需要3个文件:build.sh, CMakeLists.txt, test_find_file.cmake

      build.sh内容如下:

#! /bin/bash

# supported input parameters
params=(function macro cmake_parse_arguments \
		find_library find_path find_file find_program find_package)

usage()
{
	echo "Error: $0 needs to have an input parameter"

	echo "supported input parameters:"
	for param in ${params[@]}; do
		echo "  $0 ${param}"
	done

	exit -1
}

if [ $# != 1 ]; then
	usage
fi

flag=0
for param in ${params[@]}; do
	if [ $1 == ${param} ]; then
		flag=1
		break
	fi
done

if [ ${flag} == 0 ]; then
	echo "Error: parameter \"$1\" is not supported"
	usage
	exit -1
fi

if [[ ! -d "build" ]]; then
	mkdir build
	cd build
else
	cd build
fi

echo "==== test $1 ===="
cmake -DTEST_CMAKE_FEATURE=$1 ..

      CMakeLists.txt内容如下:

CMAKE_MINIMUM_REQUIRED(VERSION 3.22)
PROJECT(cmake_feature_usage)

message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
include(test_${TEST_CMAKE_FEATURE}.cmake)
message("==== test finish ====")

      test_find_file.cmake内容:为上面的所有示例代码

      执行可能的结果如下图所示:

      GitHub: https://github.com/fengbingchun/Linux_Code_Test

<think>好的,我现在需要帮助用户解决CMake找不到asio_cmake_module配置文件的问题。首先,我得理解用户的问题是什么。用户提到在编译时遇到CMake错误,无法找到asio_cmake_moduleConfig.cmake或asio_cmake_module-config.cmake文件,这可能与ROS Humble的io_context和serial_driver有关。 首先,我应该回忆一下CMake在查找依赖包时的机制。CMake通常通过find_package命令来查找依赖,而依赖的配置文件一般位于系统的特定路径下,比如/usr/share/cmake-<版本>/Modules,或者通过环境变量如CMAKE_PREFIX_PATH指定的路径。当CMake找不到这些文件时,通常是因为包未安装、安装路径不在搜索路径中,或者版本不兼容。 接下来,我需要参考用户提供的引用内容。例如,引用[3]提到,在MoveIt编译时找不到某个被弃用的包,解决方法是删除find_package中的相关条目。这可能意味着用户的问题也可能是由于包被弃用或更名导致的。但用户的问题是关于asio_cmake_module的,我需要确认这个包是否在ROS Humble中被更改或替代。 首先,检查asio_cmake_module是否存在。在ROS中,有些包可能被重构或合并到其他包中。比如,用户提到io_context和serial_driver,这些可能属于ROS 2的某个组件。我需要确认asio_cmake_module是否属于ROS的某个标准包,或者是否是第三方依赖。 可能的解决步骤包括: 1. 确保asio_cmake_module已正确安装。用户可能需要通过apt或源码安装这个包。例如,在Ubuntu中,可以尝试安装ros-humble-asio-cmake-module或者类似的包名。 2. 检查CMakeLists.txt中的find_package调用是否正确。可能需要指定版本或组件,或者包名称有变化。例如,是否应该使用asio_cmake_module还是asio_cmake?或者包名是否改为其他名称? 3. 如果包确实存在但路径未被CMake识别,可能需要手动设置CMAKE_PREFIX_PATH或asio_cmake_module_DIR变量,指向包含配置文件的目录。 4. 查看依赖项的版本兼容性。例如,引用[2]中提到Qt5WebKit因为版本不匹配而找不到,用户的问题可能也是由于asio_cmake_module的版本与当前ROS版本(Humble)不兼容导致的。需要确认asio_cmake_module是否支持ROS Humble。 5. 如果asio_cmake_module已被弃用,可能需要寻找替代的包或修改代码中的依赖项,类似引用[3]中的解决方法,删除或替换find_package中的相关条目。 此外,用户提到的io_context和serial_driver可能与ROS 2的Serial Driver相关,可能属于ros2_drivers仓库中的组件。可能需要检查这些包的依赖关系,确保所有依赖项都已正确安装。 可能的错误原因包括: - asio_cmake_module未安装:用户可能没有安装这个包,或者安装的版本不正确。 - 安装路径不在CMake的搜索路径中:可能需要手动设置路径变量。 - 包名变更:在ROS Humble中,包名可能有变化,导致find_package失败。 - 依赖冲突:其他依赖项可能覆盖或影响了asio_cmake_module的查找。 接下来,我需要将这些思考整理成步骤,帮助用户逐一排查问题。例如,首先建议安装缺失的包,然后检查CMakeLists.txt,设置路径变量,最后考虑替代方案或版本问题。同时,结合用户提供的引用,引用[3]中的情况类似,可能需要修改CMakeLists.txt中的依赖项。 最后,生成相关问题,帮助用户深入理解问题,比如如何调试CMake查找过程,如何管理ROS包的依赖,以及处理其他类似的配置错误。</think>### 解决方案 当CMake报错找不到`asio_cmake_moduleConfig.cmake`或`asio_cmake_module-config.cmake`时,通常是由于以下原因导致: 1. **依赖包未正确安装** 2. **CMake搜索路径未包含依赖包位置** 3. **ROS版本与依赖包不兼容** 4. **CMakeLists.txt中配置错误** 以下是逐步解决方案: --- #### 1. **确认依赖包是否安装** - **安装ROS Humble相关包**: 执行以下命令安装`asio_cmake_module`: ```bash sudo apt install ros-humble-asio-cmake-module ``` 若提示包不存在,可能需要添加ROS仓库或更新软件源: ```bash sudo apt update && sudo apt upgrade ``` - **检查安装路径**: 安装成功后,确认配置文件路径是否在CMake搜索范围内。例如: ```bash # 检查文件是否存在 ls /opt/ros/humble/share/asio_cmake_module/cmake/ ``` 若路径正确,应看到`asio_cmake_moduleConfig.cmake`或类似文件。 --- #### 2. **配置CMake搜索路径** - **设置环境变量**: 在终端或`~/.bashrc`中添加路径: ```bash export CMAKE_PREFIX_PATH=/opt/ros/humble:$CMAKE_PREFIX_PATH source ~/.bashrc ``` - **手动指定路径**: 在`CMakeLists.txt`中显式指定路径: ```cmake list(APPEND CMAKE_PREFIX_PATH "/opt/ros/humble/share/asio_cmake_module/cmake") find_package(asio_cmake_module REQUIRED) ``` --- #### 3. **检查ROS版本兼容性** - **确认依赖包支持ROS Humble**: 某些包(如`asio_cmake_module`)可能仅支持特定ROS版本。若官方仓库未提供Humble版本,需从源码编译: ```bash git clone https://github.com/ros-drivers/transport_drivers.git cd transport_drivers && colcon build --packages-select asio_cmake_module ``` --- #### 4. **修改CMakeLists.txt** - **删除冗余依赖**: 如果`asio_cmake_module`已被弃用或合并到其他包(参考引用[3]),需在`CMakeLists.txt`中删除相关条目: ```cmake # 注释或删除以下行 # find_package(asio_cmake_module REQUIRED) ``` - **更新依赖声明**: 对于ROS Humble的`io_context`和`serial_driver`,确保使用新版本接口: ```cmake find_package(rclcpp REQUIRED) find_package(serial_driver REQUIRED) ``` --- #### 5. **调试CMake配置** - **启用详细日志**: 在CMake命令中添加`--debug-find`参数,查看依赖包搜索过程: ```bash cmake --debug-find .. ``` 输出会显示搜索路径和失败原因[^1]。 --- ### 相关问题 1. **如何调试CMake的`find_package`失败问题?** > 使用`cmake --debug-find`可输出详细搜索路径。 2. **ROS Humble中如何处理弃用包的依赖冲突?** > 需检查官方文档或社区建议,删除或替换`CMakeLists.txt`中的旧包引用(参考引用[3])。 3. **如何手动指定CMake依赖包的路径?** > 通过`list(APPEND CMAKE_PREFIX_PATH "自定义路径")`或环境变量实现[^2]。 --- 通过以上步骤,可解决`asio_cmake_module`配置文件缺失问题。若仍报错,需检查ROS版本与依赖包的兼容性,或联系社区获取支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值