[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