[cmake-developers] INTERFACE_LINK_LIBRARIES property?

Stephen Kelly steveire at gmail.com
Fri May 10 06:41:39 EDT 2013


Brad King wrote:

> On 05/06/2013 12:44 PM, Stephen Kelly wrote:
>> I'm not sure what you mean by 'for now'?
> 
> I meant we could drop it and move on but not rule out the possibility
> of someday moving to it for consistency and (eventual) simplicity.
> 
>> I'd prefer not to introduce INTERFACE_LIBRARY with support for the
>> old-style interface if there will eventually be a new-style.
> 
> Perhaps we can look at reviving it but we'll have to re-work the
> policy to handle generator expressions in the old interface as
> you pointed out.  Can you please take a stab at proposing the
> new form of the policy (in design only, no code yet).

For reference, here's some old threads:

* http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/5398
  (Policy for INTERFACE_LINK_LIBRARIES)

* http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/5526
  (Setting include directories via target_link_libraries() ?)

* http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/5680
  (New INTERFACE_LINK_LIBRARIES policy approach)

* http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/5734
  (Interface includes and defines plumbing)

* http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/5904
  (Setting includes, defines and other usage requirements with one command)


In summary, we spent some time discussing INTERFACE_LINK_LIBRARIES while at 
the same time discussing the tll-vs-new-command question and various options 
for how to implement the plumbing.

Eventually, without fanfare and apparently without discussion on the mailing 
list, I abandonned that INTERFACE_LINK_LIBRARIES property in early January 
and added genex support to the properties matching 
(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? instead. The topic was 
merged in c0c8ef85fc8d65a47abfd293031bcde91e7ee930. This meant that the
complexity of issues associated with introducing the new property were 
worked-around - namely which properties to install(EXPORT).

The initial justification for replacing the old properties with the new one 
was so that targets would have property content like this using a uniform 
property name:

 LINK_LIBRARIES $<TARGET_PROPERTY:foo,INTERFACE_LINK_LIBRARIES>

That became irrelevant long ago as it was based on my misunderstanding about 
how link lines are determined.

Other justifications for the new property remain:

* Name consistency with INTERFACE_INCLUDE_DIRECTORIES and 
  INTERFACE_COMPILE_DEFINITIONS
* Not having a <CONFIG> suffix, which is no longer needed because of genex 
  support
* Consistency of access to the link interface. For static imported targets, 
  the old IMPORTED_LINK_INTERFACE_LIBRARIES property contains the link 
  interface, but for non-imported static libraries the old 
  LINK_INTERFACE_LIBRARIES does not.
* We may in the future find a need and justification for a genex like 
  $<IS_LINKED:foo> which determines whether foo is linked. The i
  implementation of that genex would be a lot simpler if it needed to 
  support only one property. This may be unlikely however. Currently
  properties like COMPATIBLE_INTERFACE_* solve similar problems that a 
  $<IS_LINKED> would solve.
* We can have empty INTERFACE_LINK_LIBRARIES on shared libraries by default.
* ??


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.

* When a target is install(EXPORT)ed, the new property will be exported. 
** 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).
** 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.

* 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. There needs to 
  be a final-migration-moment where projects no longer export targets with 
  the old properties.

* If the INTERFACE_LINK_LIBRARIES property is read on a static non-imported 
  library, its LINK_LIBRARIES property is returned.

* When exporting, if 'the implementation is the interface'


So, the primary thing to determine is whether to export the old properties, 
which is related to whether they get populated by tll().

I'd propose deprecating with a policy the signature

 target_link_libraries(foo bar)

and require that a public/private/interface keyword is present for all usage 
of it. 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.

Existing code could look like this:

A)

 add_library(foo SHARED|STATIC ...)
 tll(foo bar)
 # install(TARGETS) and proper export name omitted
 install(EXPORT foo bar ...) 

In this case, if the policy is NEW, we report an error on the tll line. If 
the policy is OLD, we populate both the new and the old link interface 
properties.


B)

 # Else as (A) ...
 tll(foo LINK_PUBLIC bar)

In this case, if the policy is NEW, we populate only the new property. If 
the policy is OLD, we populate both the new and the old link interface 
properties.

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. 

An error is reported (see below) if the target has populated old properties 
as a result of a set_property() for example so we don't have to worry about 
overwriting user-defined content. tll can't result in old property 
population for foo as the policy is determined early.

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.

C)
 
 # 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. This can't reliably be 
encoded into the new INTERFACE_LINK_LIBRARIES property on export. The 
exporting project needs to be ported to use generator expressions instead. 
This results in the CMake requirement of their downstreams to necessarily be 
bumped to CMake 2.8.11.


Thanks,

Steve.





More information about the cmake-developers mailing list