CMake中set_property/get_property的使用

Posted fengbingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CMake中set_property/get_property的使用相关的知识,希望对你有一定的参考价值。

      CMake中的set_property命令用于在给定作用域(scope)内设置命名属性,其格式如下:

set_property(<GLOBAL                      |
              DIRECTORY [<dir>]           |
              TARGET    [<target1> ...]   |
              SOURCE    [<src1> ...]
                        [DIRECTORY <dirs> ...]
                        [TARGET_DIRECTORY <targets> ...] |
              INSTALL   [<file1> ...]     |
              TEST      [<test1> ...]     |
              CACHE     [<entry1> ...]    >
             [APPEND] [APPEND_STRING]
             PROPERTY <name> [<value1> ...])

      在作用域的零个或多个对象(objects)上设置一个属性。
      第一个参数决定设置属性的作用域,它必须是以下之一:
      (1).GLOBAL:作用域是唯一的,不接受name。
      (2).DIRECTORY:作用域默认为当前目录,但其它目录(已由CMake处理)可以按完整或相对路径命名.相对路径被视为相对于当前源目录的路径。
      <dir>可以引用二进制目录(may reference a binary directory)。
      (3).TARGET:作用域(scope)可以命名零个或多个现有(existing)targets。
      (4).SOURCE:作用域(scope)可以命名零个或多个源文件。默认情况下,源文件属性仅对在同一目录(CMakeLists.txt)中添加的target可见.
      (5).INSTALL:作用域(scope)可以命名零个或多个已安装的文件路径。
      属性key和value都可以使用生成器表达式。特定属性(specific properties)可能适用于已安装的文件和/或目录。
      路径组件(path components)必须用正斜杠分割,必须规范化(normalized)并且区分大小写。
      要使用相对路径引用(reference)安装前缀本身,请使用.。
      (6).TEST:作用域(scope)可以命名零个或多个现有(existing)tests.
      (7).CACHE:作用域(scope)必须命名零个或多个缓存现有条目(cache existing entries)。
      必需的PROPERTY选项紧跟要设置的属性的名称。其余参数用于以分号分隔的列表形式组成属性值。
      如果给出了APPEND选项,则该列表将追加到任何现有属性值(空值将被忽略且不追加)。如果给出了APPEND_STRING选项,则该字符串将作为字符串追加到任何现有属性值,即,它会导致更长的字符串而不是字符串列表。
      注意:GENERATED源文件属性可能全局可见。

      CMake中的get_property命令用于获取属性,其格式如下:

get_property(<variable>
             <GLOBAL             |
              DIRECTORY [<dir>]  |
              TARGET    <target> |
              SOURCE    <source>
                        [DIRECTORY <dir> | TARGET_DIRECTORY <target>] |
              INSTALL   <file>   |
              TEST      <test>   |
              CACHE     <entry>  |
              VARIABLE           >
             PROPERTY <name>
             [SET | DEFINED | BRIEF_DOCS | FULL_DOCS])

      从作用域中的一个对象中获取一个属性。
      第一个参数指定存储结果的变量。第二个参数决定了从哪个作用域获取属性。它必须是以下之一:
      (1).GLOBAL:作用域是唯一的,不接受name。
      (2).DIRECTORY:作用域默认为当前目录,但另一个目录(已由CMake处理)可以按完整或相对路径<dir>命名.相对路径被视为相对于当前源目录的路径。
      <dir>可以引用二进制目录(may reference a binary directory)。
      (3).TARGET:作用域必须命名一个现有target。
      (4).SOURCE:作用域必须命名一个源文件。默认情况下,将从当前源目录的作用域读取源文件的属性。
      (5).INSTALL:作用域必须命名一个已安装的文件路径。
      (6).TEST:作用域必须命名一个现有test。
      (7).CACHE:作用域必须命名一个缓存条目。
      (8).VARIABLE:作用域是唯一的,不接受name。
      必需的PROPERTY选项紧跟要获取的属性名称。如果未设置该属性,则返回一个空值,尽管某些属性支持从父作用域继承。
      如果给出了SET选项,则变量将设置为布尔值,该值指示是否已设置该属性。如果给出了DEFINED选项,则变量将设置为一个布尔值,指示是否已定义该属性。
      如果给出了BRIEF_DOCS或FULL_DOCS,则变量设置为包含所请求属性的文档的字符串。如果为尚未定义的属性请求文档,则返回NOTFOUND。
      注意:GENERATED源文件属性可能全局可见。

# reference: https://github.com/Kitware/CMake/blob/master/Tests/Properties/CMakeLists.txt

get_property(GLOBALRESULT GLOBAL PROPERTY GLOBALTEST DEFINED)
if(GLOBALRESULT)
    message(SEND_ERROR "Error: global prop defined when it should not be, result is GLOBALRESULT=$GLOBALRESULT")
endif()

