Howto fix KDE4 Buildsystem with CMake CVS

Brad King brad.king at kitware.com
Mon Jan 28 14:58:17 CET 2008


Andreas Pakulat wrote:
> CMake CVS changed some behaviour in how it treats
> target_link_directories. Specifically it now doesn't -L switches to the
> linker call unless one explicitly calls link_directories() and sets the
> needed paths.

I'll elaborate on this point.  CMake's link line generation uses a new 
approach to implement proper linking in more cases.  Consider these 
libraries:

   /path/to/libfoo.a
   /path/to/libfoo.so

Previously if someone wrote

   target_link_libraries(myexe /path/to/libfoo.a)

CMake would generate this code to link it:

   ... -L/path/to -Wl,-Bstatic -lfoo -Wl,-Bdynamic ...

This worked most of the time, but some platforms (such as OS X) do not 
support the -Bstatic or equivalent flag.  This made it impossible to 
link to the static version of a library without creating a symlink in 
another directory and using that one instead.

Now CMake will generate this code:

   ... /path/to/libfoo.a ...

This guarantees that the correct library is chosen.

There is a side-effect of this fix.  Projects used to be able to write 
this (wrong) code and it would work by accident:

   add_executable(myexe myexe.c)
   target_link_libraries(myexe /path/to/libA.so -lB)

where "-lB" is meant to link "/path/to/libB.so".  This code is incorrect 
because it asks CMake to link to B but does not provide the proper 
linker search path for it.  It used to work by accident because the 
-L/path/to would get added as part of the implementation of linking to 
A.  The correct code would be

   link_directories(/path/to)
   add_executable(myexe myexe.c)
   target_link_libraries(myexe /path/to/libA.so -lB)

or even better

   add_executable(myexe myexe.c)
   target_link_libraries(myexe /path/to/libA.so /path/to/libB.so)

In order to support projects that have this bug, we've added a 
compatibility feature that adds the "-L/path/to" paths for all libraries 
linked with full paths even though the linker will not need those paths 
to find the main libraries.  The compatibility mode is enabled when a 
link line contains a non-full-path library (like B or -lB) and either 
CMAKE_BACKWARDS_COMPATIBILITY is set to 2.4 or lower or 
CMAKE_LINK_OLD_PATHS is set to true.

> This breaks building any module in KDE4 (except kdelibs) because we get
> some libraries with absolute path in the KDE_XXX_LIBS variables. Easiest
> way to reproduce is building kdelibs + kdepimlibs with cmake cvs. It
> will error out on linking kresources, because it doesn't find -lsolid.
> The linker line doesn't contain any -L switches, but some libraries like
> QtCore, kdecore and other are referenced with absolute paths which
> works.

This is correct.  The -lsolid is an example of the problem I describe above.

> a) introduce KDE_XXX_LIBRARY_DIR (or KDE_LIBRARY_DIR) and add
> link_directories calls for kde libdir and qt libdir in all
> CMakeLists.txt all over trunk/.
> 
> pro: clean solution
> con: takes quite some time and effort

In other projects we've used this approach.

   find_package(XXX REQUIRED)
   include_directories(${XXX_INCLUDE_DIRS})
   link_directories(${XXX_LIBRARY_DIRS})

KDE is already using it for include directories:

   include_directories( ${KDE4_KDEUI_INCLUDES} )

-Brad


More information about the Kde-buildsystem mailing list