[CMake] Fwd: Removing overkill linking

Andreas Pakulat apaku at gmx.de
Sat Oct 2 18:19:09 EDT 2010


On 02.10.10 23:00:57, Paul McEnery wrote:
> On 2 October 2010 21:49, Marcel (ASTRON) <loose at astron.nl> wrote:
> > Op zaterdag 02-10-2010 om 19:11 uur [tijdzone +0100], schreef Paul
> > McEnery:
> >> No sure what happened to this message. I checked the list archive, and
> >> only half of the message appeared....
> >>
> >> http://www.cmake.org/pipermail/cmake/2010-October/039975.html
> >>
> >>
> >> On 1 October 2010 16:40, Marcel Loose <loose at astron.nl> wrote:
> >> > Hi Paul,
> >> >
> >> > Probably one of the packages that you "pull in" -- dbus, dbug-glib,
> >> > libftdi, libglade, gtk+2, hal -- is introducing this dependency. Check
> >> > the different *_LIBRARIES variables and you'll probably find the fly in
> >> > your ointment.
> >> >
> >> > You may definitely want to look into the LINK_INTERFACE_LIBRARIES option
> >> > of target_link_libraries to avoid over-linking.
> >> >
> >>
> >> Thanks Marcel.
> >>
> >> I have managed to solve the issue on the shared library, however, I'm
> >> still having an issue with the executable being excessively linked.
> >> I've tried a number of different ways, but don't think I have the
> >> syntax right for what I'm trying to achieve.
> >>
> >> ====================================
> >> # Dependencies
> >> find_package      (PkgConfig)
> >> pkg_check_modules (DBUS       REQUIRED   dbus-1>=1.2.12)
> >> pkg_check_modules (DBUS-GLIB  REQUIRED   dbus-glib-1>=0.80)
> >> pkg_check_modules (FTDI       REQUIRED   libftdi>=0.13)
> >> pkg_check_modules (GLADE      REQUIRED   libglade-2.0>=2.6.4)
> >> pkg_check_modules (GTK2       REQUIRED   gtk+-2.0>=2.16.1)
> >> pkg_check_modules (HAL        REQUIRED   hal>=0.5.12)
> >>
> >> # Main config
> >> add_definitions(-DGLADEFILE="${CMAKE_INSTALL_PREFIX}/${sharedir}/galinette_gtk.glade")
> >> add_definitions(-DGALINETTE_VERSION="${GALINETTE_VERSION}")
> >>
> >> # Include & build
> >> include_directories   (. ${DBUS_INCLUDE_DIRS}
> >> ${DBUS-GLIB_INCLUDE_DIRS} ${GLADE_INCLUDE_DIRS} ${GTK2_INCLUDE_DIRS}
> >> ${HAL_INCLUDE_DIRS})
> >> add_executable        (galinette callbacks.c callbacks.h
> >> galinette-gtk.c galinette_gtk.glade galinette-gtk.h hal.c hal.h
> >> main.c)
> >> add_dependencies      (galinette libgalinette)
> >> target_link_libraries (galinette libgalinette ${DBUS_LIBRARIES}
> >> ${DBUS-GLIB_LIBRARIES} ${GLADE_LIBRARIES} ${GTK2_LIBRARIES}
> >> ${HAL_LIBRARIES})
> >> target_link_libraries (galinette LINK_INTERFACE_LIBRARIES "")
> >>
> >> # Other resources
> >> add_custom_target (galinette_gtk.glade)
> >>
> >> # Install
> >> install (TARGETS galinette           DESTINATION ${bindir})
> >> install (FILES   galinette_gtk.glade DESTINATION ${sharedir})
> >> ====================================
> >>
> >> From what I can gather from the lists and documentation, executables
> >> are handled slightly differently to libraries. To solve the library
> >> issue, I used the following which worked correctly:
> >>
> >> ====================================
> >> # Dependencies
> >> find_package          (PkgConfig)
> >> pkg_check_modules     (FTDI  REQUIRED  libftdi>=0.13)
> >>
> >> # Include & build
> >> include_directories   (. ${FTDI_INCLUDE_DIRS})
> >> add_library           (libgalinette SHARED device.c error.c firmware.c
> >> flash.c libgalinette.h libgalinette-private.h)
> >> set_target_properties (libgalinette PROPERTIES PREFIX ""
> >> LINK_INTERFACE_LIBRARIES "" SOVERSION 0)
> >> target_link_libraries (libgalinette ${FTDI_LIBRARIES})
> >>
> >> # Install
> >> install (TARGETS libgalinette LIBRARY DESTINATION ${libdir})
> >> ====================================
> >>
> >> set_target_properties doesn't seem to work on executables though.
> >>
> >> Hopefully someone who knows a bit more than I do will be able to spot
> >> what I'm doing wrong...
> >>
> >> Kind regards,
> >> Paul.
> > Hi Paul,
> >
> > How exactly did you check which libraries your executable are linked to.
> > If on Linux, you should use 'readelf -d', not 'ldd'. The latter will
> > also show all transitive dependencies, which is useful, of course, when
> > you want to know which libraries are needed. However, 'ldd' gives you a
> > false impression w.r.t. overlinking.
> >
> 
> Hi Marcel.
> 
> Thanks for the reply. I was relying on dpkg-shlibs which was throwing
> the warnings about unnecessary linking. I've just gone back now and
> checked the binary with readelf -d, and this too is showing the links
> to unneeded libraries.
> 
> I have tried a number of different configurations, but I just cant
> find examples of how to correctly use LINK_INTERFACE_LIBRARIES with an
> executable - rather than a library. Here is my most recent attempt:
> 
> http://pastebin.com/JdVPvYim
> 
> =============================
> [...]
> #
> # Include & build
> #
> include_directories   (. ${DBUS_INCLUDE_DIRS}
> ${DBUS-GLIB_INCLUDE_DIRS} ${GLADE_INCLUDE_DIRS} ${GTK2_INCLUDE_DIRS}
> ${HAL_INCLUDE_DIRS})
> add_executable        (galinette callbacks.c callbacks.h
> galinette-gtk.c galinette_gtk.glade galinette-gtk.h hal.c hal.h
> main.c)
> add_dependencies      (galinette libgalinette)
> target_link_libraries (galinette LINK_INTERFACE_LIBRARIES libgalinette
> ${DBUS_LIBRARIES} ${DBUS-GLIB_LIBRARIES} ${GLADE_LIBRARIES}
> ${GTK2_LIBRARIES} ${HAL_LIBRARIES})
>  [...]
> =============================
> 
> But this just seems to lose all the linking altogether.
> 
> I cant seem to find any projects that use LINK_INTERFACE_LIBRARIES to
> control linking with regard to "executables" rather than libraries.

Thats because a link-interface for an executable doesn't make the
slightest sense. The link-interface in cmake for a library target foo,
defines which libraries should automatically get into the linker-call
when linking some other target against foo. As one doesn't (except in
very very rare cases) link against executable, there's no point in
defining a link-interface.

To reduce excessive linking for libraries, you need to set the
target-property "LINK_INTERFACE_LIBRARIES" to an empty string and
afterwards use target-link-libraries( foo LINK_INTERFACE_LIBRARIES )
with those libs which are present in the public API of foo. Of course
all this only works as long as you're inside a cmake project or if using
imported cmake targets. Otherwise you have to rely on the responsive
FindXYZ.cmake files not adding additional, unnecessary libs to the
linker line (or whatever the find-module uses, like pkg-config files).

Andreas

-- 
You will live to see your grandchildren.


More information about the CMake mailing list