[CMake] Reverse dependencies (Unix Makefiles)

Michael Hertling mhertling at online.de
Thu May 27 10:13:10 EDT 2010


On 05/27/2010 09:05 AM, Jesper Eskilson wrote:
> 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, [...]

IMO, it is a quite straight solution: One just specifies the immediate
dependencies and has CMake find out the mediate ones - as it should be
- and the speciality of having two different circles in the dependency
graph involving the same node is coped with by the declaration of two
targets for the same library, so the circles become discontiguous.

Regards,

Michael


More information about the CMake mailing list