Jump to content

Frameworks/Epics/CMake target usage requirements: Difference between revisions

From KDE Community Wiki
Steveire (talk | contribs)
Steveire (talk | contribs)
No edit summary
 
(42 intermediate revisions by the same user not shown)
Line 1: Line 1:
This page collects ideas and requirements for a CMake which is fully target orientated, rather than directory orientated and propagates usage requirements, towards convention driven usage of propagated properties.
This page collects ideas and requirements for a CMake which is fully target orientated, rather than directory orientated. Additionally the targets propagate usage requirements to simplify the use of well-defined targets.
 
By 'fully target orientated', the intention is to be able to connect targets in a build system to other targets in that same build system and to imported targets.


Several feature requests related to this also mention the requirement to set these properties on a per-source-file basis. This wiki page ignores the source-file level requirement and defers it to future work.
Several feature requests related to this also mention the requirement to set these properties on a per-source-file basis. This wiki page ignores the source-file level requirement and defers it to future work.
Line 9: Line 11:
* Transitive behaviour - dependants should be easily informed of what properties they should use.
* Transitive behaviour - dependants should be easily informed of what properties they should use.
* CMake needs to be able to set properties differently based on whether downstreams should use its contents or not (public versus private).
* CMake needs to be able to set properties differently based on whether downstreams should use its contents or not (public versus private).
* Possibly different values based on whether linking statically or dynamically (?)
* Different values based on whether linking statically or dynamically
* Possibly different values based on the language being used.
* Possibly different values based on the language being used.
* Different values based on whether it is used from its build location or installed location (eg the include directories of a library)
* Different values based on whether it is used from its build location (ie, targets created in the same buildsystem) or installed location (eg the include directories of a library). This will be possible with generator expressions. Eg:
 
      set_property(TARGET foo PROPERTY
        INTERFACE_INCLUDE_DIRECTORIES
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>"
        "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>"
      )
 
* The public/installed include directories must be relocatable. For dependencies, this will be possible with generator expressions which assume the dependency has already been found: $<TARGET_PROPERTY:depend:INTERFACE_INCLUDE_DIRECTORIES>
* CMake may need update some properties based on the value of some other properties. For example, if the WIN32_EXECUTABLE property is true, we may need to link in a static library, as we do on windows with qtmain. https://codereview.qt-project.org/#change,26577
 
There is also a possibility that the host and target platforms (when cross compiling) should be dimensions of this feature (or possibly the generator being used). It's not clear how that could work however without turning the possibilities for Generator-expressions entirely unmaintainable. For more see http://thread.gmane.org/gmane.comp.programming.tools.cmake.user/42060/focus=42095. For now, that's not a topic for this page.


The properties that should be covered by this mechanism are:
The properties that should be covered by this mechanism are:
Line 17: Line 30:
* Link libraries
* Link libraries
* Include directories
* Include directories
* Link directories
* Preprocessor definitions
* Preprocessor definitions
* Compiler flags
* Compiler flags (eg, if -msoft-float is used by a dependency then it should be used by dependents, or -std=C++11?) Note that the raw flags should not be stored as a target property as they vary among compilers. Instead abstracted properties on the target should be made available, such as POSITION_INDEPENDENT_CODE or STD_CXX11.
* Linker flags
* Linker flags


Line 27: Line 39:
* The publisher - Imported targets need to be able to define their usage requirements . Exported target generator needs to be able to generate them.
* The publisher - Imported targets need to be able to define their usage requirements . Exported target generator needs to be able to generate them.
* The consumer - Developer needs to be able to easily read and act upon the usage requirements of dependencies.
* The consumer - Developer needs to be able to easily read and act upon the usage requirements of dependencies.
In the case of using targets from the same buildsystem, the publisher phase is not executed, and the consumer phase simply uses the same properties set in the implementation phase.


== The consuming phase ==
== The consuming phase ==


The target 'porcelain' API for the consumer is a new cmake command like:
The target API for the consumer is a new cmake command like:


  target_use_package(Foo Bar)
  target_link_libraries(Foo Bar Qt5::Widgets boost::program_options boost::mpl)


where Foo is a target created in the local CMakeLists file, and Bar is one of:
where Foo is a target created in the local CMakeLists file, and the other targets are one of:


