[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