[cmake-developers] Generator expressisons in target properties (was Re: conditionals in generator expressions)

Stephen Kelly steveire at gmail.com
Mon Oct 22 13:24:38 EDT 2012


Stephen Kelly <steveire at ...> writes:

> 
> Brad King wrote:
> >> The only option I see that might work is to extend the undefined behavior
> >> documentation of the LOCATION* properties to cover use of generator
> >> expressions with link libraries, and then try to refactor/copy the code
> >> out of cmTarget to cmGeneratorTarget to add the generator expressions
> >> feature.
> > 
> > I think this limitation is perfectly acceptable.
> 
> Great, thanks.

I've implemented this so it's ready for 2.8.11. Together with making export()
function at generate time instead of configure-time, I was able to refactor the
rest of CMake to use cmGeneratorTarget, and therefore to be (almost) able to use
generator expressions for link libraries.

That's in the use-generator-target-2 branch in my clone. 

git://gitorious.org/~steveire/cmake/steveires-cmake.git 

I'll rebase and submit the contents of it in several parallel branches when
2.8.11 opens. I'll also fix the style issues in the commits etc.

Also in my clone is the interface-target-properties branch. The commits there
'finish' the work needed to make linking work with generator expressions. 

The way I've implemented it there is to populate a LINK_LIBRARIES property as a
result of calling target_link_libraries. The INTERFACE_LINK_LIBRARIES property
can also be populated on a target, and it 'chains', which means that the
INTERFACE_LINK_LIBRARIES from the dependency tree are all processed, and the DAG
checker ensures there are no cycles in their content.

That chaining is whitelisted in the cmGeneratorExpressionEvaluator because it is
necessary to set up a DAG checker before evaluating. So, the properties that are
whitelisted are the properties that always get a DAG checker set on them before
they are evaluated.

When linking to a target, the INTERFACE_LINK_LIBRARIES are automatically used
too. The content of the INTERFACE_LINK_LIBRARIES is assumed to be mandatory, so
this makes sense. 

For backwards compatibility, the debug and optimized keywords are also processed
into generator expressions using $<CONFIG:...>.

A side-effect of using generator expressions in the LINK_LIBRARIES property in
this way is that all libraries will appear to be in the link implementation, and
may appear again when processing the link interface. I don't know the
consequences of that, if any.

For now I consider the (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?
properties obsolete and replaced by INTERFACE_LINK_LIBRARIES. I don't have any
magic to read the old property when asked for the new one etc. This is mostly
for simplicity, and because the IMPORTED and non imported old-properties have
slightly different meanings (see the comments in ), but I may investigate
further if magic is appropriate. 

Something I am certain of though is that the new name is needed for consistency
with other new properties (INTERFACE_*) and for removal of the requirement for
the IMPORTED_ prefix on imported targets. Both properties can be generated in
export() and install(EXPORT) anyway, and really I expect minimal impact from
this part. 

I've also come around to the idea that 

 target_link_libraries(foo bar)

should be enough to make foo compile and link with bar, removing the need for a
new target_use_targets command and removing the need to populate the
INCLUDE_DIRECTORIES of foo through include_directories() or otherwise, if bar
has an appropriate interface. 

The reason I've accepted that target_link_libraries() is enough is that in order
to link to bar, the include directories must be there when compiling, and in
order to use the headers of bar, the appropriate COMPILE_DEFINITIONS must be
used too. Similiarly, the appropriate COMPILE_OPTIONS (eg PIC) must be used too.
As all of that is a prerequisite for linking anyway, and as it means adding the
feature in a source-compatible way with existing CMake code, I think it's better
to use target_link_libraries. Any duplication resulting from that is already
removed for includes and defines, and we can add the same uniq on
COMPILE_OPTIONS etc.

In my branch I pseudo-implement part of that with some new generator expressions
which process the LINK_LIBRARIES property.

At this point, because multiple properties can use generator expressions, and
because several properties will depend on the content of the LINK_LIBRARIES
property, cycles in generator expressions become a problem for the first time
(up to now they haven't been). This is to be expected whenever a declarative
language is used. In the top commit in my clone I describe the problem more
fully, and a way which might work to break cycles like that, but which require
user-intervention. I don't think I have the full solution yet, so more ideas are
welcome.

Qt 5 (and Qt 4 if I can help it) and KDE will likely consume and produce
libraries taking advantage of this INTERFACE generator properties feature, which
will help drive adoption. Several modules in CMake would probably also benefit
from it (eg do any libraries in X11 depend on each other? PNG depends on LIBZ,
which is a really good and simple example which can use the feature), so part of
finishing this will be to port some of them to imported targets and the
INTERFACE properties too. 

As it is not source compatible to put imported targets into FOO_LIBRARIES where
paths were used before, I'd like to make a more-established convention of using
"ModuleName::LibraryName" which would be used by consumers of the libraries
instead of the _LIBRARIES variables. This is only a matter of documenting it as
a convention in Modules/readme.txt though anyway. The use of colons is good, as
I discovered, because makefile generators would reject them as names for 'real'
targets.

This stuff will come up again soon I'm sure, but I thought it would be a good
time to have a big-picture discussion now that I can see mostly what's going to
happen.

Any thoughts?

Thanks,

Steve.





More information about the cmake-developers mailing list