[CMake] problem with export(TARGETS ...)

Brad King brad.king at kitware.com
Thu Jan 27 17:23:44 EST 2011


On 01/27/2011 03:08 PM, Clinton Stimpson wrote:
> add_library(A SHARED a.cpp)
> add_library(B SHARED b.cpp)
> target_link_libraries(B A)
> set_target_properties(B PROPERTIES LINK_INTERFACE_LIBRARIES "")
> export(TARGETS B FILE B-exports.cmake)
> 
> that gives me an error 
> "export called with target "B" which requires target "A" that is not in the
>   export list."

Although A is not in B's link interface it is in its link implementation.
When an application links to shared library B the linker wants to find
B's runtime dependencies.  See "man ld" for the "-rpath-link" option.
CMake needs to export enough information so that when the application
imports target B and does

  target_link_libraries(myexe B)

then it can provide enough information to the linker to find library A.
This is conservative to ensure things work whether or not B's RPATH
is set (and therefore independent of RPATH settings).

Temporarily change the above example export() call to

  export(TARGETS B A FILE B-exports.cmake)

Then inspect the generated B-exports.cmake.  It will have:

  SET_TARGET_PROPERTIES(B PROPERTIES
    IMPORTED_LINK_DEPENDENT_LIBRARIES_NOCONFIG "A"
    ...
    )

to tell the importing CMake that it needs to ensure the linker can
find A when the application links to B even though A will not appear
on the link line.

> If I change A to be a static library, the error goes away.

This is because A will be linked into B so when linking to B there is
no need for the linker to look for A.

> If I change A to be a static library, and don't set the 
> LINK_INTERFACE_LIBRARIES property on B, I get the error.

This is because A remains in B's link interface and thus when an
application links to B CMake passes A on the link line too.

> I don't want to export private shared libraries.  Is there some
> other property like LINK_INTERFACE_LIBRARIES that I need to set?

Currently there is no way to do this due to the above requirements.
If A is not used by other shared libraries then you can make it
static and compile with -fPIC.  Otherwise you'll just have to
document that it is not part of your interface.

Moving forward, we could consider adding a new property for IMPORTED
targets to mark them as "private".  This would tell CMake that it
is imported only for purposes like the above and should not be
referenced directly by the importing project.

-Brad


More information about the CMake mailing list