Evaluating effective target setting via generator expression

Hi,

I want to add a link flag when the target effectively used LTO optimization. So somwhere top-level I write:

add_link_options ( $<$<BOOL:$<TARGET_PROPERTY:INTERPROCEDURAL_OPTIMIZATION>>:-flto=8> )

This works, if I set this property directly on the target or by setting CMAKE_INTERPROCEDURAL_OPTIMIZATION globally.

However, the cases are more difficult as there are also properties with the _<CONFIG> suffix that override this property.

Q1:
How do I check in a generator expression that a property is actually set?

Additionally, there are also directory properties with these names. However, the above generator expression does NOT evaluate the directory expression. So if the property is set for the directory (or any parent directory) but not for the target directly and not via global variable, the generator expression evaluates to false :frowning:

Q2:
How do I get the effective setting? Is that even possible with generator expressions?

Taking the last question first,

Not as such, no. “Effective setting” isn’t even really a correct way of describing it, since as the cmake-generator documentation says:

generator expressions are evaluated during generation of the buildsystem, and not during processing of CMakeLists.txt files

IOW,

target_link_options(targetname PRIVATE
  $<$<BOOL:$<TARGET_PROPERTY:foo>>:bar>)

doesn’t evaluate the foo property of targetname and insert bar into the LINK_OPTIONS property if it evaluates to true. It literally inserts $<$<BOOL:$<TARGET_PROPERTY:foo>>:bar> into the LINK_OPTIONS property (a ;-separated list). The generator expression isn’t evaluated until the build system is being generated, after the processing of CMakeLists.txt is completed.

That’s true, but all you really care about is the current config. So, you could do this:

target_link_options(${target_name} PRIVATE
  $<$<TARGET_PROPERTY:INTERPROCEDURAL_OPTIMIZATION>:-flto=8> 
  $<$<TARGET_PROPERTY:INTERPROCEDURAL_OPTIMIZATION_$<CONFIG>>:-flto=8>
)

Correction: You should be able to do that (in fact there are even examples in the documentation written that way), but for some reason in my testing it doesn’t actually work. (I end up with “Expression did not evaluate to a known generator expression” errors.) To get around that, it has to be written in the form you had it:

target_link_options(${target_name} PRIVATE
  $<$<BOOL:$<TARGET_PROPERTY:INTERPROCEDURAL_OPTIMIZATION>>:-flto=8> 
  $<$<BOOL:$<TARGET_PROPERTY:INTERPROCEDURAL_OPTIMIZATION_$<CONFIG>>>:-flto=8>
)

Not sure why that’s the case.

Right, generator expressions can only examine target properties. If a property is set at DIRECTORY, SOURCE, or any other scope, a genex can’t see it.

But I don’t think this is actually as much of a problem as it may seem. Don’t forget, you are the one defining the build system config. IOW, a property doesn’t just magically “get set” at directory scope, out of thin air — you set it that way, if you choose to.

If you want to set the INTERPROCEDURAL_OPTIMIZATION property on a directory basis, then you should check it with get_property(_some_var DIRECTORY ...) and use $<$<BOOL:${_some_var}>:-flto=8> to set the flag on the target.

If you choose to use set_property(TARGET targetname PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) instead, then you can use a $<TARGET_PROPERTY> generator expression.

But in most cases that’ll be totally up to you either way. Unless you’re writing a library of CMake code and have no control over the larger configuration. Then, for maximum flexibility, you may have to do “all of the above”.