[CMake] Again on dependencies tree

Michael Hertling mhertling at online.de
Mon Sep 26 14:00:53 EDT 2011


On 09/22/2011 01:00 PM, Marco Corvo wrote:
> Hi all,
> 
> I thought I came up with a solution for this problem, but looks like I'm 
> still not doing the right thing.
> 
> My project is made of many tens of packages, everyone with its nice 
> CMakeLists.txt. What I'd like to do is to have the freedom to build 
> every single package, or bunches of packages, independently, that is 
> without having to "add_subdirectory" for all packages every time. The 
> point, just to give an idea, is that the developers of the different 
> packages could checkout from the software repo just their own packages, 
> which are then supposed to be built against a software release 
> (libraries) which is centrally installed on a development machine.
> 
> In this framework I would like to let CMake discover the transitive 
> dependencies among libraries.
> 
> To make a practical example I prepared a single package A (the one the 
> developer checks out from our repo) which has an executable EXE 
> depending on library libA.a, which resides in the same package (that is 
> EXE and libA.a are all together in a source directory).
> 
> Yet libA.a depends on a library libB.a which, in this view, is available 
> somewhere in the machine. In CMake syntax I have:
> 
> - package A CMakeLists.txt:
> 
>      add_library(A src/xxx.cc)
>      set(LIB_LINK_LIST B)
>      target_link_libraries(${pkgname} ${LIB_LINK_LIST})
> 
>      add_executable(EXE bins/EXE.cc)
>      set(BIN_LINK_LIST A)
>      target_link_libraries(EXE ${BIN_LINK_LIST})
> 
> - "external" library LibDeps.cmake:
> 
>      add_library(B STATIC IMPORTED)
>      add_dependencies(B C)
> 
> - main CMakeLists.txt
> 
>      include(LibDeps.cmake)
>      add_subdirectory(A)
> 
> In my view what I should obtain is a link command like:
> g++ ...... -o EXE -L/path/to/external/libs -L/path/to/local/libs -L.... 
> -L.... libA.a -lB -lC
> 
> since Exe depends on A, which depends on B via target_link_libraries, 
> which on its side depends on C, via add_dependencies.

B is an imported target, i.e. it is already built - and possibly
installed - by *another* project, so ADD_DEPENDENCIES(B ...) does
not make any sense. Instead, you must provide B's dependencies via
the IMPORTED_LINK_INTERFACE_LIBRARIES[_<CONFIG>] target properties.
Moreover, the IMPORTED_LOCATION[_<CONFIG>] target properties with
B's location must be specified as well. Probably, the same must
be done for C. The LibDeps.cmake should rather look as follows:

# LibDeps.cmake:
ADD_LIBRARY(B STATIC IMPORTED)
ADD_LIBRARY(C ... IMPORTED)
SET_TARGET_PROPERTIES(C PROPERTIES IMPORTED_LOCATION ...)
SET_TARGET_PROPERTIES(B PROPERTIES
    IMPORTED_LOCATION ...
    IMPORTED_LINK_INTERFACE_LIBRARIES C
)

> Instead what I get is:
> g++ ...... -o EXE -L/path/to/external/libs -L/path/to/local/libs -L.... 
> -L.... libA.a B-NOTFOUND
> 
> It's clear that CMake tries to resolve the deps, otherwise what I would 
> get is just "libA.a -lB", but is not able to due to some trick I can't  
> find.

This is because B does not have an IMPORTED_LOCATION property, and
C is missing because B does not specify it as an interface library.

> target_link_library(B C) instead of add_dependencies(B C) doesn't work. 

TARGET_LINK_LIBRARIES() only works for your project's targets to
generate their link command lines, but B is already built/linked/
installed by another project. You can just link *against* B, i.e.:

TARGET_LINK_LIBRARIES(... B ...)

> I know there are ExternalProject_Add, but these are not external 
> projects, just libs residing in some (well known) directories, and 
> find_package, but it would be rather complicated  in case my libA.a 
> depends on N other libraries.
> 
> Am I missing any CMake instructions? Or is it simply the wrong way to 
> proceed?

Try again with the above-noted LibDeps.cmake and report if it works.

> Sorry for the long mail and thanks in advance.
> 
> Cheers,
> 
> Marco

Regards,

Michael


More information about the CMake mailing list