如何在CMake中删除"可能无法从目标读取位置属性"错误?

fee*_*ree 7 cmake

我现在正在尝试在这篇文章中运行一个cmake脚本.使用此脚本,CMake将打印目标的所有属性.但是,当它尝试检索目标的"LOCATION"属性时,会发现以下错误:

The LOCATION property may not be read from target "abc".  Use the target
  name directly with add_custom_command, or use the generator expression
  $<TARGET_FILE>, as appropriate.
Run Code Online (Sandbox Code Playgroud)

然后我尝试打印属性LOCATION,它也不起作用.有任何想法吗?

squ*_*les 6

为了扩展 @Florian 的评论,在当今的 CMake 版本中,默认情况下读取LOCATION目标的属性是一个错误。CMake 策略 0026的文档清楚地描述了为什么会出现这种情况:

CMake 2.8.12 及更低版本允许读取LOCATION目标属性(和特定于配置的变体)以确定构建目标的最终位置。这依赖于这样的假设:在配置时可以使用所有必要的信息来确定目标的最终位置和文件名。然而,这个属性直到稍后生成时才完全确定。

读取LOCATION属性后,稍后可以使用生成器表达式对其进行更改。CMake 允许您通过显式OLD将其设置为行为来禁用此策略:

cmake_policy(SET CMP0026 OLD)
Run Code Online (Sandbox Code Playgroud)

对结果持保留态度,因为它可能会改变!

如果您要更改策略(而不是简单地LOCATION从属性列表中删除),最好OLD单独使用 CMake 策略。当我们使用完该OLD行为后,我们可以将POP旧策略从 CMake 策略堆栈中删除以恢复使用该NEW行为。这是您提到的示例,经过修改以演示策略更改的用法:

function(echo_target tgt)
    if(NOT TARGET ${tgt})
        message("There is no target named '${tgt}'")
        return()
    endif()

    set(props
        DEBUG_OUTPUT_NAME
        DEBUG_POSTFIX
        RELEASE_OUTPUT_NAME
        ...
        LINK_SEARCH_START_STATIC
        LOCATION
        LOCATION_DEBUG
        ...
        WIN32_EXECUTABLE
        XCODE_ATTRIBUTE_WHATEVER
    )
    message(STATUS "======================== ${tgt} ========================")

    # Push the current (NEW) CMake policy onto the stack, and apply the OLD policy.
    cmake_policy(PUSH)
    cmake_policy(SET CMP0026 OLD)

    foreach(p ${props})
        # v for value, d for defined, s for set
        get_property(v TARGET ${tgt} PROPERTY ${p})
        get_property(d TARGET ${tgt} PROPERTY ${p} DEFINED)
        get_property(s TARGET ${tgt} PROPERTY ${p} SET)
        # only produce output for values that are set
        if(s)
            message(STATUS "tgt='${tgt}' p='${p}'")
            message(STATUS "  value='${v}'")
            message(STATUS "  defined='${d}'")
            message(STATUS "  set='${s}'")
            message(STATUS "")
        endif()
    endforeach()

    # Pop the previous policy from the stack to re-apply the NEW behavior.
    cmake_policy(POP)

    message(STATUS "")
endfunction()
Run Code Online (Sandbox Code Playgroud)