CMake中find_program的使用

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

find_program (
          <VAR>
          name | NAMES name1 [name2 ...] [NAMES_PER_DIR]
          [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_program(var NAMES cmake)
message("var: ${var}") # var: /usr/bin/cmake

unset(var CACHE)
find_program(var gcc) # 最简格式:find_program(<VAR> name),查找默认路径
message("var: ${var}") # var: /usr/bin/gcc

# 如果找到程序,则结果将存储在变量中,除非清除变量,否则不会重复搜索
find_program(var NAMES cmake) # 注意:未清除变量,不会重复搜索,最终结果是不对的,并没有查找cmake
message("var: ${var}") # var: /usr/bin/gcc

unset(var) # 若不带CACHE,则var是/usr/bin/gcc而不是/usr/bin/cmake
find_program(var NAMES cmake)
message("var: ${var}") # var: /usr/bin/gcc

unset(var CACHE)
find_program(var NAMES valgrind) # 如果没找到程序,结果将为<VAR>-NOTFOUND
message("var: ${var}") # var: var-NOTFOUND
if(${var} STREQUAL "var-NOTFOUND")
	message(WARNING "the specified program was not found")
endif()
if(NOT var) # 注意这里是var不是${var}
	message(WARNING "the specified program was not found")
endif()

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

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

# 手动将/usr/bin/cmake拷贝到/opt/cmake/目录下
unset(var CACHE)
find_program(var NAMES cmake PATHS /opt/cmake) # PATHS:先搜索系统路径,然后再搜索PATHS指定的路径
message("var: ${var}") # var: /usr/bin/cmake

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

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

unset(var CACHE)
find_program(var NAMES cmake PATHS /opt NO_DEFAULT_PATH) # 仅搜索:/opt/
message("var: ${var}") # var: var-NOTFOUND

unset(var CACHE)
find_program(var NAMES cmake PATHS /opt PATH_SUFFIXES cmake NO_DEFAULT_PATH) # 搜索:(1)/opt; (2)/opt/cmake/
message("var: ${var}") # var: /opt/cmake/cmake

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

unset(var CACHE)
find_program(var NAMES cmake DOC "cmake program") # CMakeCache.txt中会对var增加注释说明
message("var: ${var}") # var: /usr/bin/cmake

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

//Path to a program.
var:FILEPATH=/usr/bin/cmake

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

//cmake program
var:FILEPATH=/usr/bin/cmake

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

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

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

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

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

unset(var CACHE)
find_program(var NAMES valgrind REQUIRED) # 将触发error,停止后续的执行:CMake Error at test_find_program.cmake:68 (find_program): Could not find var using the following names: valgrind

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

# 手动将/usr/bin/cmake拷贝到/opt/cmake/目录下
unset(var CACHE)
find_program(var NAMES cmake PATHS /opt/cmake NO_DEFAULT_PATH) # 指定不使用默认路径,path最后带不带"/"均可
message("var: ${var}") # var: /opt/cmake/cmake

unset(var CACHE)
find_program(var NAMES cmake NO_DEFAULT_PATH)
message("var: ${var}") # var: var-NOTFOUND

unset(var CACHE)
find_program(var NAMES cmake)
message("var: ${var}") # var: /usr/bin/cmake

      如果未指定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变量也可能导致上述某些位置被忽略。

      执行上述测试代码需要3个文件:build.sh, CMakeLists.txt, test_find_program.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_program.cmake内容:为上面所有的示例代码

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值