[CMake] Problem with LINK_DIRECTORIES

Michael Hertling mhertling at online.de
Tue Nov 15 05:49:52 EST 2011


On 11/14/2011 09:15 PM, Robert Dailey wrote:
> On Mon, Nov 14, 2011 at 1:59 PM, Michael Hertling <mhertling at online.de>wrote:
> 
>> On 11/14/2011 06:17 PM, Robert Dailey wrote:
>>> Well maybe you can tell me I'm doing this wrong then, but based on how I
>> am
>>> currently setting up my third party libraries, it is required.
>>>
>>> So basically all third party libraries we use are not installed
>>> individually, instead we have a server on our intranet that contains
>>> precompiled versions of all libraries in a specific and consistent
>>> hierarchy. For this reason, it doesn't make sense to use find_library(),
>>> which would normally always give you absolute paths to your library files
>>> and thus link_directories() would not be needed.
>>>
>>> Instead I have a script in CMake that iterates each third party library
>> and
>>> adds its lib link directory to a list. When done I take this whole list
>> of
>>> link directories and pass it to link_directories() in my top level
>>> CMakeLists file, this way each and every project will include all of the
>>> third party library lib directories to have access to them.
>>
>> Instead of populating a list with the libraries' directories, you might
>> set up one variable for each library containing the latter's full path,
>> e.g. ZLIB_LIBRARY or BDB47_LIBRARY. Since you do this in the top-level
>> CMakeLists.txt, these variables propagate to subordinate CMakeLists.txt
>> files and, thus, will be known wherever they are needed in your project.
>>
>>> For each target I simply create a list of my libs, like so:
>>>
>>> set( libraries zlib libbdb47 )
>>
>> SET(libraries ${ZLIB_LIBRARY} ${BDB47_LIBRARY})
>>
>>> I pass each one of these to target_link_libraries() and I leave it up to
>>> the compiler to search for where to find the file in the provided link
>>> directories.
>>
>> An unrestricted use of LINK_DIRECTORIES() means asking for trouble;
>> especially with numerous directories, there's a growing probability
>> that the -L option will lure the linker into a wrong directory some
>> day. There're even situations which can't be resolved with -L/-l at
>> all: Suppose you have a directory x with liba.so and libb.so, and a
>> directory y with different versions of lib{a,b}.so. Suppose further
>> you want to link against x/liba.so and y/libb.so. How do you achieve
>> this with LINK_DIRECTORIES() and TARGET_LINK_LIBRARIES()? Reversely,
>> insisting on the use of LINK_DIRECTORIES() limits the possibilities
>> how to organize the libraries on your intranet server. IMO, these
>> are actual drawbacks. OTOH, you must know the libaries' locations
>> to use LINK_DIRECTORIES(), and the libraries must be known anyway,
>> so why not join the locations to the libraries and use full paths?
> 
> 
> Problem is, if I end up using find_library(), I will have to provide hint
> search directories for each and every single library, and there are about
> 20 of them. This to me is the same as just generating a list of directories
> and including those directly, and a lot less trouble.

As David has outlined in the meantime, the advice is not about using
FIND_LIBRARY() - which has not been mentioned a single time - but to
assemble full paths from the libraries' directories and the libraries
themselves, instead of collecting the directories and passing them to
LINK_DIRECTORIES(). I doubt that the latter really means less trouble.

> find_library() is great and I really wanted to use it for this, but to me
> the benefits of using it diminish when we are not using third party
> libraries installed in a non deterministic location. If a user installs the
> third party libraries in different locations on each of their machines, and
> different versions, it makes more sense to use it in that case.

Even if your third-party libraries' organization isn't subject to
change, so you don't need to use FIND_LIBARRY(), you might set up
variables with the libraries' full paths in the cache, i.e. using
SET(... CACHE FILEPATH ...), and preferably initialize them with
a separate file and the -C option. In this way, you do not need
to hard-code any paths in your project, and the user gains the
chance to manipulate each path on the command line or the GUI.

> Why should I let CMake search & find a library when I already know where it
> is? Simply to get absolute paths to those libraries? If I want absolute
> paths I can think of much better ways to do it, preferably through string
> concatenation.

Exactly; do this to get full paths to your libraries, use these paths
in TARGET_LINK_LIBRARIES() and eliminate LINK_DIRECTORIES() from your
project. Besides, "knowing where it is" means an assumption of your
project on your system's administrational/organizational setup, and
relying on such an assumption means that you can't change this setup
without risking your project's breakage. Finally, LINK_DIRECTORIES()
dramatically increases this risk because it makes your project subtly
vunerable to changes in the third-party libraries' directory hierarchy.

> Another issue is that 80% of the libraries we use do not have a
> pre-packaged Find module provided by CMake. This means I'd end up writing
> 80% of the find modules myself. This is a lot of work for no perceived
> benefit.

Find modules are for FIND_PACKAGE(), and no one says that there
must be a find module for each of your third-party libraries.

> With my points made and circumstances explained, can you still give me a
> good reason to use find_library?

FIND_LIBRARY() has the secondary advantage that it automatically
searches for libraries in a platform-dependent manner through a
platform-independent interface, e.g. it can search for .lib files
as well as for .so files without the user's intervention. For this
reason, I often use FIND_LIBRARY() - in conjunction with PATHS and
NO_DEFAULT_PATH - even in configuration files for FIND_PACKAGE(),
which definitely know where the requested library is located.

> I understand and agree with the issues that come with using
> link_directories(), however I haven't run into those issues yet and our
> consistent organization of third party libraries on our intranet server are
> carry over from our legacy build system that I'm replacing.

In this regard, the point is that using LINK_DIRECTORIES() - due to
its inherent booby-traps - restricts the possibilities to change the
third-party libraries' organization on your intranet server. If you
are willing to accept such a restriction, it's okay, of course. IMO,
it's completely unnecessary because the use of full paths in cached
variables - regardless if set up by FIND_LIBRARY() or initialized
via -C - makes your project by far more robust w.r.t. the external
libraries and provides additional means for the user to intervene.

Regards,

Michael


More information about the CMake mailing list