[cmake-developers] INTERFACE targets (Was: Generator expressisons in target properties)

Stephen Kelly steveire at gmail.com
Fri Nov 16 12:56:08 EST 2012


Stephen Kelly wrote:
>>>> Yes, interfaces should be flattened and replaced with their content.
>>> 
>>> So the INTERFACE_LINK_LIBRARIES property would be handled differently
>>> for an INTERFACE_LIBRARY than a SHARED_LIBRARY. I think that's a bit
>>> confusing.
>> 
>> An interface wrapping around a single other library should be equivalent
>> to defining the interface directly on that other library.  The logical
>> name of the interface target is kind of like a generator expression when
>> referenced in INTERFACE_LINK_LIBRARIES.  Wherever it is you process the
>> generator expressions, first transform "myinterface" to
>> $<TARGET_PROPERTY:myinterface,INTERFACE_LINK_LIBRARIES> or something
>> like that.
> 
> Having thought about it more, I think that using
> 
>  tll(foo iface)
> 
> should not flatten. If the user explicitly wants flattening, I think they
> should have to use
> 
>  tll(foo $<$<TARGET_PROPERTY:iface,INTERFACE_LINK_LIBRARIES>)
> 
> or even
> 
>  tll(foo $<CONSUME:iface>)
> 
> or whatever.
> 
> Maybe we can come back to this point later after the rest is in place and
> we'll see the use-cases for flattening and not flattening.

I've thought some more about the topic of targets which do not create any 
output files or binaries themselves, but which provide an interface to a 
group of other targets.

Whatever solution we come up with to do that, I'd like it to be consistent 
with other types of targets. The way I see it, these are the options:

1) cmTarget::INTERFACE_LIBRARY

A target on which the user may only set values for whitelisted properties, 
such as INTERFACE_INCLUDE_DIRECTORIES, INTERFACE_COMPILE_DEFINITIONS, 
INTERFACE_LINK_LIBRARIES etc. 

When a target of this type is used, the INTERFACE_* properties are processed 
by, eg cmComputeLinkInformation in the same way as they are processed for a 
SHARED_LIBRARY. 

That is, the value in the property is not 'inlined' to behave as if it was a 
direct dependency of the depender - That would be inconsistent and would 
require knowledge of the person writing the cmake files about what is the 
type of a target being used in a tll() call.

The name of this type is consistent with the INTERFACE_ properties. This is 
what is already in my branch.

2) cmTarget::INLINED_LIBRARY or INLINE_CONTAINER_LIBRARY

A target on which the user may only set values for whitelisted non-
INTERFACE_* properties, such as INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS, 
LINK_LIBRARIES etc. 

The values in the properties are inlined into the target properties, or its 
INTERFACE_ variants. That is, given:

 add_library(myinlined INLINED_LIBRARY)
 set_property(TARGET myinlined PROPERTY LINK_LIBRARIES bling)

This adds bling to the LINK_LIBRARIES of foo:

 target_link_libraries(foo LINK_PRIVATE myinlined)

This adds bling to the LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES of foo:

 target_link_libraries(foo LINK_PUBLIC myinlined)

(Note, we may need to add a way to use 
 target_link_libraries(foo INTERFACE_LINK_LIBRARIES myinlined)
or 
 target_link_libraries(foo INTERFACE myinlined)
to add to only a new-style INTERFACE.
)

3) cmTarget::MIXIN_LIBRARY

A target on which the user may only set values for whitelisted properties, 
such as INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS, LINK_LIBRARIES, 
INTERFACE_INCLUDE_DIRECTORIES, INTERFACE_COMPILE_DEFINITIONS, 
INTERFACE_LINK_LIBRARIES etc. 

The values in the properties are inlined into the target. That is, given:

 add_library(mymixin MIXIN_LIBRARY)
 set_property(TARGET mymixin PROPERTY LINK_LIBRARIES bling)
 set_property(TARGET mymixin PROPERTY INTERFACE_LINK_LIBRARIES plong)

All of the following have the same effect:

 target_link_libraries(foo mymixin)
 target_link_libraries(foo LINK_PUBLIC mymixin)
 target_link_libraries(foo LINK_PRIVATE mymixin)

namely, bling is appended to the LINK_LIBRARIES of foo, and plong is 
appended to the INTERFACE_LINK_LIBRARIES of foo.



Can you think of any other possibilities? 

Although they are not mutually exclusive, I don't think we need to add more 
than one of them. I'm not really sure 3) is useful. 1) can be turned into 2) 
by the user by using a generator expression, that is 

 target_link_libraries(foo 
    $<TARGET_PROPERTY:iface,INTERFACE_LINK_LIBRARIES>
 )

or a PUBLIC variant instead of 

 target_link_libraries(foo iface)

Because of that, I think my preference is to use 1). I don't like non-
explicit inlining.

Any thoughts on that?

Thanks,

Steve.





More information about the cmake-developers mailing list