【问题标题】:CMake: set_target_properties fails with target defined by generator expressionCMake:set_target_properties 失败,目标由生成器表达式定义
【发布时间】:2021-07-14 17:33:14
【问题描述】:

我在使用 cmake 生成器表达式 TARGET_NAME_IF_EXISTS 时遇到问题。有了这个CMakeLists.txt

cmake_minimum_required(VERSION 3.13.0)
option(SLIB_BUILD_STATIC "" ON)
project(slib VERSION 1.0)

add_library(slibObjects OBJECT main.c)
add_library(slib SHARED $<TARGET_OBJECTS:slibObjects>)

if (SLIB_BUILD_STATIC)                  # Can this if() be replaced with a GenExp?
  add_library(slibStatic STATIC $<TARGET_OBJECTS:slibObjects>)
endif()

set_target_properties(
    slib
    $<TARGET_NAME_IF_EXISTS:slibStatic> # This GenExp doesn't get reduced
  PROPERTIES
    VERSION ${SLIB_VERSION}
    SOVERSION ${SLIB_VERSION_MAJOR}
)

我明白了

CMake Error at CMakeLists.txt:12 (set_target_properties):
  set_target_properties Can not find target to add properties to:
  $<TARGET_NAME_IF_EXISTS:slibStatic>

我预计 set_target_properties 会减少到其中之一,具体取决于是否设置了 SLIB_BUILD_STATIC

set_target_properties( slib slibStatic PROPERTIES ...)
set_target_properties( slib PROPERTIES ...)

我做错了什么?

【问题讨论】:

    标签: cmake cmake-language


    【解决方案1】:

    生成器表达式不能替代if 命令

    生成器表达式仅可用于某些 properties 和某些 variables,因此可以在配置阶段结束时将它们评估为一个值,这取决于构建类型.使用普通的 if 无法实现此类行为,因为多配置 CMake 生成器(如 Visual Studio)读取 CMakeLists.txt 一次但会创建多个配置。

    生成器表达式也可用于设置这些属性和变量的命令

    生成器表达式的每种可能用法都在文档中明确说明用于支持它们的命令/属性/变量。

    set_target_properties 命令的文档没有描述生成器表达式的用法,因此该命令根本不支持它们。

    实际上,可以将生成器表达式作为属性的传递给该命令。在这种情况下,该命令只会将该值分配给相应的属性。配置后对属性求值时是否解析生成器表达式取决于属性。

    但是 target 的名称和 property 的名称都不能是生成器表达式。

    对于有条件地为目标设置属性,使用普通的if

    # Unconditionally set properties for 'slib' target.
    set_target_properties(
        slib
      PROPERTIES
        VERSION ${SLIB_VERSION}
        SOVERSION ${SLIB_VERSION_MAJOR}
    )
    # Set properties for 'slibStatic' target only if this target exist.
    if (TARGET slibStatic)
      set_target_properties(
          slibStatic
        PROPERTIES
          VERSION ${SLIB_VERSION}
          SOVERSION ${SLIB_VERSION_MAJOR}
      )
    endif()
    

    为避免复制粘贴属性的赋值,您可以创建一个包含目标列表的变量,然后使用此变量:

    # Variable which contain list of affected targets.
    set(targets_for_version_set slib)
    # Add target 'slibStatic' to the list only if the target exist
    
    if (TARGET slibStatic)
      list(APPEND targets_for_version_set slibStatic)
    endif()
    # Now assign properties for all variables in the list
    set_target_properties(
        ${targets_for_version_set}
      PROPERTIES
        VERSION ${SLIB_VERSION}
        SOVERSION ${SLIB_VERSION_MAJOR}
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-09
      • 1970-01-01
      • 2018-09-11
      相关资源
      最近更新 更多