接口库的自定义属性

问题描述

我们希望为每个使用过的库添加一个许可证文件,以及一种比较许可证以检测它们是否发生变化的机制。因此,我们将其许可文件添加到每个库(Boost、Qt 等)中,并有一个签入副本。

我们认为我们可以为此添加一个我们自己的接口库,使用我们自己的名称,并将实际的 CMake 导入库链接到它,例如 Qt6::CoreBoost::filesystem。但是将许可证文件添加属性会导致错误。最后只链接到我们自己的接口库。

function(myNewExternal NAME)
   _myParseExternalParameters(EXTARGS ${ARGN})

   if(NOT DEFINED EXTARGS_TARGET)
      message(FATAL_ERROR "myNewExternal missing TARGET")
   endif()

   add_library(${NAME} INTERFACE)
   target_link_libraries(${NAME} INTERFACE ${EXTARGS_TARGET})

   # add property for the original files
   define_property(
      TARGET 
      PROPERTY MY_LIC_ORIGINAL
      BRIEF_DOCS "Original file name on system"
      FULL_DOCS "...")

   # add property for the checked-in files
   define_property(
      TARGET 
      PROPERTY MY_LIC_CHECKEDIN
      BRIEF_DOCS "File name checked-in git (with md5sum appended on disk)"
      FULL_DOCS "...")

   # add property for the flags (checked(c),printed(p))
   define_property(
      TARGET 
      PROPERTY MY_LIC_FLAGS
      BRIEF_DOCS "Flags for license checks or manual generation"
      FULL_DOCS "...")
endfunction()

然而,设置目标的属性失败并出现错误

CMake Error at cmake/700-externals.cmake:39 (set_property):
  INTERFACE_LIBRARY targets may only have whitelisted properties.  The
  property "MY_LIC_ORIGINAL" is not allowed.

在这里做错了什么,“正确”的方法是什么?

解决方法

INTERFACE 库的自定义属性必须以 INTERFACE_ 为前缀。这是一个用于验证的简单 CMakeLists.txt:

cmake_minimum_required(VERSION 3.21)
project(test NONE)

add_library(foo INTERFACE)
set_property(TARGET foo PROPERTY INTERFACE_CUSTOM "bar")

get_property(value TARGET foo PROPERTY INTERFACE_CUSTOM)
message(STATUS "foo.INTERFACE_CUSTOM = \"${value}\"")

在命令行:

$ cmake -S . -B build
-- foo.INTERFACE_CUSTOM = "bar"
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/build

请注意,除非为其定义了几个简单的兼容性规则之一,否则自定义 INTERFACE 属性不会传播。有关详情,请参阅 compatible interface properties