Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I remove the "the Location property may not be read from target" error in CMake?

Tags:

cmake

I am now trying run a CMake script in this post. With this script, CMake will print all the properties of a target. However, when it tries to retrieve the LOCATION property of the target, the following error is observed:

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.

Then I tried to print the property with message($<TARGET_FILE:abc>), but it does not work either. Any ideas?

like image 330
feelfree Avatar asked Aug 25 '15 07:08

feelfree


1 Answers

To expand on @Florian's comment, reading the LOCATION property of a target is an error by default in today's CMake versions. The documentation for CMake Policy 0026 clearly describes why this is the case:

CMake 2.8.12 and lower allowed reading the LOCATION target property (and configuration-specific variants) to determine the eventual location of build targets. This relies on the assumption that all necessary information is available at configure-time to determine the final location and filename of the target. However, this property is not fully determined until later at generate-time.

After reading the LOCATION property, it can later be changed using generator expressions. CMake allows you to disable this policy, by setting it to the OLD behavior explicitly:

cmake_policy(SET CMP0026 OLD)

Just take the result with a grain of salt, as it may change!

If you're going to change the policy (instead of simply removing LOCATION from the list of properties), it is best to use OLD CMake policies in isolation. When we're done using the OLD behavior, we can POP the old policy off the CMake policy stack to resume using the NEW behavior. Here's the example you referred to, modified to demonstrate usage of the policy change:

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()
like image 61
Kevin Avatar answered Sep 22 '22 11:09

Kevin