CMake中set_property/get_property的使用

本文介绍CMake中set_property和get_property命令的使用方法,包括如何设置和获取不同作用域内的属性,如全局、目录、目标等。并提供测试代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值