define_property on target has no effect?

kfsone/cmake-defprop: Cmake “define-property” validation (github.com)

Am I misusing/misunderstanding define_property?

CMake documentation suggests that using define_property will cause get_target_property to return no value if the property is defined as a TARGET property and INHERITED .

I wanted to use target properties on INTERFACE libraries to allow me to forward runtime file requirements on INTERFACE libraries so that post-build functions can be called naively and simply consume the list of runtime requirements if they are inherited up to a target.

# (wow, I really botched this line in the description originally)
define_property (TARGET PROPERTY runtime_stuff INHERITED)
if (complex-conditional)
  set_target_properties (libsoandso PROPERTIES runtime_stuff strings.bundle config.ini)
endif ()


function (post_build_soandso TARGET)
    get_property (runtimes ${TARGET} runtime_stuff)
    if (runtimes)
        add_custom_command ...
    endif ()
endfunction ()

This doesn’t work, because runtimes gets set to runtimes-NOTFOUND.

While not the worst thing in the world, it’s a weird case to try and teach.

    get_property (runtimes ${TARGET} runtime_stuff)
    if (runtimes AND NOT ${runtimes} STREQUAL "runtimes-NOTFOUND")

this is not something I expect developers who aren’t living in CMake to get right, so define_property promises to give me a better behavior.

It doesn’t appear to work, though.

CMake treats a variable whose value ends in -NOTFOUND as false (this is documented in the docs of the if() command). So if you do this:

set(var var-NOTFOUND)
if(var)
  message(FATAL_ERROR "")
endif()

you will not get an error. So if your actual code contains the if as you described, it should work. If it doesn’t, the problem is somewhere else.

1 Like

It gets treated as false, but it also expands out to a string. My reading of ‘define_property’ documentation is that it would cause the get_property outvar to have no value, not a value that will be inconvenient in anything but a boolean context.

get_property(runtimes ${TARGET} runtime_stuff)
add_custom_command (${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${runtime_stuff} $<TARGET_FILE_DIR:${TARGET}> COMMAND_EXPAND_LISTS)

is not happy when this expands to

cmake -E copy_if_different runtimes-NOTFOUND .../build/.../target.dir

This command is not well-formed. It should be one of the following alternatives:

get_property(runtimes TARGET ${TARGET} PROPERTY runtime_stuff)
get_target_property(runtimes ${TARGET} runtime_stuff)

If the property is not defined, get_property() returns an empty string, but get_target_property() returns runtimes-NOTFOUND. Use the former if you want an empty string in this scenario.

1 Like

Oh, heck; thanks.

Is there a reason that define doesn’t affect get_target_property? (I’m guessing scope)

I assume you mean define_property(), not define(). There’s no difference in what get_property() and get_target_property() see as target properties. Both commands see the property as not defined. The difference is in what they give back when the property isn’t defined, and that difference has nothing to do with the define_property() command.