[CMake] link_libraries vs target_link_libraries
Fernando Cacciola
fernando.cacciola at gmail.com
Tue Nov 11 13:13:43 EST 2008
Hi Andreas,
> On 11.11.08 14:12:39, Fernando Cacciola wrote:
>> Hi Andreas,
>>
>>> On 10.11.08 12:01:13, Fernando Cacciola wrote:
>>>> The CGAL library (www.cgal.org) uses cmake as build system. Thus, our
>>>> users do:
>>>>
>>>> find_package(CGAL REQUIRED)
>>>> include( ${CGAL_USE_FILE} )
>>>> ...
>>>>
>>>>
>>>> UseCGAL.cmake, as all such files, call include_directories,
>>>> add_definitions and overrides (under certain circumstances) the
>>>> compiler/linker flags that were used to build the CGAL library.
>>>>
>>>> These are all settings that affect any target added after the
>>>> inclusion of UseCGAL.cmake.
>>>>
>>>> However, following the recommended practice (according to the
>>>> documentation of the deprecated link_libraries command), UseCGAL DOES
>>>> NOT call link_libraries. Instead, it realies on the user calling
>>>> target_link_libraries himself.
>>>>
>>>> Well, I'm questioning this recommended practice because it's half
>>>> baked: It makes sense to allow users to control which targets are
>>>> linked against CGAL, but NOT if OTOH they cannot control which
>>>> targets are given the CGAL include directories, definitions and
>>>> flags.
>>>>
>>>> That is, IMO, target_link_libraries makes little sense in the absence
>>>> of target_include_directories, target_add_definitions and
>>>> target_*_FLAGS.
>>>>
>>>> What it's so special about linking that only that command can be made
>>>> target specific???
>>>>
>>>> Or am I missing something?
>>> There are projects that have headers that are usable without linking
>>> against any library. There are also projects installing their headers into
>>> a common place, that have multiple libraries. In that latter case you'd
>>> have include_directories() point to the common place for the headers, but
>>> obviously you can't know which of the libraries needs to be linked in.
>>>
>> Who is you in your sentence?
>>
>> The UseXYZ modules which depends on the parameters to find_package(XYZ)
>> certainly knows it.
>
> No it doesn't. UseXXX is a "global" thing, so it can't know which of the
> targets in a project need which files.
>
Right, but the again a typical UseXYZ would do:
include_directories( ${XYZ_INCLUDE_DIR} )
add_definitions( ${XYZ_DEFINITIOS} )
set( CMAKE_CXX_FLAGS "$XYZ_CXX_FLAGS") )
So it doesn't know which of your targets need the include dirs, the
definitions and the flags.. and it doesn't care.
>>> Boost is a good example (albeit it doesn't use cmake to build itself).
>>> There are various libraries shipped with it, they all install their headers
>>> into <includedir>/boost/<libraryname>/ and the libs are of course directly
>>> in <libdir>. And its common practice to have only <includedir>/boost in the
>>> include-directories.
>>>
>> And BOOST_LIBRARIES is defined as a list of all libraries indicated by
>> the user as boost components.
>
> Right, but those are all I'm going to use in my project, which might or
> might not be different from those that I want on target A and B.
>
Right.
>> So, if there where a UseBoost.cmake file
>> which would do
>>
>> include_directories( ${BOOST_INCLUDE_DIR} )
>> add_definitions( ${BOOST_DEFINITIONS} )
>>
>> then wouldn't it make sense for it to do
>>
>> link_libraries( ${BOOST_LIBRARIES} )
>>
>> as well?
>
> That would mean _all_ my targets link against those libraries, which is
> completely wrong.
Right.
> In fact I don't understand why include_directories and
> add_definitions are not deprecated as well
Which is precisely my point!! :)
target_link_libraries, which is GREAT, is actually pretty useless
without target_include_directories, target_add_definitions and
<TARGET>_CMAKE_CXX_FLAGS.
Yet OTOH given that those do not exists, it is just plain silly to
recommend not using link_libraries, because it gets less than half the
story right.
And IMO is equally silly to follow the recomendation and end up doing
what most Use files typically do: to set so much that affects all
subsequent targets, even compiler and linker flags, BUT simply define a
variable XYZ_LIBRARY so a user can decide which target to link againt
XYZ_LIBRARY.
I mean, being able to control this is cool, sure, but why can I only
control that and not the other equally critical settings???
IMO, if a user won't have real control over which targets actually use
XYZ (in all the extent to which using XYZ, as defined by
find_package(XYZ), means) then I rather don't bother them requiring
users to call target_link_libraries by hand (while everything else is
setup by the Use file itself). It's just silly.
So to restat my point, if a UseFile does this:
include_directories( ${XYZ_INCLUDE_DIR} )
add_definitions( ${XYZ_DEFINITIOS} )
set( CMAKE_CXX_FLAGS "$XYZ_CXX_FLAGS") )
which shouldn't under the argument of "what if I don't want that for all
my targets", then it should do this as well:
link_libraries( ${XYZ_LIBRARIES} )
Best
Fernando
More information about the CMake
mailing list