[cmake-developers] Generator expressisons in target properties

Stephen Kelly steveire at gmail.com
Tue Nov 6 14:07:16 EST 2012


Brad King wrote:

> On 11/06/2012 12:00 PM, Stephen Kelly wrote:
>> The include directories and compile definitions are set by the
>> target_link_libraries command.
> 
> ...by adding generator expressions, right?  They won't be evaluated
> until much later.

Yes. 

> 
>> It might make sense to add a policy for that
>> feature, as otherwise the order of include directories would change, eg:
>> 
>>  add_executable(foo ...)
>>  target_link_libraries(foo bar bat)
>>  include_directories(${bat_INCLUDE_DIRS} ${bar_INCLUDE_DIRS})
> 
> How do you propose to trigger this policy warning?  At no one point
> while processing the above commands do we know whether the order
> changes.

True, I don't know how to warn about it. Does that mean that a policy is 
entirely unsuitable? Or does it mean we can't build this functionality into 
tll() after all?

> 
>> I propose that
>> 
>>  target_link_libraries(foo LINK_INTERFACE_LIBRARIES bar)
>> 
>> should be allowed for an imported foo, but
>> 
>>  target_link_libraries(foo bar)
>> 
>> remains not-allowed.
> 
> Okay.  The only purpose of it is to set properties while processing the
> debug/optimized keywords anyway.

In my branch it also sets the INTERFACE_INCLUDE_DIRECTORIES and 
INTERFACE_COMPILE_DEFINITIONS.

> 
>> As I introduced the INTERFACE_LINK_LIBRARIES property, I also introduced
>> a backward-compatibility feature to also read the old IMPORTED*_<CONFIG>
>> properties. I don't know enough about cmComputeLinkDepends to know if
>> that's ok.
> 
> I don't think we should honor both properties at once.  If the new
> name is set the old names should be ignored (perhaps with a warning if
> an old name is set too).

That could be an option. I think it gets complicated though. 

1. In my branch I made tll() populate the INTERFACE_LINK_LIBRARIES prop
2. Exports generate INTERFACE_LINK_LIBRARIES on imported targets if set
3. The maintainer of the library may have also set 
INTERFACE_LINK_LIBRARIES_DEBUG
4. A consumer of the library might build it with CMake 2.8.11, and when 
using the imported target, the INTERFACE_LINK_LIBRARIES (autopopulated by 
tll()) will be used and the INTERFACE_LINK_LIBRARIES_DEBUG will be ignored. 
The maintainer might not be aware of CMake 2.8.11 yet, and so it would 
appear to be a backward incompatible change.

> 
> A common use of LINK_INTERFACE_LIBRARIES is to be empty so this
> does not look correct:
> 
>  -  if(!explicitLibraries &&
>  +  if(explicitLibraries.empty() &&

Ok, I'll think more about it.

>> I asked before for more information about why direct depends are
>> separated from transitive ones. The reason seems to be related to
>> ordering of the
> 
> Yes.  If you read and understand cmComputeLinkDepends in detail you will
> see there is no way to implement the current logic without keeping these
> separate.
> 
>> depends when invoking the linker, which is relevant for static libraries
>> (but not shared libraries, right?).
> 
> It's platform dependent IIRC.  On some platforms order doesn't even matter
> among static libraries.  On others order matters among both.

Yes, I read the comment and implementation in cmComputeLinkDepends, but I 
didn't fully understand the motivation. This is good enough for me though.

>>  add_library(iface INTERFACE)
>>  set_property(TARGET iface PROPERTY INTERFACE_LINK_LIBRARIES foo bar)
>>  target_link_libraries(test_exe directdep1 iface directdep2)
>> 
>> It is not really equivalent to this:
>> 
>>  target_link_libraries(test_exe directdep1 foo bar directdep2)
>> 
>> But maybe it should be, or maybe I would want it to be? Maybe we can make
>> it possible to populate the non-INTERFACE LINK_LIBRARIES property on
>> libraries of type INTERFACE_LIBRARY to use the contents as direct depends
>> of test_exe?
> 
> 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. 

In that case INTERFACE_LIBRARY might not be the best name for it. Maybe 
SUBSTITUTE would be better.

>> I'm thinking of simply removing the memoization from cmTarget.
> 
> Sure, they are only an optimization.  Get things correct first and
> optimize later.

What I'm proposing is removal of an existing optimization, but ok I'll go 
ahead and do that.

>>  add_library(boost::core INTERFACE IMPORTED)
> 
> Side question: Does the "IMPORTED" status of an INTERFACE have any
> real meaning?  It won't build anything in the project either way.

I thought about this too, but I haven't thought it through fully yet. I do 
want INTERFACE_LIBRARYs to be install(EXPORT)able (for the boost use-case), 
and that is not possible for IMPORTED libraries.

I haven't yet thought through whether it makes sense to allow or disallow 
install(EXPORT)ing an INTERFACE_LIBRARY imported from elsewhere. If it has 
other IMPORTED targets in its interface, then it probably doesn't make sense 
to allow it.

Thanks,

Steve.





More information about the cmake-developers mailing list