[CMake] Bad documentation of the LINK_INTERFACE_LIBRARIES property and other transitive linking topics

Alan W. Irwin irwin at beluga.phys.uvic.ca
Wed Nov 23 04:25:34 EST 2011


cmake-2.8.6 has the following documentation of the
LINK_INTERFACE_LIBRARIES property for targets:

   LINK_INTERFACE_LIBRARIES
        List public interface libraries for a shared library or executable.

        By default linking to a shared library target transitively links to
        targets with which the library itself was linked.  For an executable
        with exports (see the ENABLE_EXPORTS property) no default transitive
        link dependencies are used.  This property replaces the default
        transitive link dependencies with an explicit list.  When the target
        is linked into another target the libraries listed (and recursively
        their link interface libraries) will be provided to the other target
        also.  If the list is empty then no transitive link dependencies will
        be incorporated when this target is linked into another target even if
        the default set is non-empty.  This property is ignored for STATIC
        libraries.

I believe the reference to executables above is just plain
wrong/misleading.  For example, the FAQ states that
LINK_INTERFACE_LIBRARIES simply lists "the libraries that should be
transitively included in the link by CMake" with the clear implication
(also confirmed by experiment below) that this target property affects
_everything that links to the target whose property is being set_.
But nothing links to an executable so why are executables mentioned at
all?

Here is the background for why I am looking into using this property:

I am told by Orion Poplawski (the guy who packages PLplot for Fedora)
that "rpmlint" warns whenever Linux libraries are overlinked
(presumably because that overlinking brings in unneeded rpm library
dependencies).  I have confirmed for one PLplot library where he gave
the detailed warning messages, that "ldd -u" lists exactly the same
unused direct dependencies as rpmlint. These rpmlint and "ldd -u"
warnings are the direct result of the default transitive linking for
shared libraries used in CMake.

So I have been investigating how to avoid transitive linking for
shared libraries by consulting the CMake FAQ, cmake man page, and
previous threads on this list that have "transitive" in the subject
line. Apparently you are supposed to create an empty
LINK_INTERFACE_LIBRARIES target property.  However, it is not clear
anywhere which target(s) in a chain of direct dependencies should have
an empty LINK_INTERFACE_LIBRARIES property.

Here is a test CMakeList.txt file (adapted from a previous thread on
transitive linking) to investigate this question.

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(TRANSLINK C)

# Test results for main executable
# which directly depends on just libE
# which directly depends just on libD 
# which directly depends just on libC
# which directly depends just on libB
# which directly depends just on libA
# All libraries are shared.

FILE(WRITE ${CMAKE_BINARY_DIR}/a.c "#include <stdio.h>\nvoid a(void){printf(\"hello, world\\n\");}\n")
ADD_LIBRARY(A SHARED a.c)
#TARGET_LINK_LIBRARIES(A LINK_INTERFACE_LIBRARIES)

FILE(WRITE ${CMAKE_BINARY_DIR}/b.c "void b(void){a();}\n")
ADD_LIBRARY(B SHARED b.c)
TARGET_LINK_LIBRARIES(B A)
#TARGET_LINK_LIBRARIES(B LINK_INTERFACE_LIBRARIES)

FILE(WRITE ${CMAKE_BINARY_DIR}/c.c "void c(void){b();}\n")
ADD_LIBRARY(C SHARED c.c)
TARGET_LINK_LIBRARIES(C B)
#TARGET_LINK_LIBRARIES(C LINK_INTERFACE_LIBRARIES)

FILE(WRITE ${CMAKE_BINARY_DIR}/d.c "void d(void){c();}\n")
ADD_LIBRARY(D SHARED d.c)
TARGET_LINK_LIBRARIES(D C)
TARGET_LINK_LIBRARIES(D LINK_INTERFACE_LIBRARIES)

FILE(WRITE ${CMAKE_BINARY_DIR}/e.c "void e(void){d();}\n")
ADD_LIBRARY(E SHARED e.c)
TARGET_LINK_LIBRARIES(E D)
#TARGET_LINK_LIBRARIES(E LINK_INTERFACE_LIBRARIES)

FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(){e();}\n")
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main E)
#TARGET_LINK_LIBRARIES(main LINK_INTERFACE_LIBRARIES)

Note, the LINK_INTERFACE_LIBRARIES target property is emptied for the D
library with the

TARGET_LINK_LIBRARIES(D LINK_INTERFACE_LIBRARIES)

command, but all other such commands are commented out.  The
documentation of TARGET_LINK_LIBRARIES(... LINK_INTERFACE_LIBRARIES)
implies equivalance of the above with

SET_TARGET_PROPERTIES(D PROPERTIES LINK_INTERFACE_LIBRARIES "")

and I have also confirmed that experimentally.

In sum, from this experiment it looks like I will have to set
LINK_INTERFACE_LIBRARIES to empty for all PLplot library targets that
depend on other library targets (e.g., B, C, D, and E, above, but _not_
main or A) created by our build system to comprehensively turn off
transitive linking and avoid overlinking that rpmlint is complaining
about.

However, I am concerned about the safety of doing this.  For example,
a decade or so ago Linux had a buggy run-time loader that would only
work if you used transitive linking so that became the autotools
practice (at least at that time, it may have changed since I quit
using autotools) and I assume that is why transitive linking is the
default with CMake. Are there still enterprise edition Linux distros
out there where turning off transitive linking would cause problems?
Does non-transitive linking cause problems on former or current
Windows or Mac OS X platforms?

Because of these concerns I will probably enable transitive linking by
default but have an option (which defaults to OFF) to disable
transitive linking with an associated docstring that warns that ON is
experimental and may not work on all platforms.

All this to quiet rpmlint warnings....

Alan
__________________________
Alan W. Irwin

Astronomical research affiliation with Department of Physics and Astronomy,
University of Victoria (astrowww.phys.uvic.ca).

Programming affiliations with the FreeEOS equation-of-state
implementation for stellar interiors (freeeos.sf.net); the Time
Ephemerides project (timeephem.sf.net); PLplot scientific plotting
software package (plplot.sf.net); the libLASi project
(unifont.org/lasi); the Loads of Linux Links project (loll.sf.net);
and the Linux Brochure Project (lbproject.sf.net).
__________________________

Linux-powered Science
__________________________


More information about the CMake mailing list