* A package containing imported targets and variables with the appropriate naming conventions for variables for use with each property (eg for linking, include directories, flags etc).
* A target created in this buildsystem, or
* An imported target
* An imported target
* A prefix for variables with the appropriate naming conventions for variables for use with each property (eg for linking, include directories, flags etc).


The 'plumbing' API would be the populated variables themselves, for example, the Bar_LIBRARIES Bar_INCLUDE_DIRECTORIES variables and others. Consumers could choose to forego the porcelain API where needed and use the plumbing API instead.
== The publishing phase ==


The implementation of the target_use_package command would take the following steps:
All required information would need to be encoded in properties on the targets, probably in generator expressions (eg, The INTERFACE_INCLUDE_DIRECTORIES of the Bar target might contain several entries of the form $<$<CONFIG:Debug>:/foo/bar>).


* find the Bar package if not already found this allows consumers to find the package with their own arguments to find_package and then call target_use_package)
For creators of Find modules, the responsibility would be on the Find module author to ensure correctly creating imported targets and populating the correct properties on them.


Notes:
For Config files, exported targets should be used, which will generate properties on the imported targets based on the values of properties set during the implementation phase.
 
In the case where Bar is a package which has no components, or in which we do not specify components, there is no need to use find_package.
 
target_use_package(Foo Bar)
 
If Bar is not defined, it is assumed to be a package, and is searched for. After that, if Bar_LIBRARIES contains imported targets, they and their appropriate properties are used when building Foo. Otherwise, the variables with the appropriate naming conventions (eg Bar_LIBRARIES Bar_INCLUDE_DIRS) are used.
 
In the case where we want to customize how we find the package:
 
find_package(Bar PATHS ...)
target_use_package(Foo Bar) # Checks Bar_FOUND and does not attempt to  find it again.
 
In the case of using a package with components, it would work like this:
 
find_package(Bar REQUIRED Bat)
target_use_package(Foo ${Bar_Bat_LIBRARIES})
 
If Bar_Bat_LIBRARIES is an imported target, the appropriate properties from it are used when building Foo.
Otherwise, the variables with the appropriate naming conventions (eg Bar_Bat_LIBRARIES Bar_Bat_INCLUDE_DIRS) are used.
 
 
== The publishing phase ==
 
Inside of Find modules or Config modules, the variables would be set and populated. The variables would all contain an ExactCase prefix, and whatever other information is appropriate. That is, some information would be encoded in the name of variables (eg, there might be Bar_INCLUDE_DIRS_<CONFIG> defined here), and some information would be encoded in generator expressions (eg, Bar_INCLUDE_DIRS might contain several entries of the form $<CONFIG?Debug:/foo/bar>). The generator expressions form would be most convenient for consumers and should be preferred, but the decision may also be influenced by existing convention (eg in the case of CMAKE_CXX_FLAGS_DEBUG).
 
For creators of Find modules, the responsibility would be on the Find module author to ensure adherence to the correct naming conventions, as appropriate. For Config files, exported targets should be used, which will generate properties on the imported targets based on the values of properties set during the implementation phase.


== The implementation phase ==
== The implementation phase ==
Line 80: Line 67:
Plumbing API:
Plumbing API:


The plumbing API and implementation detail for this will be based on target properties, not directory level properties. The properties will have well-defined names, preferably without containing any of the dimensions in their name (eg, language, config, shared/ststic etc), though it will likely be necessary to include in the name whether it is a internal requirement or a usage requirement (eg public versus private) and make use of generator expressions to deal with those dimensions. The implementor will be able to for example:
The plumbing API and implementation detail for this will be based on target properties, not directory level properties.  
 
The properties will have well-defined names, preferably without containing any of the dimensions in their name (eg, language, config, shared/ststic etc) but the value will make use of generator expressions to deal with those dimensions. The implementor will be able to for example:


  set_property(TARGET Foo
  set_property(TARGET Foo
   APPEND PROPERTY INCLUDE_DIRECTORIES
   APPEND PROPERTY INCLUDE_DIRECTORIES
   "/internal/dependency"
   "/internal/dependency"
   "$<CONFIG?Debug:/internal/foo/debugstuff>"
   "$<$<CONFIG:Debug>:/internal/foo/debugstuff>"
  )
  )


  set_property(TARGET Foo
  set_property(TARGET Foo
   APPEND PROPERTY INCLUDE_DIRECTORIES_PUBLIC
   APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
   "/includes/you/need/to/use/foo"
   "/includes/you/need/to/use/foo"
   "$<CONFIG?Debug:/foo/debugstuff>"
   "$<$<CONFIG:Debug>:/foo/debugstuff>"
   "$<CONFIG?Release:/foo/releasestuff>"
   "$<$<CONFIG:Release>:/foo/releasestuff>"
  )
  )


