[cmake-developers] conditionals in generator expressions
Stephen Kelly
steveire at gmail.com
Sun Aug 19 17:43:35 EDT 2012
Brad King wrote:
> On 08/14/2012 05:11 AM, Stephen Kelly wrote:
>> Thanks, I'll see what I can figure out.
>>
>> I think at this point, I'm more interested in linking to a library based
>> on the content of a target property (ie, linking QT_QTMAIN_LIBRARY based
>> on whether WIN32_EXECUTABLE is set), so I may need to expand it along the
>> lines you did for $<CONFIG:> first.
>
> I rebased the topic after the sweeping changes and merged it to next.
> Please fetch "generator-expression-conditions" from the topic stage
> and base your work on that instead.
Thanks, here are my findings so far, which relate to my extension of that
branch at git at gitorious.org:~steveire/cmake/steveires-cmake.git:
1) The result string of the $<CONFIG:...> expression does not allow lists.
That means we can't do anything like this:
include_directories("$<$<CONFIG:Release>:/foo;/bar/bat>")
include_directories("$<$<CONFIG:Release>:${somedirs}>")
# somedirs might contain a list
I fixed that in my branch by modifying cmSystemTools::ExpandListArgument.
2) Because of the way generator expressions are parsed, the > character
can't be part of the result string. This is an unlikely but possible
character to appear in include directories for example.
This seems to be because the generator expression can start and end anywhere
in the input string to the Process method, instead of assuming that the
start of the string is the start of the generator expression, and the end is
the end of it. The latter probably makes more sense in the context of target
property generator expressions. Eg, I'd prefer this to be illegal:
include_directories("/tmp/$<$<CONFIG:Release>:foo/>bar")
# Could include /tmp/bar or /tmp/foo/bar, but not very readable.
Can this be changed? If it would break existing users of generator
expressions, maybe we can enforce complete-string-generator-expressions if
it is being used on a target (eg if (this->Target) inside Process() on my
branch).
3) I can add something like $<TARGET_INTERFACE_INCLUDE_DIRS:tgt> in the
future to expand to the interface include directories of a target (currently
cmake has no such concept, but I'm thinking in the future).
However, I don't think something like
$<$<CONFIG:Release>:$<TARGET_INTERFACE_INCLUDE_DIRS:tgt>>
would work, would it? The 'right hand side' of the expressions must be the
final string?
That was mostly just a thought experiment though. There wouldn't be any real
need for TARGET_INTERFACE_INCLUDE_DIRS to be a generator expression instead
of a static property on a target. If that is to be conditional on something
like CONFIG:Release, that can just be in a generator expression in that
TARGET_INTERFACE_INCLUDE_DIRS property anyway.
I can't really think of a situation that that would be needed, but it is an
interesting point which might be worth documenting.
4) I'm really not certain if I've implemented the patch for conditional link
libraries in the right place. I tried a few different locations. I'm also
not sure if there is logic at configure time which can't be implemented in
terms of the generator expressions which are not evaluated by then. I tried
using it with imported targets which had entries in their
IMPORTED_LINK_INTERFACE_LIBRARIES, which seemed to work, so that's
encouraging.
5) I think it's quite cool that I can add something like
set(_WIN32_EXE "$<AND:$<TARGET_PROPERTY_STREQUAL:TYPE,EXECUTABLE>,
$<TARGET_PROPERTY_BOOL:WIN32_EXECUTABLE>>")
target_link_libraries(Qt5::Core
LINK_INTERFACE_LIBRARIES
"$<${_WIN32_EXE}:Qt5::WinMain>"
)
and it will lie dormant and not have any effect on any shared libraries
until it is finally linked to an executable :). Several features come
together nicely there.
6) In my new implementation of cmTarget::GetIncludeDirectories, it is now
necessary for that method to only be called at generate-time. As far as I
can see, that is already true for that method, but for maintenance it is a
bit difficult. Are there other examples of similar requirements of when an
API can be meaningfully called? It seems to be something that could benefit
from refactoring throughout cmake if so.
Thanks,
Steve.
More information about the cmake-developers
mailing list