[CMake] Proposal: extra option PRIVATE for target_link_libraries

Michael Wild themiwi at gmail.com
Wed Dec 23 09:14:57 EST 2009


On 23. Dec, 2009, at 15:03 , Alexander Neundorf wrote:

> On Wednesday 23 December 2009, Michael Wild wrote:
>> On 23. Dec, 2009, at 14:36 , Alexander Neundorf wrote:
>>> On Wednesday 23 December 2009, Marcel Loose wrote:
>>>> Hi all,
>>>> 
>>>> I suggested this in the quite long thread "third party library
>>>> dependencies", but it may have been overlooked. Hence, I started a new
>>>> thread.
>>>> 
>>>> Upon (re)reading the Mandriva page
>>>> http://wiki.mandriva.com/en/Overlinking, I was thinking: maybe the issue
>>>> of overlinking can be solved more or less the same way as pkg-config
>>>> does: i.e. by defining private dependencies. This could be an extra
>>>> option to target_link_libraries.
>>>> Something like:
>>>> 
>>>> target_link_libraries(mylib public1 public2 PRIVATE private1 private2)
>>> 
>>> Assuming that public1 and public2 are libraries also built with cmake,
>>> that can be done already today:
>>> 
>>> add_library(public1 ...)
>>> target_link_libraries(public1 private1)
>>> target_link_libraries(public1 LINK_INTERFACE_LIBRARIES "")
>>> 
>>> add_library(public2 ...)
>>> target_link_libraries(public2 private2)
>>> target_link_libraries(public2 LINK_INTERFACE_LIBRARIES "")
>>> 
>>> install(TARGETS public1 public2 ... EXPORT MyPublicLibs)
>>> install(EXPORT ...)
>>> 
>>> 
>>> Then later on, when loading these exported targets, you will get what you
>>> want. If public1/2 are shared libs, their "link interface" will be empty.
>>> If they are static, you will link against everything they have been
>>> "linked" against, independent of the LINK_INTERFACE_LIBRARIES (which is
>>> used only for shared libs).
>>> 
>>> Alex
>> 
>> So, the last step in doing
>> 
>> add_library(public1 ...)
>> add_library(public2 ...)
>> target_link_libraries(public2 public1 private1)
>> target_link_libraries(public2 LINK_INTERFACE_LIBRARIES public1)
>> 
>> is equivalent to
>> 
>> set_target_properties(public2 PROPERTIES LINK_INTERFACE_LIBRARIES
>> "public1")
>> 
>> Am I right?
> 
> Yes, but if you use 
> target_link_libraries(public2 LINK_INTERFACE_LIBRARIES public1)
> it can handle the "optimized" and "debug" keywords, which may be contained in 
> some of the _LIBRARY/_LIBRARIES variables.
> 
>> So, this should definitely go somewhere on the Wiki, that when one creates
>> a project that does an install(EXPORT ...) and provides a XXX-config.cmake
>> file, that one should carefully use target_link_libraries(...
>> LINK_INTERFACE_LIBRARIES ...) to make things play nicely.
>> 
>> This doesn't solve the problem for non-cmake built libraries which are
>> discovered through FindXXX.cmake modules, though.
> 
> Well, partly. The FindXXX.cmake module can also set up the library as an 
> imported target and set the respective properties manually.
> But I'm not aware of any Findxxx.cmake module which does that currently.
> 
> Alex

That's what I've been referring to earlier in this thread... The only catch with IMPORTED targets I can make out is that if the author of the FindXXX.cmake module uses a common name for the target, that it might clash with a target name in the client project. Perhaps the FindXXX.cmake module could do (here the case for zlib)

find_library(ZLIB_LIBRARY z)
# TODO detect whether it is static or shared
add_library(ZLIB_z SHARED IMPORTED)
set_target_properties(ZLIB_z PROPERTIES IMPORTED_LOCATION "${ZLIB_LIBRARY})
# TODO set up IMPORTED_LINK_INTERFACE_LIBRARIES
set(ZLIB_LIBRARIES "ZLIB_z")


What do you think? Also, should there be a way of finding both, static and shared versions?

Michael


More information about the CMake mailing list