There will likely be a need for a porcelain API for these properties too, such as
A more complete syntax for the generator expressions is described [http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/3615/focus=3900 here].
 
target_include_directories(Foo
  "/internal/dependency"
CONFIGURATION Debug
  "/internal/dependency"
PUBLIC
  "/includes/you/need/to/use/foo"
CONFIGURATION Debug
  "/foo/debugstuff"
CONFIGURATION Release
  "/foo/releasestuff"
)


=== Current state ===
=== Current state ===
Line 126: Line 103:
|-  
|-  
| Compile options || set(CMAKE_CXX_FLAGS) string with language and configuration specified || set COMPILE_FLAGS target property with no language or configuration specified || No way of specifying language (needed?). Needs to get support for generator expressions for configuration, and needs a way to differentiate public/private. Rebase the COMPILE_OPTIONS branch to master and finish it so that we can deal with ';' separated lists instead of spaces.
| Compile options || set(CMAKE_CXX_FLAGS) string with language and configuration specified || set COMPILE_FLAGS target property with no language or configuration specified || No way of specifying language (needed?). Needs to get support for generator expressions for configuration, and needs a way to differentiate public/private. Rebase the COMPILE_OPTIONS branch to master and finish it so that we can deal with ';' separated lists instead of spaces.
|}
== TODO ==
{| class="sortable" border="1" cellpadding="5" cellspacing="0" style="border: gray solid 1px; border-collapse: collapse; text-align: left; width:100%;"
|- style="background: #ececec; white-space:nowrap;"
! Status
! Description
!  width=120 | Notes
|-
{{FeatureDone|Agree on and implement generator expression language|Steve/Brad}}
|-
{{FeatureDone|Extend built-in generator expression API as required|Steve}}
|-
{{FeatureDone|At the start of generate-time, create a const cmGeneratorTarget for each cmTarget* (target-prime-time). From this point on, no generator should need to use a cmTarget*.|CMake 2.8.9 or earlier}}
|-
{{FeatureDone|Implement evaluation of results of generator expressions while evaluating the parent. For example if A depends on B, and C depends on B, C should get the requested content from A when evaluating its expression that uses B. Together with this feature, implement code to ensure that the dependencies form a DAG, and error out if not.|CMake 2.8.10}}
|-
{{FeatureDone|Implement support for generator expressions in the COMPILE_DEFINITIONS target property (likely the easiest one to start with). Consider creating and storing cmGeneratorExpression objects early (at target-prime-time) and evaluating them later. Similar for all following target properties. The add_definitions() presents issues due to the -D requirement there, and it is likely not needed anyway, so don't support generator expressions with that command. Consider adding a compile_defintions() command if such a thing is wanted at 'directory scope' (unlikely).|CMake 2.8.10}}
|-
{{FeatureDone|Implement support for generator expressions in the INCLUDE_DIRECTORIES target property.|CMake 2.8.10}}
|-
{{FeatureDone|Implement support for INTERFACE_COMPILE_DEFINITIONS target property.|CMake 2.8.11}}
|-
{{FeatureDone|Implement support for INTERFACE_INCLUDE_DIRECTORIES target property. This will require the creation of a new generator expressions $<BUILD_INTERFACE> which is "1" if the target is part of the same build-system, or a build-imported target created by export(), and $<INSTALL_INTERFACE> which is "0" if the target is an install(EXPORT)ed target. This is needed because directories which should be used at build-time are not the same as those to use with installed targets. $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> should work as expected for both build targets/build-imported targets and installed imported targets. In fact is it likely the only option for installed imported targets because the imported target generator does not know the correct paths. As config files [http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/2574 need to find their own dependencies anyway], they can ensure that they get imported targets for those dependencies in the Find modules. |CMake 2.8.11}}
|-
{{FeatureDone|Implement support for generator targets in target_link_libraries, LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES target properties, using knowledge and refactorings already gained.|CMake 2.8.11}}
|-
{{FeatureDone|Implement imported usage requirements in boost, at least as proof of concept https://github.com/ryppl/ryppl/commit/8b7bda65393030f668cf2fcbc0c2378335c1027c.|Steve}}
|-
{{FeatureDone|Implement compile features in interfaces such as INTERFACE_POSITION_INDEPENDENT_CODE.|CMake 2.8.11}}
|-
{{FeatureDone|Implement imported usage requirements in FindQt4.cmake.|CMake 2.8.11}}
|-
{{FeatureDone|Investigate whether targets-as-interfaces can benefit the try_compile API. We currently have issues with it in KDE due to the need for CMAKE_POSITION_INDEPENDENT_CODE to be set globally.|CMake 2.8.11}}
|-
{{FeatureDone|Implement imported usage requirements in Qt 5 Config files.|Qt 5.1.0}}
|-
{{FeatureDone|Implement INTERFACE_COMPILE_OPTIONS target property. This is similar to the features stuff, but with the difference that it is compiler specific and a workaround for lack of a similar feature in CMake so far. Add a way for users to use $<$<MATCHES: $<CXX_COMPILER_ID>,GCC>:-fPIC>  (similar for compiler versions). This can be used for soft/hard float, c++11 etc until CMake has built-in support for those.|CMake 2.8.12}}
|-
{{FeatureDone|Implement target usage in some macros/functions. For example, qt5_generate_moc currently reads the directory property INCLUDE_DIRECTORIES, but not the target property (as it does not include yet). At this point, we can do things like this: qt5_generate_moc(infile.h moc_outfile.cpp TARGET foo); add_library(foo ${srcs}). TARGET foo is specified before the foo target exists, but it is used as part of a generator expression like add_custom_command(COMMAND ${Qt5Core_MOC_EXECUTABLE} ARGS "$<JOIN: -I,$<TARGET_PROPERTY:${theTARGET},INTERFACE_INCLUDE_DIRECTORIES>>"), where the $<JOIN> generator expression takes a separator and a list to join with it. |CMake 2.8.12}}
|-
{{FeatureDone|Implement support for libraries of type INTERFACE_LIBRARY which only contain interface properties.|CMake 3.0.0}}
|-
{{FeatureDone|Implement compile feature for [http://www.cmake.org/cmake/help/v3.1/manual/cmake-compile-features.7.html language dialects].|CMake 3.1.0}}
|}
|}


Line 149: Line 171:


http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/3119/focus=3315
http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/3119/focus=3315
http://thread.gmane.org/gmane.comp.programming.tools.cmake.user/37340

Latest revision as of 09:36, 21 February 2015

This page collects ideas and requirements for a CMake which is fully target orientated, rather than directory orientated. Additionally the targets propagate usage requirements to simplify the use of well-defined targets.

By 'fully target orientated', the intention is to be able to connect targets in a build system to other targets in that same build system and to imported targets.

Several feature requests related to this also mention the requirement to set these properties on a per-source-file basis. This wiki page ignores the source-file level requirement and defers it to future work.

There are several dimensions to this:

  • CMake needs to be able to set all necessary properties to configure the build.
  • CMake needs to be able to set properties differently based on debug and release configurations
  • Transitive behaviour - dependants should be easily informed of what properties they should use.
  • CMake needs to be able to set properties differently based on whether downstreams should use its contents or not (public versus private).
  • Different values based on whether linking statically or dynamically
  • Possibly different values based on the language being used.
  • Different values based on whether it is used from its build location (ie, targets created in the same buildsystem) or installed location (eg the include directories of a library). This will be possible with generator expressions. Eg:
     set_property(TARGET foo PROPERTY
       INTERFACE_INCLUDE_DIRECTORIES
       "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>"
       "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>"
     )
  • The public/installed include directories must be relocatable. For dependencies, this will be possible with generator expressions which assume the dependency has already been found: $<TARGET_PROPERTY:depend:INTERFACE_INCLUDE_DIRECTORIES>
  • CMake may need update some properties based on the value of some other properties. For example, if the WIN32_EXECUTABLE property is true, we may need to link in a static library, as we do on windows with qtmain. https://codereview.qt-project.org/#change,26577

There is also a possibility that the host and target platforms (when cross compiling) should be dimensions of this feature (or possibly the generator being used). It's not clear how that could work however without turning the possibilities for Generator-expressions entirely unmaintainable. For more see http://thread.gmane.org/gmane.comp.programming.tools.cmake.user/42060/focus=42095. For now, that's not a topic for this page.

The properties that should be covered by this mechanism are:

  • Link libraries
  • Include directories
  • Preprocessor definitions
  • Compiler flags (eg, if -msoft-float is used by a dependency then it should be used by dependents, or -std=C++11?) Note that the raw flags should not be stored as a target property as they vary among compilers. Instead abstracted properties on the target should be made available, such as POSITION_INDEPENDENT_CODE or STD_CXX11.
  • Linker flags

There are several aspects to this

  • The implementation - the upstream developer needs to be able to mark properties for the values in each required dimension (The usage requirements).
  • The publisher - Imported targets need to be able to define their usage requirements . Exported target generator needs to be able to generate them.
  • The consumer - Developer needs to be able to easily read and act upon the usage requirements of dependencies.

In the case of using targets from the same buildsystem, the publisher phase is not executed, and the consumer phase simply uses the same properties set in the implementation phase.

The consuming phase

The target API for the consumer is a new cmake command like:

target_link_libraries(Foo Bar Qt5::Widgets boost::program_options boost::mpl)

where Foo is a target created in the local CMakeLists file, and the other targets are one of:

  • A target created in this buildsystem, or
  • An imported target

The publishing phase

All required information would need to be encoded in properties on the targets, probably in generator expressions (eg, The INTERFACE_INCLUDE_DIRECTORIES of the Bar target might contain several entries of the form $<$<CONFIG:Debug>:/foo/bar>).

For creators of Find modules, the responsibility would be on the Find module author to ensure correctly creating imported targets and populating the correct properties on them.

For Config files, exported targets should be used, which will generate properties on the imported targets based on the values of properties set during the implementation phase.

The implementation phase

For authors of libraries which create CMake Config files, there needs to be API to populate each property on particular targets. The properties are then used when targets are exported with the install(... EXPORT ...) signature.

Plumbing API:

The plumbing API and implementation detail for this will be based on target properties, not directory level properties.

The properties will have well-defined names, preferably without containing any of the dimensions in their name (eg, language, config, shared/ststic etc) but the value will make use of generator expressions to deal with those dimensions. The implementor will be able to for example:

set_property(TARGET Foo
  APPEND PROPERTY INCLUDE_DIRECTORIES
  "/internal/dependency"
  "$<$<CONFIG:Debug>:/internal/foo/debugstuff>"
)
set_property(TARGET Foo
  APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
  "/includes/you/need/to/use/foo"
  "$<$<CONFIG:Debug>:/foo/debugstuff>"
  "$<$<CONFIG:Release>:/foo/releasestuff>"
)

A more complete syntax for the generator expressions is described here.

Current state

Property Directory-level API Target-level API Notes
Link Libraries link_libraries command target_link_libraries command Already possible to differentiate between public and private linking, and debug/optimized. However, it might be worth porting this to generator expressions too for consistency and to allow differentiation based on other configurations.
Include directories include_directories set target property INCLUDE_DIRECTORIES

Needs to get support for generator expressions, and possibly needs a way to differentiate public/private

Preprocessor defintions add_defnitions command set target property COMPILE_DEFINITIONS and COMPILE_DEFINITIONS_<CONFIG> No way of specifying language (needed?). May need to get support for generator expressions, and needs a way to differentiate public/private
Compile options set(CMAKE_CXX_FLAGS) string with language and configuration specified set COMPILE_FLAGS target property with no language or configuration specified No way of specifying language (needed?). Needs to get support for generator expressions for configuration, and needs a way to differentiate public/private. Rebase the COMPILE_OPTIONS branch to master and finish it so that we can deal with ';' separated lists instead of spaces.

TODO

Status Description Notes
DONE Agree on and implement generator expression language Steve/Brad
DONE Extend built-in generator expression API as required Steve
DONE At the start of generate-time, create a const cmGeneratorTarget for each cmTarget* (target-prime-time). From this point on, no generator should need to use a cmTarget*. CMake 2.8.9 or earlier
DONE Implement evaluation of results of generator expressions while evaluating the parent. For example if A depends on B, and C depends on B, C should get the requested content from A when evaluating its expression that uses B. Together with this feature, implement code to ensure that the dependencies form a DAG, and error out if not. CMake 2.8.10
DONE Implement support for generator expressions in the COMPILE_DEFINITIONS target property (likely the easiest one to start with). Consider creating and storing cmGeneratorExpression objects early (at target-prime-time) and evaluating them later. Similar for all following target properties. The add_definitions() presents issues due to the -D requirement there, and it is likely not needed anyway, so don't support generator expressions with that command. Consider adding a compile_defintions() command if such a thing is wanted at 'directory scope' (unlikely). CMake 2.8.10
DONE Implement support for generator expressions in the INCLUDE_DIRECTORIES target property. CMake 2.8.10
DONE Implement support for INTERFACE_COMPILE_DEFINITIONS target property. CMake 2.8.11
DONE Implement support for INTERFACE_INCLUDE_DIRECTORIES target property. This will require the creation of a new generator expressions $<BUILD_INTERFACE> which is "1" if the target is part of the same build-system, or a build-imported target created by export(), and $<INSTALL_INTERFACE> which is "0" if the target is an install(EXPORT)ed target. This is needed because directories which should be used at build-time are not the same as those to use with installed targets. $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> should work as expected for both build targets/build-imported targets and installed imported targets. In fact is it likely the only option for installed imported targets because the imported target generator does not know the correct paths. As config files need to find their own dependencies anyway, they can ensure that they get imported targets for those dependencies in the Find modules. CMake 2.8.11
DONE Implement support for generator targets in target_link_libraries, LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES target properties, using knowledge and refactorings already gained. CMake 2.8.11
DONE Implement imported usage requirements in boost, at least as proof of concept https://github.com/ryppl/ryppl/commit/8b7bda65393030f668cf2fcbc0c2378335c1027c. Steve
DONE Implement compile features in interfaces such as INTERFACE_POSITION_INDEPENDENT_CODE. CMake 2.8.11
DONE Implement imported usage requirements in FindQt4.cmake. CMake 2.8.11
DONE Investigate whether targets-as-interfaces can benefit the try_compile API. We currently have issues with it in KDE due to the need for CMAKE_POSITION_INDEPENDENT_CODE to be set globally. CMake 2.8.11
DONE Implement imported usage requirements in Qt 5 Config files. Qt 5.1.0
DONE Implement INTERFACE_COMPILE_OPTIONS target property. This is similar to the features stuff, but with the difference that it is compiler specific and a workaround for lack of a similar feature in CMake so far. Add a way for users to use $<$<MATCHES: $<CXX_COMPILER_ID>,GCC>:-fPIC> (similar for compiler versions). This can be used for soft/hard float, c++11 etc until CMake has built-in support for those. CMake 2.8.12
DONE Implement target usage in some macros/functions. For example, qt5_generate_moc currently reads the directory property INCLUDE_DIRECTORIES, but not the target property (as it does not include yet). At this point, we can do things like this: qt5_generate_moc(infile.h moc_outfile.cpp TARGET foo); add_library(foo ${srcs}). TARGET foo is specified before the foo target exists, but it is used as part of a generator expression like add_custom_command(COMMAND ${Qt5Core_MOC_EXECUTABLE} ARGS "$<JOIN: -I,$<TARGET_PROPERTY:${theTARGET},INTERFACE_INCLUDE_DIRECTORIES>>"), where the $<JOIN> generator expression takes a separator and a list to join with it. CMake 2.8.12
DONE Implement support for libraries of type INTERFACE_LIBRARY which only contain interface properties. CMake 3.0.0
DONE Implement compile feature for language dialects. CMake 3.1.0

Links

http://thread.gmane.org/gmane.comp.programming.tools.cmake.user/39090/focus=39114

http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/2145

http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/2574

http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/3119

http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/3083

http://thread.gmane.org/gmane.comp.kde.devel.buildsystem/7165/

http://lists.qt-project.org/pipermail/development/2011-November/000258.html

http://www.cmake.org/pipermail/cmake/2007-June/014386.html

http://lists.qt-project.org/pipermail/development/2011-November/000251.html

http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/3119/focus=3315

http://thread.gmane.org/gmane.comp.programming.tools.cmake.user/37340