[CMake] Reverse dependencies (Unix Makefiles)
Jesper Eskilson
jesper.eskilson at iar.se
Thu May 27 03:05:47 EDT 2010
On 05/26/2010 05:17 PM, Michael Hertling wrote:
>> Will this still work with an executable E wich depends on B -> C -> B.
>> Won't C pull in A as well?
>
> OK, I suppose, that means you have targets D *and* E in your project, D
> links against A, E against B, A and B both link against C which finally
> needs A *or* B, right? ['fetching a cup of coffee... ;) ]
Correct.
> Now, indeed, you can not associate C with A in this exclusive manner
> anymore, but you can make use of an imported target's decoupling from
> its actual file: Introduce two imported library targets CA and CB, both
> pointing to libC.a on disk, but associated with either A or B. Look here:
>
> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
> PROJECT(ABCDE C)
> # Generate static libraries A,B,C with circular dependencies:
> FILE(WRITE A.c "void fA(void){ fC(); } void ident(void){}")
> FILE(WRITE B.c "void fB(void){ fC(); } void ident(void){}")
> FILE(WRITE C.c "void fC(void){ ident(); }")
> ADD_LIBRARY(A0 STATIC EXCLUDE_FROM_ALL A.c)
> ADD_LIBRARY(B0 STATIC EXCLUDE_FROM_ALL B.c)
> ADD_LIBRARY(C0 STATIC EXCLUDE_FROM_ALL C.c)
> SET_TARGET_PROPERTIES(A0 PROPERTIES ARCHIVE_OUTPUT_NAME A)
> SET_TARGET_PROPERTIES(B0 PROPERTIES ARCHIVE_OUTPUT_NAME B)
> SET_TARGET_PROPERTIES(C0 PROPERTIES ARCHIVE_OUTPUT_NAME C)
> # Incorporate A and B as imported targets:
> ADD_LIBRARY(A STATIC IMPORTED)
> ADD_LIBRARY(B STATIC IMPORTED)
> SET_TARGET_PROPERTIES(A PROPERTIES IMPORTED_LOCATION
> ${CMAKE_CURRENT_BINARY_DIR}/libA.a)
> SET_TARGET_PROPERTIES(B PROPERTIES IMPORTED_LOCATION
> ${CMAKE_CURRENT_BINARY_DIR}/libB.a)
> # Incorporate two imported targets CA and CB for C:
> ADD_LIBRARY(CA STATIC IMPORTED)
> ADD_LIBRARY(CB STATIC IMPORTED)
> SET_TARGET_PROPERTIES(CA PROPERTIES IMPORTED_LOCATION
> ${CMAKE_CURRENT_BINARY_DIR}/libC.a)
> SET_TARGET_PROPERTIES(CB PROPERTIES IMPORTED_LOCATION
> ${CMAKE_CURRENT_BINARY_DIR}/libC.a)
> # Declare circular dependencies:
> SET_TARGET_PROPERTIES(A PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES CA)
> SET_TARGET_PROPERTIES(CA PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES A)
> SET_TARGET_PROPERTIES(B PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES CB)
> SET_TARGET_PROPERTIES(CB PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES B)
> # Generate executable D linking against library A:
> FILE(WRITE D.c "void main(void){ fA(); }")
> ADD_EXECUTABLE(D D.c)
> TARGET_LINK_LIBRARIES(D A)
> # Generate executable E linking against library B:
> FILE(WRITE E.c "void main(void){ fB(); }")
> ADD_EXECUTABLE(E E.c)
> TARGET_LINK_LIBRARIES(E B)
>
> After cmaking, type "make {A,B,C}0" to build lib{A,B,C}.a, and then
> "make VERBOSE=1" for the executables D and E; the link lines are:
>
> gcc CMakeFiles/D.dir/D.c.o -o D -rdynamic libA.a libC.a libA.a libC.a
> gcc CMakeFiles/E.dir/E.c.o -o E -rdynamic libB.a libC.a libB.a libC.a
>
> Thus, the circular dependencies are respected as desired without
> repeating A or B in TARGET_LINK_LIBRARIES() for D and E.
Sounds like a somewhat convoluted solution, but thanks anyway. Now at
least I know that it can be done.
--
/Jesper
More information about the CMake
mailing list