define_property(GLOBAL PROPERTY GLOBALTEST
    BRIEF_DOCS "A test property"
    FULL_DOCS "A long description of this test property"
)

get_property(GLOBALRESULT GLOBAL PROPERTY GLOBALTEST DEFINED)
if(NOT GLOBALRESULT)
    message(SEND_ERROR "Error: global prop not defined, result is GLOBALRESULT=$GLOBALRESULT")
endif()

set_property(GLOBAL PROPERTY GLOBALTEST 1)
set_property(DIRECTORY PROPERTY DIRECTORYTEST 1)
set_property(SOURCE source/add.cpp PROPERTY SOURCETEST 1)
get_property(GLOBALRESULT GLOBAL PROPERTY GLOBALTEST)
get_property(DIRECTORYRESULT DIRECTORY PROPERTY DIRECTORYTEST)
get_property(SOURCERESULT SOURCE source/add.cpp PROPERTY SOURCETEST)
if(NOT (GLOBALRESULT AND DIRECTORYRESULT AND SOURCERESULT))
    message(SEND_ERROR "Error: test results are "
        "GLOBALRESULT=$GLOBALRESULT "
        "DIRECTORYRESULT=$DIRECTORYRESULT "
        "SOURCERESULT=$SOURCERESULT")
endif()

# test the target property
include_directories(include)
add_library(Properties source/add.cpp)
set_property(TARGET Properties PROPERTY TARGETTEST 1)
get_property(TARGETRESULT TARGET Properties PROPERTY TARGETTEST)
if(NOT TARGETRESULT)
    message(SEND_ERROR "Error: target result is TARGETRESULT=$TARGETRESULT")
endif()

# test APPEND and APPEND_STRING set_property()
set_property(TARGET Properties PROPERTY FOO foo)
set_property(TARGET Properties PROPERTY BAR bar)
set_property(TARGET Properties APPEND PROPERTY FOO 123)
set_property(TARGET Properties APPEND_STRING PROPERTY BAR 456)

get_property(APPEND_RESULT TARGET Properties PROPERTY FOO)
if(NOT "$APPEND_RESULT" STREQUAL "foo;123")
    message(SEND_ERROR "Error: target result is APPEND_RESULT=$APPEND_RESULT")
endif()

get_property(APPEND_STRING_RESULT TARGET Properties PROPERTY BAR)
if(NOT "$APPEND_STRING_RESULT" STREQUAL "bar456")
    message(SEND_ERROR "Error: target result is APPEND_STRING_RESULT=$APPEND_STRING_RESULT")
endif()

# test get_property SET
get_property(TARGETRESULT TARGET Properties PROPERTY TARGETTEST SET)
if(NOT TARGETRESULT)
    message(SEND_ERROR "Error: target prop not set, result is TARGETRESULT=$TARGETRESULT")
endif()

# test unsetting a property
set_property(TARGET Properties PROPERTY TARGETTEST)
get_property(TARGETRESULT TARGET Properties PROPERTY TARGETTEST SET)
if(TARGETRESULT)
    message(SEND_ERROR "Error: target prop not unset, result is TARGETRESULT=$TARGETRESULT")
endif()

      执行测试代码需要多个文件

      build.sh内容如下:

#! /bin/bash

# supported input parameters(cmake commands)
params=(function macro cmake_parse_arguments \\
		find_library find_path find_file find_program find_package \\
		cmake_policy cmake_minimum_required project include \\
		string list set foreach message option if while return \\
		math file configure_file \\
		include_directories add_executable add_library target_link_libraries install \\
		target_sources add_custom_command add_custom_target \\
		add_subdirectory aux_source_directory \\
		set_property set_target_properties define_property)

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 ===="

# test_set.cmake: cmake -DTEST_CMAKE_FEATURE=$1 --log-level=verbose ..
# test_option.cmake: cmake -DTEST_CMAKE_FEATURE=$1 -DBUILD_PYTORCH=ON ..
cmake -DTEST_CMAKE_FEATURE=$1 ..
# It can be executed directly on the terminal, no need to execute build.sh, for example: cmake -P test_set.cmake
make
# make install # only used in cmake files with install command

      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_set_property.cmake内容为上面的所有测试代码段:参考CMake官方测试代码

      另外还包括三个目录:include,source,samples,它们都是非常简单的实现,仅用于测试,如下:

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

 

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

以上是关于CMake中set_property/get_property的使用的主要内容,如果未能解决你的问题,请参考以下文章

CMake中cmake_policy的使用

cmake的缓存变量可以用于cpp源码中吗

CMake中cmake_minimum_required的使用

CMake (三)cmake 在工程中的用法

Android OpenCVVisual Studio 创建支持 OpenCV 库的 CMake 工程 ② ( VS 中创建 CMake 工程 | CMake 工程中配置 OpenCV 头文件 )

make如何指定cmake路径