[cmake-developers] INTERFACE_LINK_LIBRARIES property?

Stephen Kelly steveire at gmail.com
Thu May 30 05:31:19 EDT 2013


Brad King wrote:

> On 05/10/2013 06:41 AM, Stephen Kelly wrote:
>> * http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/5680
>>   (New INTERFACE_LINK_LIBRARIES policy approach)
> 
> I remember being quite happy with the proposal I made at the start of
> that thread.  Let's see if we can come up with something equivalent.
> For reference, the key sections of my message were:
> 
> On 12/22/2012 10:22 AM, Brad King wrote:
>> First I'll define how the properties behave when building a target.
>> I'll cover exporting below.
>>
>> In the OLD behavior the link interface is completely determined as
>> it is in CMake 2.8.10 by the LINK_INTERFACE_LIBRARIES(_<CONFIG>)
>> properties.  The target_link_libraries command will populate the
>> properties as it does now and leave the new names untouched.
>>
>> In the NEW behavior the link interface is completely determined
>> by the new INTERFACE_LINK_LIBRARIES property.  All forms of tll()
>> including its LINK_INTERFACE_LIBRARIES mode will populate only
>> the new properties.  The old property is completely ignored.

Any thoughts on adding PUBLIC PRIVATE and INTERFACE keywords to tll for 
consistency with the other target_* commands?

 http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/6864/focus=6886

>> When the policy is not set (internally it is WARN) then tll()
>> will populate both the old and new properties.  ComputeLinkInterface
>> will compute both the old and new style link interfaces, warn if
>> they are different, and use the old one.

Ok.

> ...
>> Now, on to exporting.  Unlike the previous iteration the policy
>> affects it too.
>>
>> When the policy is OLD/WARN we export only the old interface and
>> not the new interface.
>>
>> When the policy is NEW we export only the new interface and not
>> the old interface by default.  We can have a new property to
>> explicitly request that the old link interface properties be
>> exported.  We can either ask projects to set the old interface
>> properties manually for export or try to compute the values from
>> the new ones by pre-evaluating the generator expressions for
>> each configuration.  This will allow projects to support older
>> CMake versions for their clients if they want to, but it will
>> be an explicit decision.

Yes.

> Now, returning to your message:
> 
> On 05/10/2013 06:41 AM, Stephen Kelly wrote:
>> If the new property is introduced, the behavior would be:
>> 
>> * If an in-buildsystem or IMPORTED target has the new property, it is
>> used
>>   and the old properties are not used.
> 
> For in-build targets this needs to depend on the policy setting as in my
> quote above.  The behavior of the project's build should not depend on
> the version of CMake currently running, but rather the behavior intended
> by the project author.  The intention is implied by the policy setting
> or lack of one.

Right.

> For IMPORTED targets I think your proposal is correct: use the new
> property if it is set and otherwise use the old property.  It is up to
> the provider of the imported targets to specify the old and/or new
> properties correctly to handle various CMake versions for consumers.

Right.

>> * When a target is install(EXPORT)ed, the new property will be exported.
> 
> ...when the policy is NEW.  When it is OLD/WARN we export only the old
> properties.

Ok.

>> ** There needs to be a way to determine whether to additionally export
>> the
>>    old properties. Even if the exporting target does not have the old
>>    properties set, we can still conditionally write the content of the
>>    new INTERFACE_LINK_LIBRARIES to IMPORTED_LINK_INTERFACE_LIBRARIES, as
>>    both now support generator expressions. This will allow exporting
>>    projects to maintain compatibility with downstreams using CMake 2.8.11
>>    (or earlier if generator expressions are not used).
> 
> Yes, and the install(EXPORT) option you proposed can work for that.
> If possible I'd like to try to (partially) evaluate the $<CONFIG>-type
> expressions to set the old per-config properties.  That will make it easy
> for packages to support the old properties for CMake < 2.8.11.

I'm still not a fan of partial evaluation like that. It would be complex and 
a source of bugs for little gain.

