CMake usage requirements in KDE Frameworks

Alexander Neundorf neundorf at kde.org
Mon Mar 18 20:48:03 UTC 2013


On Saturday 16 March 2013, Stephen Kelly wrote:
> Hi there,
> 
> == What happened? ==
> 
> I've pushed a commit which removed much of the CMake code which calls
> include_directories().
> 
>  http://commits.kde.org/kdelibs/56d571a223e00ffed4cb682eb098c5b1e347fa70
> 
> This mail is an explanation of things you might see in the patch or in
> cmake code you read in frameworks.
> 
> == Why? ==
> 
> As of CMake 2.8.11, they are not needed for certain targets, namely Qt and
> in-tree KDE Frameworks targets. Specifying incorrect include dirs and
> incompletely specifying include dirs is a common source of build problems
> in KDE, so this should be more convenient for everyone hacking on the KF5
> frameworks repo.
> 
> This will be expanded later to also cover installed KDE targets, which
> means downstreams such as plasma-frameworks won't need to use
> include_directories(${KF5_INCLUDE_DIRS}) etc anymore.
> 
> == How do we use it? ==
> 
> As of CMake 2.8.11, targets (those created by add_library and
> add_executable) can now define an INTERFACE_INCLUDE_DIRECTORIES property.
> When a downstream links to an upstream which has such a property, it is
> read and the include directories are used. For example:
> 
>  add_library(foo ...)
>  set_property(TARGET foo PROPERTY INTERFACE_INCLUDE_DIRECTORIES
> "/opt/foo/include")
> 
>  add_library(bar ...)
>  # This line not only links bar to foo, but also makes bar compile with -
> I/opt/foo/include, because that is from the interface of foo
>  target_link_libraries(bar foo)
> 
> We can't just remove all include_directories() calls for other packages
> like zlib for example, because some action is required to make the new
> features work, and that action has only been taken for Qt and KDE targets
> so far.
> 
> The target_link_libraries command also now has similar behavior for
> COMPILE_DEFINITIONS, and whether to use POSITION_INDEPENDENT_CODE or not,
> and whether to link to qtmain.lib on Windows.
> 
> If CMake is not already mysterious magic to you, read on to see how it
> works.
> 
> My talk at Qt DevDays last year has all the information too:
> http://www.youtube.com/watch?v=GJ0kMsLbk6Q
> 
> The wiki also has more info:
> 
>  http://community.kde.org/Frameworks/Epics/CMake_target_usage_requirements
> 
> == How does it work? ==
> 
> Of course, in-tree include dirs that should be used are different from
> installed dirs. For example, when karchive is used by a target in the
> frameworks buildsystem, the include dirs used should be
> 
>  -I${CMAKE_CURRENT_SOURCE_DIR}/ -I${CMAKE_CURRENT_BINARY_DIR}/
> 
> but when it is used from its installed location, the include dirs used
> should be:
> 
>  -I${INSTALL_PREFIX}/include
> 
> The new features also support that, and it looks like this:
> 
>  set_property(TARGET foo
>    PROPERTY INTERFACE_INCLUDE_DIRECTORIES
>       "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};
> ${CMAKE_CURRENT_SOURCE_DIR}>"
>       "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>"
>  )
> 
> There is also a convenience built-in to CMake for the BUILD_INTERFACE
> 
>  set(CMAKE_BUILD_INTERFACE_INCLUDES ON)
> 
> which automatically adds
> 
>  "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};
> ${CMAKE_CURRENT_SOURCE_DIR}>"
> 
> to the INTERFACE_INCLUDE_DIRECTORIES of each target. 

Since cmake 2.4.0. the global cmake variable CMAKE_INCLUDE_CURRENT_DIR exists. 
When set to TRUE, cmake automatically adds CMAKE_CURRENT_SOURCE_DIR and 
CMAKE_CURRENT_BINARY_DIR to the include dirs.

I would say the name CMAKE_BUILD_INTERFACE_INCLUDES is too generic, it should 
have a name which is more similar to CMAKE_INCLUDE_CURRENT_DIR, since it does 
something quite similar, maybe CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ?


> In the future there will also be a convenience to add
> 
>  "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>"
> 
> to each target, but we don't have that yet. 

Do you mean a hardcoded "/include" ?
IMO this is too much guessing. Nowhere else (except when searching stuff) 
cmake assumes anything about your install destinations.

> Private include directories are listed in the INCLUDE_DIRECTORIES property.
> Public include directories are listed in the INCLUDE_DIRECTORIES and in the
> INTERFACE_INCLUDE_DIRECTORIES property. If a directory appears in the
> INTERFACE_INCLUDE_DIRECTORIES but not in the INCLUDE_DIRECTORIES property
> of a target, that means that it will not be used to compile the target,
> but will be used by the user of the target.
> 
> A new command is also introduced in CMake 2.8.11 to set this stuff
> conveniently:
> 
>  add_library(foo ...)
> 
>  target_include_directories(foo PRIVATE "/foo/private")
>  target_include_directories(foo PUBLIC "/foo/public")
>  target_include_directories(foo INTERFACE "/foo/interface/only")

Does this actually apply to the BUILD or to the INSTALL include interface ?
 

Thanks for the nice explanation :-)
Alex


More information about the Kde-buildsystem mailing list