[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