[CMake] what is best for library dependencies?

Michael Hertling mhertling at online.de
Tue Oct 4 03:37:15 EDT 2011


On 10/03/2011 11:32 AM, Rolf Eike Beer wrote:
> Am Sonntag, 2. Oktober 2011, 12:21:01 schrieb Cristobal Navarro:
>> hello,
>>
>> as many of us, i am making a library and this is my first time. I have some
>> concept questions.
>>
>> for example, my library depends on "GLEW" library. Therefore applications
>> that use my library must compile with  "-lmylib"  and  "-lGLEW"
> 
> Nope. Your library has to link against those libraries. The applications only 
> have to if they use this interface directly.

This might be insufficient; look at the following counterexample:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(INSUFFICIENT C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(CMAKE_SKIP_BUILD_RPATH TRUE)
FILE(WRITE ${CMAKE_BINARY_DIR}/f.c "void f(void){}\n")
ADD_LIBRARY(f SHARED f.c)
FILE(WRITE ${CMAKE_BINARY_DIR}/g.c "void g(void){f();}\n")
ADD_LIBRARY(g SHARED g.c)
TARGET_LINK_LIBRARIES(g f)
GET_TARGET_PROPERTY(G_LIBRARY g LOCATION)
FILE(WRITE ${CMAKE_BINARY_DIR}/main.c
"int main(void){g(); return 0;}\n")
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main ${G_LIBRARY})

This exemplary project has two shared library targets f and g and an
executable target main; g uses and is linked against f, and main uses
and is linked against g. The latter is done with g's full path so that
TARGET_LINK_LIBRARIES() doesn't track the transient dependencies main-
on-g-on-f. That's the situation you aim at, if I understand correctly.
A "readelf -d libg.so" reveals that libg.so actually has a DT_NEEDED
tag of "libf.so", and main's link command line essentially reads

gcc .../main.c.o -o main ... -L${CMAKE_BINARY_DIR} -lg

i.e. main is about to be linked against libg.so only. Nevertheless, the
linking operation fails since libf.so is not found although it resides
next to libg.so in the build directory. The reason is that ld in fact
uses libg.so's DT_NEEDED tags to learn about the prerequisite libf.so,
but has no hint where to find it; see ld's manpage - particularly the
-rpath-link section with its 8-item list - for more information. The
reason why it usually works even without TARGET_LINK_LIBRARIES()'s
ado is item 6 in connection with CMake's elaborate RPATH handling.
In short: DT_NEEDED tells which library, but not where it is.

Furthermore, it's not necessary that g is linked against f as long as
both are mentioned on the linker command line in the correct order or
recognized by other means. It's also not necessary for executables to
be linked against libraries they're immediately referring to; e.g. if
main calls f() and libg.so has a hint to libf.so, it's sufficient for
main to link against libg.so, provided that libf.so can be found. The
essence is that for an executable's creation, all symbols need to be
resolved, i.e. each necessary library must be found - may it via an
explicit specification on the command line, may it by following DT
_NEEDED via DT_RPATH or whichever methods the linker offers to
locate libraries. However, if "mylib" depends on "GLEW", it's
usually perfect to link the former against the latter.

Regards,

Michael

>> is it possible, to make the "-lGLEW" implicit inside my library?? or making
>> the user put it manually is the way to go?
> 
> You do TARGET_LINK_LIBRARIES(mylib /path/to/glew/libglew.so). That's all. To 
> get the path to GLEW in a system independent way please have a look on 
> FIND_LIBRARY.
> 
> The only exception is if your library is a static one and the target 
> application is not built with CMake. The problem is that you can't put this 
> information in static libraries. Writing a pkgconfig or CMake export file is the 
> way to go then.
> 
> Eike


More information about the CMake mailing list