[cmake-developers] Introducing the ${Foo_TARGETS} variable (IntroduceTARGETSVariable branch)

Vadim Zhukov persgray at gmail.com
Mon Jul 29 05:22:02 EDT 2013


2013/7/27 Alexander Neundorf <neundorf at kde.org>:
> Hi,
>
> I pushed the IntroduceTARGETSVariable branch to stage.
>
> It introduces the new variable Foo_TARGETS to be used in Config files,
> additionally to or maybe better instead of Foo_LIBRARIES and Foo_INCLUDE_DIRS.
>
> This variable shall be used to list the target(s) imported by the package Foo.
>
> So it can be used in tll() calls to link against the library (package).
> What makes it differ from Foo_LIBRARIES, is that CMake checks that each of the
> items listed in this variable
> * is an existing target
> * has the INTERFACE_INCLUDE_DIRS property set.
>
> This should make sure that using this variable in a tll() call should suffice
> to give the target the required include dirs and libraries.
>
> IMO this has multiple advantages:
> * using
>      tll(hello ${Foo_TARGETS} )
>   instead of
>      tll(hello foo )
>   gives the reader a strong hint that ${Foo_TARGETS} comes from a
>   find_package(Foo) call, while in the second case it is not clear at
>   all whether "foo" is an in-project target, an imported target or
>   the basename of a library.
>   This doesn't matter much for the developer who added the dependency
>   to foo himself, since he knows what he's doing at this moment, but it
>   matters a lot for everybody else, who have to find out what's going on, be
>   it a developer new to this code or somebody trying to debug build problems
>   of somebody else's project via a mailing list.
>
> * using
>      tll(hello ${Foo_TARGETS} )
>   instead of
>      tll(hello ${Foo_LIBRARIES} )
>   tells the reader that by using ${Foo_TARGETS} there is need for
>   an additional call to set the include dirs, but that the include dirs are
>   coming attached to the targets listed in ${Foo_TARGETS}.
>   This is actually enforced with this patch.
>   Again, this helps a lot when reading cmake code you didn't write yourself.
>
> * there is a direct mapping from the package name "Foo" used in
>   find_package(Foo) to the variable name "Foo_TARGETS". This is something
>   I heard many people wishing for/complaining about.
>   This cannot be enforced when using target names directly (this would mean
>   that the name of the Config.cmake file must be exactly the name of the
>   target to use, and there is no enforcement of namespaces like "Foo::"
>   possible).
>
>
> * with this variable, for many projects Foo_TARGETS will be the only variable
>   which needs to be set in the Config.cmake file, so they become simpler.
>
>
>
> It has one disadvantage, which is that with this new variable there are now
> two standards: either use ${Foo_LIBRARIES} and ${Foo_INCLUDE_DIRS}, or use
> ${Foo_TARGETS}.

Is there a way for Foo_INCLUDE_DIRS and Foo_LIBRARIES to be
automatically populated by find_package() when Foo_TARGETS is set?
This way migration to Foo_TARGETS could be done smoother.

> Error messages
> --------------
>
> In the case that a target does not exist, the following error message is
> generated:
>
> CMake Warning at /opt/ecm/share/ECM/find-modules/FindKF5.cmake:180
> (find_package):
>   Found package configuration file:
>
>     /opt/kf5/lib/cmake/KCoreAddons/KCoreAddonsConfig.cmake
>
>   but "KCoreAddons" is considered to be NOT FOUND because the variable
>   KCoreAddons_TARGETS set by it lists the following non-existant targets: Foo
> Call Stack (most recent call first):
>   CMakeLists.txt:14 (find_package)
>
>
> In the case that a target is listed. which does not have the include dirs set,
> the following error message is generated:
>
> CMake Warning at /opt/ecm/share/ECM/find-modules/FindKF5.cmake:180
> (find_package):
>   Found package configuration file:
>
>     /opt/kf5/lib/cmake/KCoreAddons/KCoreAddonsConfig.cmake
>
>   but "KCoreAddons" is considered to be NOT FOUND because the variable
>   KCoreAddons_TARGETS set by it lists the following targets which do not have
>   the required INTERFACE_INCLUDE_DIRECTORIES target property set:
>   KF5::KCoreAddons
> Call Stack (most recent call first):
>   CMakeLists.txt:14 (find_package)
>
>
>
> TODO
> ----
>
> * Tests are still missing.
>
> * Should the variable be mentioned in the documentation for find_package() ?
>
> * There is the theoretical risk that there are Config.cmake files out there
> which set a variable with that name already, but without the include dir
> property. Should this be based on a policy, so that the error is only
> generated if cmake 2.8.12 or higher is required ? Or should there be an
> emergency switch -DCMAKE_IGNORE_MISSING_INCLUDE_DIRS_ON_IMPORTED_TARGETS for
> this case ?
>
>
>
> Comments ?
> If possible, I'd like to get that into 2.8.12.

It's a very nice feature because it will also automatically fix many
CMakeLists.txt bugs caused by missing include_directories() calls.
E.g., if libjpeg and libpng both has their INCLUDE_DIRS set to
"/usr/include" in the project developer's OS, then developers usually
miss either ${JPEG_INCLUDE_DIRS} or ${PNG_INCLUDE_DIRS}, and that
breaks build on some other platforms. I can see that minor KDE
releases typically close some such bugs, while every major release
does open new ones. :) So moving to Foo_TARGETS will save time for
packagers of CMake-based projects notably; thank you a lot for this
work!

--
  WBR,
  Vadim Zhukov



More information about the cmake-developers mailing list