[cmake-developers] Setting the link interface and dependencies in one command

Brad King brad.king at kitware.com
Wed Oct 5 09:31:59 EDT 2011


On 10/4/2011 10:22 PM, Stephen Kelly wrote:
> 1) Change the meaning of LINK_INTERFACE_LIBRARIES in
>
> set_target_properties(foo LINK_INTERFACE_LIBRARIES bar)

Do you mean target_link_libraries, rather than set_target_properties?
The latter is a very general command and will not be taught special
behavior for certain properties.  I'm assuming you mean

   target_link_libraries(foo LINK_INTERFACE_LIBRARIES bar)

> set_target_properties(foo baz LINK_INTERFACE_LIBRARIES bar)

   target_link_libraries(foo baz LINK_INTERFACE_LIBRARIES bar)

> mean 'foo links against baz, but doesn't expose symbols from it; foo links
> against bar, and does export symbols from it'.

Currently this is actually a command mode, not a keyword.  It only works
with LINK_INTERFACE_LIBRARIES as the second argument.  Therefore the second
example is actually not valid right now.  The only ambiguity in this behavior
change would be in the first example.  However in the future the latter example
may mean "link to baz and put bar in the interface but do not link to it".

I'm not excited about adding another policy that affects linking behavior.
CMP0003 was a major disruption that caused a lot of confusion, but it was
worthwhile because it enabled proper generation of link behavior in cases
that were previously not even possible.  The proposed policy will affect
every single call to target_link_libraries that uses the interface mode.

Since we support repeated libraries on the link line we cannot even try
to avoid warning by detecting cases that the interface duplicates part
of the real link dependencies.  Every project that currently uses the
feature will need to be changed to avoid duplication.  Any project that
wants the new behavior will have to explicitly set the policy to NEW.
Someone coming back and reading the code later will have no idea from
the local context whether the call means interface-only or depend+interface
because the meaning depends on a policy setting made elsewhere.

Side Note:
When thinking about examples for this it is important to remember that
there can be multiple calls to target_link_libraries spread out all over
for the same target.  This is often used for cases of optional features with
optional dependencies.

> 2) Introduce another variable for doing the same thing as above.

s/variable/keyword argument to target_link_libraries/

The meaning of the target property "LINK_INTERFACE_LIBRARIES" will not change.
It must match the meaning of IMPORTED_LINK_INTERFACE_LIBRARIES in the case of
IMPORTED targets when the interface is the only thing to specify.  It also can
vary on a per-configuration basis, as in LINK_INTERFACE_LIBRARIES_<CONFIG>.

The only question is whether the target_link_libraries command can be modified
to change when it adds a link dependency and/or appends to the link interface.

> As David notes, this might be confusing without looking up docs

...but not as confusing as having to look around the rest of the project
source tree for a policy setting to know the meaning.  David was asking that
the new option be well-named to avoid confusing it with the current option.

> behaviour of LINK_INTERFACE_LIBRARIES (do not actually link to the things
> listed there) doesn't have a use-case

I'm reserving this use case for a future type of (virtual) target that does
not actually have a library file but can specify a link interface on other
real libraries.  Besides, the meaning of the LINK_INTERFACE_LIBRARIES target
property should not change as noted above.

> 3) Introduce a variable for doing the opposite of what

s/variable/keyword argument to target_link_libraries/

> LINK_INTERFACE_LIBRARIES does. That is, the equivalent of the above would be
>
> set_target_properties(foo bat LINK_DEPENDENT_LIBRARIES baz)

   target_link_libraries(foo bat LINK_DEPENDENT_LIBRARIES baz)

This may have confusing interaction with the LINK_INTERFACE_LIBRARIES keyword
argument.  In the above example the presence of LINK_DEPENDENT_LIBRARIES for
baz would have to imply LINK_INTERFACE_LIBRARIES for bat.  Then a later

   target_link_libraries(foo other libs with no keyword)

call would suddenly add only link dependencies and not the interface even
though the LINK_INTERFACE_LIBRARIES keyword never appears in any call.

> My preference is (1).

We need to use (2) with a well-chosen name.

> Does anyone know the reason for the current behaviour?

Only a command with "link_libraries" in its name should add link dependencies.
Setting the LINK_INTERFACE_LIBRARIES property should not add new link rules
for the target on which it is set.

Originally the link interface could be set only by the property.  Then when
people kept using ${FOO_LIBRARIES} in the property it caused confusion because
those variables often contain "debug" and "optimized" keyword arguments that
are meaningful only to the target_link_libraries command.  Then we added the
option to that command to set the property by taking the keywords into account.

This was all new enough at the time that we didn't want to think about how to
make the same command do both.

-Brad



More information about the cmake-developers mailing list