>> ** If the old properties and the new property are set, we export them
>>    all. This will allow exporting projects to maintain compatibility with
>>    downstreams using CMake < 2.8.11. It is ok if the new
>>    INTERFACE_LINK_LIBRARIES and the old LINK_INTERFACE_LIBRARIES have
>>    differing content and no warning is issued. The new property may
>>    simply contain new genex-powered-convenience, similar to how QtCore
>>    now conveniently links to the qtmain.lib now on Windows.
> 
> Perhaps whatever install(EXPORT) option exports the old properties can
> also somehow indicate whether to use the project's settings for the old
> properties or try to generate values automatically from the new ones.

I'd prefer not to try to magically generate things like that. It would be 
complex and a source of bugs.

> This will give projects a choice on whether they want to populate the
> old properties explicitly or ask CMake to do it for them.

Rather than offer so much choice for something which is pure backwards-
compatibility (and therefore obsolete from the start), I'd prefer to offer 
only one way - user specified old properties.

>> * target_link_libraries signatures will populate the new
>>   INTERFACE_LINK_LIBRARIES property. There will need to be a way to make
>>   it additionally conditionally populate the old properties.
> 
> See my proposed approach quoted above for this.

You mean CMake magically determining the old properties from the new one?

> 
>> So, the primary thing to determine is whether to export the old
>> properties, which is related to whether they get populated by tll().
> 
> I don't think they are related.  The policy I proposed will determine
> which properties define the link interface and how the link interface
> is represented on export.  When the policy is OLD/WARN nothing changes.
> When the policy is NEW we use/export only the new properties unless a
> keyword explicitly says to populate the old.

Ok.

>> With the policy, the required tll signature, and new property, the
>> implementation is never the interface for shared libraries.
> 
> Since I'm vetoing "the required tll signature" we need another way
> to achieve this.  One of the confusing things about use of the old
> tll() signature is that it seems to populate the public link interface
> until one uses one of the newer signatures and suddenly all the other
> "public" entries disappear.

Agreed.

> I think we can solve both problems with
> a second new policy (distinct from the other policy discussed outside
> this paragraph) that simply disallows use of the old signatures
> (plain tll and LINK_INTERFACE_LIBRARIES mode)

This seems very similar to the proposal I made ('I'd propose deprecating 
with a policy the signature...') that you vetoed. Is it just a refinement of 
what I proposed?

> and the new signature
> (LINK_PUBLIC/LINK_PRIVATE) for a single LHS.  If a project uses *only*
> the new signature then we never need to use "the implementation is the
> interface" for shared libraries.  If a project uses *only* the old
> signatures then the existing behavior continues to work.

Yes, I think this is also what I proposed. Although I still propose 
deprecating LINK_PUBLIC/LINK_PRIVATE for PUBLIC/PRIVATE for consistency with 
the new commands.

>> The policy would also determine whether the new or old link interface
>> property is populated by the command. The value of the policy is
>> determined when the foo target is created.
> 
> Yes, that is consistent with my above-quoted proposal.  The tll signatures
> that explicitly populate the link interface will simply choose which
> properties to populate based on the policy.

Yes.

>> When the policy is switched to NEW, exporting projects can simultaneously
>> use a new keyword to install(EXPORT) to make it duplicate the
>> INTERFACE_LINK_LIBRARIES as old property names.
> 
> Yes, as discussed above.
> 
>> So, the API difference would be
>> 
>>  install(EXPORT fooTargets ...) # Export only new properties
>> 
>> vs
>> 
>>  install(EXPORT fooTargets GEN_OLD ...) # Export new and old properties
>> 
>> I don't mind what the keyword is.
> 
> Yes, and the keyword is an error when the policy is not NEW.
> Perhaps "EXPORT_LINK_INTERFACE_LIBRARIES"?

Yes, that seems fine.

>>  # Else as (A) ...
>>  set_property(TARGET foo PROPERTY LINK_INTERFACE_LIBRARIES_COVERAGE bat)
>>  install(EXPORT foo bar bat ...)
>>  
>> In this case, if the policy is NEW, the export line reports an error
>> because a LINK_INTERFACE_LIBRARIES_<foo> property is set.
> 
> Yes, something like this.
> 
> In my proposal when the policy is NEW the old properties are ignored
> and the link interface is fully determined by the new property.
> Therefore when processing an export that does not request that the
> old properties be populated by the project's own values we should
> generate an error if it sets them.

Yes.

Thanks,

Steve.





More information about the cmake-developers mailing list