[CMake] Transitive Link Dependencies

Michael Hertling mhertling at online.de
Wed Jul 14 13:59:12 EDT 2010


On 07/14/2010 05:51 PM, Kevin Fitch wrote:
> A.a is not intended to be a path. From my reading of the cmake book adding
> .a is the way you say you specifically want the static library over the
> dynamic library. To me libA.a would be a path.

If "A.a" is not the name of a target it's treated as a file/path name,
and in this case "A.a" makes TARGET_LINK_LIBRARIES() look for a static
library instead of a shared one; look at the following CMakeLists.txt:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(TRANSLINKDEPS C)
FILE(WRITE a.c "void a(void){}\n")
ADD_LIBRARY(A.static STATIC a.c)
ADD_LIBRARY(A.shared SHARED a.c)
SET_TARGET_PROPERTIES(A.static A.shared PROPERTIES OUTPUT_NAME "A")
FILE(WRITE b.c "void b(void){}\n")
ADD_LIBRARY(B SHARED b.c)
TARGET_LINK_LIBRARIES(A.static B)
TARGET_LINK_LIBRARIES(A.shared B)
LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
FILE(WRITE main.c "void main(void){}\n")
ADD_EXECUTABLE(main1 main.c)
TARGET_LINK_LIBRARIES(main1 A)
ADD_EXECUTABLE(main2 main.c)
TARGET_LINK_LIBRARIES(main2 A.a)

The link lines for main1 and main2 are, in short:

gcc .../main.c.o -o main1 ... -L... -lA ...
gcc .../main.c.o -o main2 ... -L... -Wl,-Bstatic -lA -Wl,-Bdynamic ...

So, main1 is linked against libA.so, and main2 is linked against libA.a,
and the "lib" prefix is added by the linker as usual. Nevertheless, "A"
and "A.a" aren't targets, so CMake's tracking of transient dependencies
doesn't apply as it can be seen with "B" not occuring on the link lines
for main{1,2} although the "A" libraries depend on it.

> So, you are saying that there is currently no way in cmake to get transitive
> link dependencies AND specifically call out that you want to specifically
> link against the static (or dynamic) version.

No: The static and the shared version of a library must be associated
each with an individual target, see FAQ 7.1, so you can explicitly
mention the static version's target in TARGET_LINK_LIBRARIES().

Replacing

TARGET_LINK_LIBRARIES(main1 A)
TARGET_LINK_LIBRARIES(main2 A.a)

by

TARGET_LINK_LIBRARIES(main1 A.shared)
TARGET_LINK_LIBRARIES(main2 A.static)

in the example's CMakeLists.txt yields the following link lines:

gcc .../main.c.o -o main1 ... -L... libA.so libB.so ...
gcc .../main.c.o -o main2 ... -L... libA.a libB.so ...

Thus, the linking is done against the shared and the static version of
"A" as desired, and the dependency on "B" is resolved as desired, too.

Regards,

Michael

> On Wed, Jul 14, 2010 at 9:13 AM, Michael Hertling <mhertling at online.de>wrote:
> 
>> On 07/14/2010 02:38 PM, Kevin Fitch wrote:
>>> I have found a situation where transitive link dependencies don't seem to
>>> work the way I would expect. I have a library A that depends on B. e.g.
>>>
>>> target_link_libraries(A B)
>>> # and elsewhere we have ...
>>> target_link_libraries(foo A)
>>> #then B gets linked into foo as expected
>>> #But, if I try to be more explicit in saying I want the static version of
>>> A...
>>> target_link_libraries(bar A.a)
>>> # B does not get linked into bar ... :(
>>>
>>> Is this known/expected behavior, or is it a bug?
>>
>> Known/expected because "A.a" does not denote a target but a path, i.e.
>> CMake links "bar" against the library file "A.a" but can't figure out
>> any dependencies of the latter. With "target_link_libraries(foo A)",
>> you link "foo" against a target "A", so CMake's dependency tracking
>> applies and "B" is pulled in, too.
>>
>> Regards,
>>
>> Michael


More information about the CMake mailing list