[Cmake-commits] CMake branch, next, updated. v3.0.0-rc3-2044-g4a8ed81

Stephen Kelly steveire at gmail.com
Mon Apr 7 12:05:27 EDT 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  4a8ed816dfb7b0b18168a492c481fd97b54d2ade (commit)
       via  14f0b08276963a0c65fbd51984f5c4f16c38512d (commit)
       via  2be3d8d4e8631b954d7c3836b4e01b9a5873e950 (commit)
       via  8a156df344e1ae7cda726f191445bd03e8744db3 (commit)
       via  b3ad313b6d7e7e37e26d03583d164b6c018bb92f (commit)
       via  c65e0d3d0d6595cb5c5dcae277f854580e4a37d9 (commit)
       via  0e25b369a4c6797b12123cda6b2cde04c60b3254 (commit)
      from  abf56a0ae10cd00dd598389894c67da9053d8e44 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4a8ed816dfb7b0b18168a492c481fd97b54d2ade
commit 4a8ed816dfb7b0b18168a492c481fd97b54d2ade
Merge: abf56a0 14f0b08
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Mon Apr 7 12:05:24 2014 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Mon Apr 7 12:05:24 2014 -0400

    Merge topic 'target_compile_features' into next
    
    14f0b082 Export: Populate INTERFACE_COMPILE_FEATURES property.
    2be3d8d4 Add target_compile_features command.
    8a156df3 cmTargetPropCommandBase: Change the interface to return bool.
    b3ad313b cmTarget: Transitively evaluate compiler features.
    c65e0d3d cmTarget: Allow populating COMPILE_FEATURES using generator expressions.
    0e25b369 Features: Add cxx_auto_type.


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=14f0b08276963a0c65fbd51984f5c4f16c38512d
commit 14f0b08276963a0c65fbd51984f5c4f16c38512d
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Dec 17 19:23:40 2013 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Mon Apr 7 18:05:01 2014 +0200

    Export: Populate INTERFACE_COMPILE_FEATURES property.

diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index e79206d..6c8ebb6 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -85,6 +85,9 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
     this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", te,
                                     cmGeneratorExpression::BuildInterface,
                                     properties, missingTargets);
+    this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", te,
+                                    cmGeneratorExpression::BuildInterface,
+                                    properties, missingTargets);
     this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
                                   te, properties);
     const bool newCMP0022Behavior =
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index a83a228..89071c0 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -149,6 +149,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
                                   te,
                                   cmGeneratorExpression::InstallInterface,
                                   properties, missingTargets);
+    this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES",
+                                  te,
+                                  cmGeneratorExpression::InstallInterface,
+                                  properties, missingTargets);
 
     const bool newCMP0022Behavior =
                               te->GetPolicyStatusCMP0022() != cmPolicies::WARN
diff --git a/Tests/ExportImport/Export/Interface/CMakeLists.txt b/Tests/ExportImport/Export/Interface/CMakeLists.txt
index 9d4793d..1b653eb 100644
--- a/Tests/ExportImport/Export/Interface/CMakeLists.txt
+++ b/Tests/ExportImport/Export/Interface/CMakeLists.txt
@@ -23,7 +23,10 @@ set_property(TARGET sharedlib PROPERTY INTERFACE_COMPILE_DEFINITIONS "SHAREDLIB_
 add_library(sharediface INTERFACE)
 target_link_libraries(sharediface INTERFACE sharedlib)
 
-install(TARGETS headeronly sharediface
+add_library(use_auto_type INTERFACE)
+target_compile_features(use_auto_type INTERFACE cxx_auto_type)
+
+install(TARGETS headeronly sharediface use_auto_type
   EXPORT expInterface
 )
 install(TARGETS sharedlib
diff --git a/Tests/ExportImport/Import/CMakeLists.txt b/Tests/ExportImport/Import/CMakeLists.txt
index 5e809a2..229e579 100644
--- a/Tests/ExportImport/Import/CMakeLists.txt
+++ b/Tests/ExportImport/Import/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.7.20090711)
+cmake_minimum_required (VERSION 3.0)
 project(Import C CXX)
 
 # Import everything in a subdirectory.
diff --git a/Tests/ExportImport/Import/Interface/CMakeLists.txt b/Tests/ExportImport/Import/Interface/CMakeLists.txt
index cf7e2bc..1f30c67 100644
--- a/Tests/ExportImport/Import/Interface/CMakeLists.txt
+++ b/Tests/ExportImport/Import/Interface/CMakeLists.txt
@@ -40,6 +40,23 @@ macro(do_try_compile prefix)
   if(NOT ${prefix}IFACE_TRY_COMPILE)
     message(SEND_ERROR "${prefix} try_compile with IMPORTED INTERFACE target failed!\n\n${OUTPUT}")
   endif()
+
+  if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_auto_type;")
+    set(CMAKE_REQUIRED_LIBRARIES ${prefix}::use_auto_type)
+    check_cxx_source_compiles(
+      "
+    int main(int,char**)
+    {
+      auto value = 0;
+      return value;
+    }
+    " ${prefix}IMPORTED_IFACE_CONSTEXPR)
+
+    if(NOT ${prefix}IMPORTED_IFACE_CONSTEXPR)
+      message(SEND_ERROR "${prefix} try_compile with IMPORTED INTERFACE target failed!\n\n${OUTPUT}")
+    endif()
+  endif()
+
 endmacro()
 
 do_try_compile(bld)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2be3d8d4e8631b954d7c3836b4e01b9a5873e950
commit 2be3d8d4e8631b954d7c3836b4e01b9a5873e950
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 13 14:25:08 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Mon Apr 7 18:05:01 2014 +0200

    Add target_compile_features command.
    
    This can be used to set the compiler features required by particular
    targets. An error is issued at CMake time if the compiler does not
    support the required feature. If a language dialect flag is required
    by the features used, that will be added automatically.
    
    Base the target_compile_features command on cmTargetPropCommandBase. This
    gives us 'free' handling of IMPORTED, ALIAS, INTERFACE, non-compilable
    and missing targets.

diff --git a/Help/command/target_compile_features.rst b/Help/command/target_compile_features.rst
new file mode 100644
index 0000000..f8e5c54
--- /dev/null
+++ b/Help/command/target_compile_features.rst
@@ -0,0 +1,30 @@
+target_compile_features
+-----------------------
+
+Add expected compiler features to a target.
+
+::
+
+  target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])
+
+Specify compiler features required when compiling a given target.  If the
+feature is not listed in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable,
+then an error will be reported by CMake.  If the use of the feature requires
+an additional compiler flag, such as ``-std=c++11``, the flag will be added
+automatically.
+
+The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
+specify the scope of the features.  ``PRIVATE`` and ``PUBLIC`` items will
+populate the :prop_tgt:`COMPILE_FEATURES` property of ``<target>``.
+``PUBLIC`` and ``INTERFACE`` items will populate the
+:prop_tgt:`INTERFACE_COMPILE_FEATURES` property of ``<target>``.  Repeated
+calls for the same ``<target>`` append items.
+
+The named ``<target>`` must have been created by a command such as
+:command:`add_executable` or :command:`add_library` and must not be
+an ``IMPORTED`` target.
+
+Arguments to ``target_compile_features`` may use "generator expressions"
+with the syntax ``$<...>``.
+See the :manual:`cmake-generator-expressions(7)` manual for available
+expressions.
diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst
index 4b1dbed..17c3236 100644
--- a/Help/manual/cmake-commands.7.rst
+++ b/Help/manual/cmake-commands.7.rst
@@ -91,6 +91,7 @@ These commands may be used freely in CMake projects.
    /command/source_group
    /command/string
    /command/target_compile_definitions
+   /command/target_compile_features
    /command/target_compile_options
    /command/target_include_directories
    /command/target_link_libraries
diff --git a/Help/release/dev/compile-language-features.rst b/Help/release/dev/compile-language-features.rst
index 74fe209..3c5d7ca 100644
--- a/Help/release/dev/compile-language-features.rst
+++ b/Help/release/dev/compile-language-features.rst
@@ -12,3 +12,7 @@ target-language-features
   information to ensure that the compiler in use is capable of building
   the target, and to add any necessary compile flags to support language
   features.
+
+* New :command:`target_compile_features` command allows populating the
+  :prop_tgt:`COMPILE_FEATURES` target property, just like any other
+  build variable.
diff --git a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
index d49bb68..3278b2e 100644
--- a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
+++ b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
@@ -7,6 +7,9 @@ The features listed in this variable may be known to be available to the
 C++ compiler.  If the feature is available with the C++ compiler, it will
 be listed in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable.
 
+The features listed here may be used with the :command:`target_compile_features`
+command.
+
 The features known to this version of CMake are:
 
 ``cxx_auto_type``
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 4c678d8..660c0c5 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -346,6 +346,7 @@ foreach(command_file
     cmSourceGroupCommand
     cmSubdirDependsCommand
     cmTargetCompileDefinitionsCommand
+    cmTargetCompileFeaturesCommand
     cmTargetCompileOptionsCommand
     cmTargetIncludeDirectoriesCommand
     cmTargetSourcesCommand
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
new file mode 100644
index 0000000..10daad4
--- /dev/null
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -0,0 +1,70 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <steveire at gmail.com>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmTargetCompileFeaturesCommand.h"
+
+bool cmTargetCompileFeaturesCommand::InitialPass(
+  std::vector<std::string> const& args,
+  cmExecutionStatus &)
+{
+  return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS);
+}
+
+void cmTargetCompileFeaturesCommand
+::HandleImportedTarget(const std::string &tgt)
+{
+  cmOStringStream e;
+  e << "Cannot specify compile features for imported target \""
+    << tgt << "\".";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+void cmTargetCompileFeaturesCommand
+::HandleMissingTarget(const std::string &name)
+{
+  cmOStringStream e;
+  e << "Cannot specify compile features for target \"" << name << "\" "
+       "which is not built by this project.";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+std::string cmTargetCompileFeaturesCommand
+::Join(const std::vector<std::string> &content)
+{
+  std::string defs;
+  std::string sep;
+  for(std::vector<std::string>::const_iterator it = content.begin();
+    it != content.end(); ++it)
+    {
+    defs += sep + *it;
+    sep = ";";
+    }
+  return defs;
+}
+
+//----------------------------------------------------------------------------
+bool cmTargetCompileFeaturesCommand
+::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
+                                   bool, bool)
+{
+  for(std::vector<std::string>::const_iterator it = content.begin();
+    it != content.end(); ++it)
+    {
+    std::string error;
+    if(!this->Makefile->AddRequiredTargetFeature(tgt, *it, &error))
+      {
+      this->SetError(error);
+      return false;
+      }
+    }
+  return true;
+}
diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h
new file mode 100644
index 0000000..fa7ae8d
--- /dev/null
+++ b/Source/cmTargetCompileFeaturesCommand.h
@@ -0,0 +1,41 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <steveire at gmail.com>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmTargetCompileFeaturesCommand_h
+#define cmTargetCompileFeaturesCommand_h
+
+#include "cmTargetPropCommandBase.h"
+
+class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase
+{
+  virtual cmCommand* Clone()
+    {
+    return new cmTargetCompileFeaturesCommand;
+    }
+
+  virtual bool InitialPass(std::vector<std::string> const& args,
+                           cmExecutionStatus &status);
+
+  virtual std::string GetName() const { return "target_compile_features";}
+
+  cmTypeMacro(cmTargetCompileFeaturesCommand, cmTargetPropCommandBase);
+
+private:
+  virtual void HandleImportedTarget(const std::string &tgt);
+  virtual void HandleMissingTarget(const std::string &name);
+
+  virtual bool HandleDirectContent(cmTarget *tgt,
+                                   const std::vector<std::string> &content,
+                                   bool prepend, bool system);
+  virtual std::string Join(const std::vector<std::string> &content);
+};
+
+#endif
diff --git a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
new file mode 100644
index 0000000..ad76411
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.0)
+project(target_compile_features)
+
+set(CMAKE_VERBOSE_MAKEFILE ON)
+
+add_executable(target_compile_features main.cpp)
+target_compile_features(target_compile_features
+  PRIVATE cxx_auto_type
+)
+
+add_library(lib_auto_type lib_auto_type.cpp)
+target_compile_features(lib_auto_type
+  PUBLIC cxx_auto_type
+)
+
+add_executable(lib_user lib_user.cpp)
+target_link_libraries(lib_user lib_auto_type)
diff --git a/Tests/CMakeCommands/target_compile_features/dummy.cpp b/Tests/CMakeCommands/target_compile_features/dummy.cpp
new file mode 100644
index 0000000..341aaaf
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/dummy.cpp
@@ -0,0 +1,5 @@
+
+int main(int, char **)
+{
+  return 0;
+}
diff --git a/Tests/CMakeCommands/target_compile_features/lib_auto_type.cpp b/Tests/CMakeCommands/target_compile_features/lib_auto_type.cpp
new file mode 100644
index 0000000..71b2215
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/lib_auto_type.cpp
@@ -0,0 +1,6 @@
+
+int getAutoTypeImpl()
+{
+  auto i = 0;
+  return i;
+}
diff --git a/Tests/CMakeCommands/target_compile_features/lib_auto_type.h b/Tests/CMakeCommands/target_compile_features/lib_auto_type.h
new file mode 100644
index 0000000..c825b10
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/lib_auto_type.h
@@ -0,0 +1,8 @@
+
+int getAutoTypeImpl();
+
+int getAutoType()
+{
+  auto i = getAutoTypeImpl();
+  return i;
+}
diff --git a/Tests/CMakeCommands/target_compile_features/lib_user.cpp b/Tests/CMakeCommands/target_compile_features/lib_user.cpp
new file mode 100644
index 0000000..976068a
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/lib_user.cpp
@@ -0,0 +1,7 @@
+
+#include "lib_auto_type.h"
+
+int main(int argc, char **argv)
+{
+  return getAutoType();
+}
diff --git a/Tests/CMakeCommands/target_compile_features/main.cpp b/Tests/CMakeCommands/target_compile_features/main.cpp
new file mode 100644
index 0000000..fe29b04
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/main.cpp
@@ -0,0 +1,6 @@
+
+int main(int, char **)
+{
+  auto i = 0;
+  return i;
+}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index fc58f1e..c1d5cde 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -200,6 +200,7 @@ if(BUILD_TESTING)
   if(CMAKE_CXX_COMPILER_ID STREQUAL GNU
       AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
     ADD_TEST_MACRO(CompileFeatures CompileFeatures)
+    ADD_TEST_MACRO(CMakeCommands.target_compile_features target_compile_features)
   endif()
   # assume no resources building to test
   set(TEST_RESOURCES FALSE)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index dd769ac..00e6702 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -125,6 +125,10 @@ endif()
 add_RunCMake_test(File_Generate)
 add_RunCMake_test(ExportWithoutLanguage)
 add_RunCMake_test(target_link_libraries)
+
+if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
+  add_RunCMake_test(target_compile_features)
+endif()
 add_RunCMake_test(CheckModules)
 add_RunCMake_test(CommandLine)
 
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features-result.txt b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features-stderr.txt b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features-stderr.txt
new file mode 100644
index 0000000..d819d15
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at NotAFeature_OriginDebug_target_compile_features.cmake:4 \(target_compile_features\):
+  target_compile_features specified unknown feature "not_a_feature" for
+  target "somelib".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features.cmake b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features.cmake
new file mode 100644
index 0000000..467d9a1
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features.cmake
@@ -0,0 +1,4 @@
+
+set(CMAKE_DEBUG_TARGET_PROPERTIES COMPILE_FEATURES)
+add_library(somelib STATIC empty.cpp)
+target_compile_features(somelib PRIVATE not_a_feature)
diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
index a059900..a6aeeee 100644
--- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
@@ -6,3 +6,4 @@ run_cmake(NotAFeatureTransitive)
 run_cmake(NotAFeature_OriginDebug)
 run_cmake(NotAFeature_OriginDebugGenex)
 run_cmake(NotAFeature_OriginDebugTransitive)
+run_cmake(NotAFeature_OriginDebug_target_compile_features)
diff --git a/Tests/RunCMake/target_compile_features/CMakeLists.txt b/Tests/RunCMake/target_compile_features/CMakeLists.txt
new file mode 100644
index 0000000..3482e6b
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.0)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
new file mode 100644
index 0000000..f2abef7
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
@@ -0,0 +1,11 @@
+include(RunCMake)
+
+run_cmake(not_enough_args)
+run_cmake(alias_target)
+run_cmake(utility_target)
+run_cmake(invalid_args)
+run_cmake(invalid_args_on_interface)
+run_cmake(imported_target)
+run_cmake(no_target)
+run_cmake(not_a_cxx_feature)
+run_cmake(no_matching_cxx_feature)
diff --git a/Tests/RunCMake/target_compile_features/alias_target-result.txt b/Tests/RunCMake/target_compile_features/alias_target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/alias_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/alias_target-stderr.txt b/Tests/RunCMake/target_compile_features/alias_target-stderr.txt
new file mode 100644
index 0000000..417bf62
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/alias_target-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at alias_target.cmake:4 \(target_compile_features\):
+  target_compile_features can not be used on an ALIAS target.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/alias_target.cmake b/Tests/RunCMake/target_compile_features/alias_target.cmake
new file mode 100644
index 0000000..d35ddba
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/alias_target.cmake
@@ -0,0 +1,4 @@
+
+add_executable(main empty.cpp)
+add_executable(Alias::Main ALIAS main)
+target_compile_features(Alias::Main PRIVATE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/empty.cpp b/Tests/RunCMake/target_compile_features/empty.cpp
new file mode 100644
index 0000000..bfbbdde
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/target_compile_features/imported_target-result.txt b/Tests/RunCMake/target_compile_features/imported_target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/imported_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/imported_target-stderr.txt b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
new file mode 100644
index 0000000..c6ff5ec
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at imported_target.cmake:3 \(target_compile_features\):
+  Cannot specify compile features for imported target "main".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/imported_target.cmake b/Tests/RunCMake/target_compile_features/imported_target.cmake
new file mode 100644
index 0000000..e248c2f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/imported_target.cmake
@@ -0,0 +1,3 @@
+
+add_library(main INTERFACE IMPORTED)
+target_compile_features(main INTERFACE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args-result.txt b/Tests/RunCMake/target_compile_features/invalid_args-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt b/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt
new file mode 100644
index 0000000..bd5b7b9
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at invalid_args.cmake:3 \(target_compile_features\):
+  target_compile_features called with invalid arguments
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args.cmake b/Tests/RunCMake/target_compile_features/invalid_args.cmake
new file mode 100644
index 0000000..1a7fb37
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args.cmake
@@ -0,0 +1,3 @@
+
+add_executable(main empty.cpp)
+target_compile_features(main INVALID cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-result.txt b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
new file mode 100644
index 0000000..c30209a
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at invalid_args_on_interface.cmake:3 \(target_compile_features\):
+  target_compile_features may only be set INTERFACE properties on INTERFACE
+  targets
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake b/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake
new file mode 100644
index 0000000..324d0f3
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake
@@ -0,0 +1,3 @@
+
+add_library(main INTERFACE)
+target_compile_features(main PRIVATE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-result.txt b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt
new file mode 100644
index 0000000..4c76c7a
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at no_matching_cxx_feature.cmake:[0-9][0-9]? \((target_compile_features|message)\):
+  The compiler feature "[^"]+" is not known to compiler
+
+  "[^"]*"
+
+  version *[.0-9]+\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake
new file mode 100644
index 0000000..0452dbf
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake
@@ -0,0 +1,26 @@
+
+if (NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";gnu_cxx_typeof;"
+    AND NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";msvc_cxx_sealed;" )
+  # Simulate passing the test.
+  message(SEND_ERROR
+    "The compiler feature \"gnu_cxx_dummy\" is not known to compiler\n\"GNU\"\nversion 4.8.1."
+  )
+  return()
+endif()
+
+if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";gnu_cxx_typeof;")
+  set(feature msvc_cxx_sealed)
+  if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";msvc_cxx_sealed;")
+    # If a compiler supports both extensions, remove one of them.
+    list(REMOVE_ITEM CMAKE_CXX_COMPILE_FEATURES msvc_cxx_sealed)
+  endif()
+else()
+  set(feature gnu_cxx_typeof)
+endif()
+
+add_executable(main empty.cpp)
+
+target_compile_features(main
+  PRIVATE
+    ${feature}
+)
diff --git a/Tests/RunCMake/target_compile_features/no_target-result.txt b/Tests/RunCMake/target_compile_features/no_target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/no_target-stderr.txt b/Tests/RunCMake/target_compile_features/no_target-stderr.txt
new file mode 100644
index 0000000..323ba7a
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_target-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at no_target.cmake:2 \(target_compile_features\):
+  Cannot specify compile features for target "main" which is not built by
+  this project.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/no_target.cmake b/Tests/RunCMake/target_compile_features/no_target.cmake
new file mode 100644
index 0000000..3f0afe2
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_target.cmake
@@ -0,0 +1,2 @@
+
+target_compile_features(main INTERFACE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature-result.txt b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt
new file mode 100644
index 0000000..efa2bad
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at not_a_cxx_feature.cmake:3 \(target_compile_features\):
+  target_compile_features specified unknown feature "cxx_not_a_feature" for
+  target "main".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake b/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake
new file mode 100644
index 0000000..0207b72
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake
@@ -0,0 +1,6 @@
+
+add_executable(main empty.cpp)
+target_compile_features(main
+  PRIVATE
+    cxx_not_a_feature
+)
diff --git a/Tests/RunCMake/target_compile_features/not_enough_args-result.txt b/Tests/RunCMake/target_compile_features/not_enough_args-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_enough_args-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt b/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt
new file mode 100644
index 0000000..2f8d812
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at not_enough_args.cmake:3 \(target_compile_features\):
+  target_compile_features called with incorrect number of arguments
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/not_enough_args.cmake b/Tests/RunCMake/target_compile_features/not_enough_args.cmake
new file mode 100644
index 0000000..9561230
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_enough_args.cmake
@@ -0,0 +1,3 @@
+
+add_executable(main empty.cpp)
+target_compile_features(main)
diff --git a/Tests/RunCMake/target_compile_features/utility_target-result.txt b/Tests/RunCMake/target_compile_features/utility_target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/utility_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/utility_target-stderr.txt b/Tests/RunCMake/target_compile_features/utility_target-stderr.txt
new file mode 100644
index 0000000..d239059
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/utility_target-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at utility_target.cmake:4 \(target_compile_features\):
+  target_compile_features called with non-compilable target type
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/utility_target.cmake b/Tests/RunCMake/target_compile_features/utility_target.cmake
new file mode 100644
index 0000000..8919056
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/utility_target.cmake
@@ -0,0 +1,4 @@
+
+add_custom_target(utility)
+
+target_compile_features(utility PRIVATE cxx_delegating_constructors)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8a156df344e1ae7cda726f191445bd03e8744db3
commit 8a156df344e1ae7cda726f191445bd03e8744db3
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sat Nov 9 00:18:35 2013 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Mon Apr 7 18:05:01 2014 +0200

    cmTargetPropCommandBase: Change the interface to return bool.
    
    This is needed for the target_compile_features command, which
    may fail at configure time if an invalid feature is specified.

diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index b567252..66d8ad3 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -58,9 +58,10 @@ std::string cmTargetCompileDefinitionsCommand
 }
 
 //----------------------------------------------------------------------------
-void cmTargetCompileDefinitionsCommand
+bool cmTargetCompileDefinitionsCommand
 ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
                                    bool, bool)
 {
   tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
+  return true;
 }
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
index 5ba9e03..b548c70 100644
--- a/Source/cmTargetCompileDefinitionsCommand.h
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -44,7 +44,7 @@ private:
   virtual void HandleImportedTarget(const std::string &tgt);
   virtual void HandleMissingTarget(const std::string &name);
 
-  virtual void HandleDirectContent(cmTarget *tgt,
+  virtual bool HandleDirectContent(cmTarget *tgt,
                                    const std::vector<std::string> &content,
                                    bool prepend, bool system);
   virtual std::string Join(const std::vector<std::string> &content);
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
index 254acc7..18499fd 100644
--- a/Source/cmTargetCompileOptionsCommand.cxx
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -51,7 +51,7 @@ std::string cmTargetCompileOptionsCommand
 }
 
 //----------------------------------------------------------------------------
-void cmTargetCompileOptionsCommand
+bool cmTargetCompileOptionsCommand
 ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
                                    bool, bool)
 {
@@ -59,4 +59,5 @@ void cmTargetCompileOptionsCommand
   this->Makefile->GetBacktrace(lfbt);
   cmValueWithOrigin entry(this->Join(content), lfbt);
   tgt->InsertCompileOption(entry);
+  return true;
 }
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
index d58dc07..d43534d 100644
--- a/Source/cmTargetCompileOptionsCommand.h
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -44,7 +44,7 @@ private:
   virtual void HandleImportedTarget(const std::string &tgt);
   virtual void HandleMissingTarget(const std::string &name);
 
-  virtual void HandleDirectContent(cmTarget *tgt,
+  virtual bool HandleDirectContent(cmTarget *tgt,
                                    const std::vector<std::string> &content,
                                    bool prepend, bool system);
   virtual std::string Join(const std::vector<std::string> &content);
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index f8e1188..caec7eb 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -66,7 +66,7 @@ std::string cmTargetIncludeDirectoriesCommand
 }
 
 //----------------------------------------------------------------------------
-void cmTargetIncludeDirectoriesCommand
+bool cmTargetIncludeDirectoriesCommand
 ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
                       bool prepend, bool system)
 {
@@ -78,6 +78,7 @@ void cmTargetIncludeDirectoriesCommand
     {
     tgt->AddSystemIncludeDirectories(content);
     }
+  return true;
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
index c8b22fb..2a7814e 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.h
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -45,7 +45,7 @@ private:
   virtual void HandleImportedTarget(const std::string &tgt);
   virtual void HandleMissingTarget(const std::string &name);
 
-  virtual void HandleDirectContent(cmTarget *tgt,
+  virtual bool HandleDirectContent(cmTarget *tgt,
                                    const std::vector<std::string> &content,
                                    bool prepend, bool system);
   virtual void HandleInterfaceContent(cmTarget *tgt,
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index d356611..4696de4 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -132,29 +132,31 @@ bool cmTargetPropCommandBase
         || args[i] == "PRIVATE"
         || args[i] == "INTERFACE" )
       {
-      this->PopulateTargetProperies(scope, content, prepend, system);
-      return true;
+      return this->PopulateTargetProperies(scope, content, prepend, system);
       }
     content.push_back(args[i]);
     }
-  this->PopulateTargetProperies(scope, content, prepend, system);
-  return true;
+  return this->PopulateTargetProperies(scope, content, prepend, system);
 }
 
 //----------------------------------------------------------------------------
-void cmTargetPropCommandBase
+bool cmTargetPropCommandBase
 ::PopulateTargetProperies(const std::string &scope,
                           const std::vector<std::string> &content,
                           bool prepend, bool system)
 {
   if (scope == "PRIVATE" || scope == "PUBLIC")
     {
-    this->HandleDirectContent(this->Target, content, prepend, system);
+    if (!this->HandleDirectContent(this->Target, content, prepend, system))
+      {
+      return false;
+      }
     }
   if (scope == "INTERFACE" || scope == "PUBLIC")
     {
     this->HandleInterfaceContent(this->Target, content, prepend, system);
     }
+  return true;
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index 555a08a..d42b588 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -44,7 +44,7 @@ private:
   virtual void HandleImportedTarget(const std::string &tgt) = 0;
   virtual void HandleMissingTarget(const std::string &name) = 0;
 
-  virtual void HandleDirectContent(cmTarget *tgt,
+  virtual bool HandleDirectContent(cmTarget *tgt,
                                    const std::vector<std::string> &content,
                                    bool prepend, bool system) = 0;
 
@@ -52,7 +52,7 @@ private:
 
   bool ProcessContentArgs(std::vector<std::string> const& args,
                           unsigned int &argIndex, bool prepend, bool system);
-  void PopulateTargetProperies(const std::string &scope,
+  bool PopulateTargetProperies(const std::string &scope,
                                const std::vector<std::string> &content,
                                bool prepend, bool system);
 };
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index e82b36d..ce3b11e 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -56,9 +56,10 @@ std::string cmTargetSourcesCommand
 }
 
 //----------------------------------------------------------------------------
-void cmTargetSourcesCommand
+bool cmTargetSourcesCommand
 ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
                       bool, bool)
 {
   tgt->AppendProperty("SOURCES", this->Join(content).c_str());
+  return true;
 }
diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h
index dae78c4..a170e36 100644
--- a/Source/cmTargetSourcesCommand.h
+++ b/Source/cmTargetSourcesCommand.h
@@ -45,7 +45,7 @@ private:
   virtual void HandleImportedTarget(const std::string &tgt);
   virtual void HandleMissingTarget(const std::string &name);
 
-  virtual void HandleDirectContent(cmTarget *tgt,
+  virtual bool HandleDirectContent(cmTarget *tgt,
                                    const std::vector<std::string> &content,
                                    bool prepend, bool system);
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b3ad313b6d7e7e37e26d03583d164b6c018bb92f
commit b3ad313b6d7e7e37e26d03583d164b6c018bb92f
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Oct 22 01:40:47 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Mon Apr 7 18:05:01 2014 +0200

    cmTarget: Transitively evaluate compiler features.
    
    Extend the interface of the target_compile_features command with
    PUBLIC and INTERFACE keywords. Populate the INTERFACE_COMPILER_FEATURES
    target property if they are set. Consume the INTERFACE_COMPILER_FEATURES
    target property from linked dependent targets to determine the final
    required compiler features and the compile flag, if needed.
    
    Use the same pattern of origin-debugging which is used for other
    build properties.

diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 30413ae..a82522d 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -151,6 +151,7 @@ Properties on Targets
    /prop_tgt/INSTALL_RPATH_USE_LINK_PATH
    /prop_tgt/INTERFACE_AUTOUIC_OPTIONS
    /prop_tgt/INTERFACE_COMPILE_DEFINITIONS
+   /prop_tgt/INTERFACE_COMPILE_FEATURES
    /prop_tgt/INTERFACE_COMPILE_OPTIONS
    /prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
    /prop_tgt/INTERFACE_LINK_LIBRARIES
diff --git a/Help/prop_tgt/INTERFACE_COMPILE_FEATURES.rst b/Help/prop_tgt/INTERFACE_COMPILE_FEATURES.rst
new file mode 100644
index 0000000..a98e362
--- /dev/null
+++ b/Help/prop_tgt/INTERFACE_COMPILE_FEATURES.rst
@@ -0,0 +1,14 @@
+INTERFACE_COMPILE_FEATURES
+--------------------------
+
+List of public compile requirements for a library.
+
+Targets may populate this property to publish the compiler features
+required to compile against the headers for the target.  Consuming
+targets can add entries to their own :prop_tgt:`COMPILE_FEATURES`
+property such as ``$<TARGET_PROPERTY:foo,INTERFACE_COMPILE_FEATURES>``
+to require the features specified in the interface of ``foo``.
+
+Contents of ``INTERFACE_COMPILE_FEATURES`` may use "generator expressions"
+with the syntax ``$<...>``.  See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions.
diff --git a/Help/variable/CMAKE_DEBUG_TARGET_PROPERTIES.rst b/Help/variable/CMAKE_DEBUG_TARGET_PROPERTIES.rst
index edd8fa1..e200b86 100644
--- a/Help/variable/CMAKE_DEBUG_TARGET_PROPERTIES.rst
+++ b/Help/variable/CMAKE_DEBUG_TARGET_PROPERTIES.rst
@@ -7,7 +7,7 @@ This variable can be populated with a list of properties to generate
 debug output for when evaluating target properties.  Currently it can
 only be used when evaluating the :prop_tgt:`INCLUDE_DIRECTORIES`,
 :prop_tgt:`COMPILE_DEFINITIONS`, :prop_tgt:`COMPILE_OPTIONS`,
-:prop_tgt:`AUTOUIC_OPTIONS`, :prop_tgt:`SOURCES`,
+:prop_tgt:`AUTOUIC_OPTIONS`, :prop_tgt:`SOURCES`, :prop_tgt:`COMPILE_FEATURES`,
 :prop_tgt:`POSITION_INDEPENDENT_CODE` target properties and any other property
 listed in :prop_tgt:`COMPATIBLE_INTERFACE_STRING` and other ``COMPATIBLE_INTERFACE_``
 properties.  It outputs an origin for each entry in the target property.
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index b3147f7..7217a56 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -26,7 +26,8 @@
   SELECT(F, EvaluatingCompileDefinitions,       COMPILE_DEFINITIONS) \
   SELECT(F, EvaluatingCompileOptions,           COMPILE_OPTIONS) \
   SELECT(F, EvaluatingAutoUicOptions,           AUTOUIC_OPTIONS) \
-  SELECT(F, EvaluatingSources,                  SOURCES)
+  SELECT(F, EvaluatingSources,                  SOURCES) \
+  SELECT(F, EvaluatingCompileFeatures,          COMPILE_FEATURES)
 
 #define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \
   CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH)
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index f581806..528b1dc 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1460,7 +1460,7 @@ void cmLocalGenerator::AddCompileOptions(
       }
     }
   std::vector<std::string> features;
-  target->GetCompileFeatures(features);
+  target->GetCompileFeatures(features, config);
   for(std::vector<std::string>::const_iterator it = features.begin();
       it != features.end(); ++it)
     {
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 09e3339..1d4d84c 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -166,11 +166,14 @@ public:
                                 CachedLinkInterfaceCompileDefinitionsEntries;
   mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
                                 CachedLinkInterfaceSourcesEntries;
+  mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
+                                CachedLinkInterfaceCompileFeaturesEntries;
 
   mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
   mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
   mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
   mutable std::map<std::string, bool> CacheLinkInterfaceSourcesDone;
+  mutable std::map<std::string, bool> CacheLinkInterfaceCompileFeaturesDone;
 };
 
 //----------------------------------------------------------------------------
@@ -205,6 +208,7 @@ cmTargetInternals::~cmTargetInternals()
 {
   deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
   deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
+  deleteAndClear(this->CachedLinkInterfaceCompileFeaturesEntries);
   deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
   deleteAndClear(this->CachedLinkInterfaceSourcesEntries);
 }
@@ -228,6 +232,7 @@ cmTarget::cmTarget()
   this->BuildInterfaceIncludesAppended = false;
   this->DebugIncludesDone = false;
   this->DebugCompileOptionsDone = false;
+  this->DebugCompileFeaturesDone = false;
   this->DebugCompileDefinitionsDone = false;
   this->DebugSourcesDone = false;
 }
@@ -2617,18 +2622,114 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
 }
 
 //----------------------------------------------------------------------------
-void cmTarget::GetCompileFeatures(std::vector<std::string> &features) const
+static void processCompileFeatures(cmTarget const* tgt,
+      const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+      std::vector<std::string> &options,
+      std::set<std::string> &uniqueOptions,
+      cmGeneratorExpressionDAGChecker *dagChecker,
+      const std::string& config, bool debugOptions)
 {
-  assert(this->GetType() != INTERFACE_LIBRARY);
-  for(std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
-      si = this->Internal->CompileFeaturesEntries.begin();
-      si != this->Internal->CompileFeaturesEntries.end(); ++si)
+  processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+                                dagChecker, config, debugOptions, "features");
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::GetCompileFeatures(std::vector<std::string> &result,
+                                  const std::string& config) const
+{
+  std::set<std::string> uniqueFeatures;
+  cmListFileBacktrace lfbt;
+
+  cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+                                             this->GetName(),
+                                             "COMPILE_FEATURES",
+                                             0, 0);
+
+  std::vector<std::string> debugProperties;
+  const char *debugProp =
+              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+  if (debugProp)
     {
-    cmSystemTools::ExpandListArgument((*si)->ge->Evaluate(this->Makefile,
-                                        "",
-                                        false,
-                                        this),
-                                      features);
+    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+    }
+
+  bool debugFeatures = !this->DebugCompileFeaturesDone
+                    && std::find(debugProperties.begin(),
+                                 debugProperties.end(),
+                                 "COMPILE_FEATURES")
+                        != debugProperties.end();
+
+  if (this->Makefile->IsGeneratingBuildSystem())
+    {
+    this->DebugCompileFeaturesDone = true;
+    }
+
+  processCompileFeatures(this,
+                            this->Internal->CompileFeaturesEntries,
+                            result,
+                            uniqueFeatures,
+                            &dagChecker,
+                            config,
+                            debugFeatures);
+
+  if (!this->Internal->CacheLinkInterfaceCompileFeaturesDone[config])
+    {
+    for (std::vector<cmValueWithOrigin>::const_iterator
+        it = this->Internal->LinkImplementationPropertyEntries.begin(),
+        end = this->Internal->LinkImplementationPropertyEntries.end();
+        it != end; ++it)
+      {
+      if (!cmGeneratorExpression::IsValidTargetName(it->Value)
+          && cmGeneratorExpression::Find(it->Value) == std::string::npos)
+        {
+        continue;
+        }
+      {
+      cmGeneratorExpression ge(lfbt);
+      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+                                                        ge.Parse(it->Value);
+      std::string targetResult = cge->Evaluate(this->Makefile, config,
+                                        false, this, 0, 0);
+      if (!this->Makefile->FindTargetToUse(targetResult))
+        {
+        continue;
+        }
+      }
+      std::string featureGenex = "$<TARGET_PROPERTY:" +
+                              it->Value + ",INTERFACE_COMPILE_FEATURES>";
+      if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
+        {
+        // Because it->Value is a generator expression, ensure that it
+        // evaluates to the non-empty string before being used in the
+        // TARGET_PROPERTY expression.
+        featureGenex = "$<$<BOOL:" + it->Value + ">:" + featureGenex + ">";
+        }
+      cmGeneratorExpression ge(it->Backtrace);
+      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
+                                                                featureGenex);
+
+      this->Internal
+        ->CachedLinkInterfaceCompileFeaturesEntries[config].push_back(
+                        new cmTargetInternals::TargetPropertyEntry(cge,
+                                                              it->Value));
+      }
+    }
+
+  processCompileFeatures(this,
+    this->Internal->CachedLinkInterfaceCompileFeaturesEntries[config],
+                            result,
+                            uniqueFeatures,
+                            &dagChecker,
+                            config,
+                            debugFeatures);
+
+  if (!this->Makefile->IsGeneratingBuildSystem())
+    {
+    deleteAndClear(this->Internal->CachedLinkInterfaceCompileFeaturesEntries);
+    }
+  else
+    {
+    this->Internal->CacheLinkInterfaceCompileFeaturesDone[config] = true;
     }
 }
 
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index fe3ea2b..8984649 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -545,7 +545,8 @@ public:
                          const std::string& config) const;
   void GetAutoUicOptions(std::vector<std::string> &result,
                          const std::string& config) const;
-  void GetCompileFeatures(std::vector<std::string> &features) const;
+  void GetCompileFeatures(std::vector<std::string> &features,
+                          const std::string& config) const;
 
   bool IsNullImpliedByLinkLibraries(const std::string &p) const;
   bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
@@ -712,6 +713,7 @@ private:
   mutable bool DebugCompileOptionsDone;
   mutable bool DebugCompileDefinitionsDone;
   mutable bool DebugSourcesDone;
+  mutable bool DebugCompileFeaturesDone;
   mutable std::set<std::string> LinkImplicitNullProperties;
   bool BuildInterfaceIncludesAppended;
 
diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt
index 2114f94..bceb6bb 100644
--- a/Tests/CompileFeatures/CMakeLists.txt
+++ b/Tests/CompileFeatures/CMakeLists.txt
@@ -27,3 +27,10 @@ add_executable(GenexCompileFeatures main.cpp)
 set_property(TARGET GenexCompileFeatures
   PROPERTY COMPILE_FEATURES "$<1:cxx_auto_type>;$<0:not_a_feature>"
 )
+
+add_library(iface INTERFACE)
+set_property(TARGET iface
+  PROPERTY INTERFACE_COMPILE_FEATURES "cxx_auto_type"
+)
+add_executable(IfaceCompileFeatures main.cpp)
+target_link_libraries(IfaceCompileFeatures iface)
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeatureTransitive-result.txt b/Tests/RunCMake/CompileFeatures/NotAFeatureTransitive-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeatureTransitive-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeatureTransitive-stderr.txt b/Tests/RunCMake/CompileFeatures/NotAFeatureTransitive-stderr.txt
new file mode 100644
index 0000000..ff60e50
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeatureTransitive-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error in CMakeLists.txt:
+  Specified unknown feature "not_a_feature" for target "somelib".
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeatureTransitive.cmake b/Tests/RunCMake/CompileFeatures/NotAFeatureTransitive.cmake
new file mode 100644
index 0000000..7311aec
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeatureTransitive.cmake
@@ -0,0 +1,6 @@
+
+add_library(iface INTERFACE)
+set_property(TARGET iface PROPERTY INTERFACE_COMPILE_FEATURES "not_a_feature")
+
+add_library(somelib STATIC empty.cpp)
+target_link_libraries(somelib iface)
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug-result.txt b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug-stderr.txt b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug-stderr.txt
new file mode 100644
index 0000000..60a8e51
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug-stderr.txt
@@ -0,0 +1,11 @@
+CMake Debug Log at NotAFeature_OriginDebug.cmake:4 \(set_property\):
+  Used compile features for target somelib:
+
+   \* not_a_feature
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error in CMakeLists.txt:
+  Specified unknown feature "not_a_feature" for target "somelib".
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug.cmake b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug.cmake
new file mode 100644
index 0000000..350c2ea
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug.cmake
@@ -0,0 +1,4 @@
+
+set(CMAKE_DEBUG_TARGET_PROPERTIES COMPILE_FEATURES)
+add_library(somelib STATIC empty.cpp)
+set_property(TARGET somelib PROPERTY COMPILE_FEATURES "not_a_feature")
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex-result.txt b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex-stderr.txt b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex-stderr.txt
new file mode 100644
index 0000000..08e20a8
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex-stderr.txt
@@ -0,0 +1,11 @@
+CMake Debug Log at NotAFeature_OriginDebugGenex.cmake:4 \(set_property\):
+  Used compile features for target somelib:
+
+   \* not_a_feature
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error in CMakeLists.txt:
+  Specified unknown feature "not_a_feature" for target "somelib".
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex.cmake b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex.cmake
new file mode 100644
index 0000000..2122981
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex.cmake
@@ -0,0 +1,4 @@
+
+set(CMAKE_DEBUG_TARGET_PROPERTIES COMPILE_FEATURES)
+add_library(somelib STATIC empty.cpp)
+set_property(TARGET somelib PROPERTY COMPILE_FEATURES "$<1:not_a_feature>")
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive-result.txt b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive-stderr.txt b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive-stderr.txt
new file mode 100644
index 0000000..23c3305
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive-stderr.txt
@@ -0,0 +1,11 @@
+CMake Debug Log at NotAFeature_OriginDebugTransitive.cmake:6 \(target_link_libraries\):
+  Used compile features for target somelib:
+
+   \* not_a_feature
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error in CMakeLists.txt:
+  Specified unknown feature "not_a_feature" for target "somelib".
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive.cmake b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive.cmake
new file mode 100644
index 0000000..05d0073
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive.cmake
@@ -0,0 +1,6 @@
+
+set(CMAKE_DEBUG_TARGET_PROPERTIES COMPILE_FEATURES)
+add_library(iface INTERFACE)
+set_property(TARGET iface PROPERTY INTERFACE_COMPILE_FEATURES "not_a_feature")
+add_library(somelib STATIC empty.cpp)
+target_link_libraries(somelib iface)
diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
index da9477d..a059900 100644
--- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
@@ -2,3 +2,7 @@ include(RunCMake)
 
 run_cmake(NotAFeature)
 run_cmake(NotAFeatureGenex)
+run_cmake(NotAFeatureTransitive)
+run_cmake(NotAFeature_OriginDebug)
+run_cmake(NotAFeature_OriginDebugGenex)
+run_cmake(NotAFeature_OriginDebugTransitive)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c65e0d3d0d6595cb5c5dcae277f854580e4a37d9
commit c65e0d3d0d6595cb5c5dcae277f854580e4a37d9
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Oct 22 15:05:49 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Mon Apr 7 18:05:00 2014 +0200

    cmTarget: Allow populating COMPILE_FEATURES using generator expressions.
    
    Delay validation of the content as a feature if it contains a
    generator expression. It will be checked again at generate-time
    after evaluation.

diff --git a/Help/prop_tgt/COMPILE_FEATURES.rst b/Help/prop_tgt/COMPILE_FEATURES.rst
index b2c6145..dc32825 100644
--- a/Help/prop_tgt/COMPILE_FEATURES.rst
+++ b/Help/prop_tgt/COMPILE_FEATURES.rst
@@ -5,3 +5,7 @@ Compiler features enabled for this target.
 
 The list of features in this property are a subset of the features listed
 in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable.
+
+Contents of ``COMPILE_FEATURES`` may use "generator expressions" with the
+syntax ``$<...>``.  See the :manual:`cmake-generator-expressions(7)` manual for
+available expressions.
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 0f8e7dc..f581806 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1459,17 +1459,14 @@ void cmLocalGenerator::AddCompileOptions(
       this->AppendFlagEscape(flags, *i);
       }
     }
-  if (const char* featureProp = target->GetProperty("COMPILE_FEATURES"))
+  std::vector<std::string> features;
+  target->GetCompileFeatures(features);
+  for(std::vector<std::string>::const_iterator it = features.begin();
+      it != features.end(); ++it)
     {
-    std::vector<std::string> features;
-    cmSystemTools::ExpandListArgument(featureProp, features);
-    for(std::vector<std::string>::const_iterator it = features.begin();
-        it != features.end(); ++it)
+     if (!this->Makefile->AddRequiredTargetFeature(target, *it))
       {
-      if (!this->Makefile->AddRequiredTargetFeature(target, *it))
-        {
-        return;
-        }
+      return;
       }
     }
   this->AddCompilerRequirementFlag(flags, target, lang);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 0b3c43e..5004a08 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -4521,6 +4521,11 @@ bool cmMakefile::
 AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
                          std::string *error) const
 {
+  if (cmGeneratorExpression::Find(feature) != std::string::npos)
+    {
+    target->AppendProperty("COMPILE_FEATURES", feature.c_str());
+    return true;
+    }
   bool isCxxFeature = std::find_if(cmArrayBegin(CXX_FEATURES) + 1,
               cmArrayEnd(CXX_FEATURES), cmStrCmp(feature))
               != cmArrayEnd(CXX_FEATURES);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 6f53009..09e3339 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -2617,6 +2617,22 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
 }
 
 //----------------------------------------------------------------------------
+void cmTarget::GetCompileFeatures(std::vector<std::string> &features) const
+{
+  assert(this->GetType() != INTERFACE_LIBRARY);
+  for(std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
+      si = this->Internal->CompileFeaturesEntries.begin();
+      si != this->Internal->CompileFeaturesEntries.end(); ++si)
+    {
+    cmSystemTools::ExpandListArgument((*si)->ge->Evaluate(this->Makefile,
+                                        "",
+                                        false,
+                                        this),
+                                      features);
+    }
+}
+
+//----------------------------------------------------------------------------
 void cmTarget::MaybeInvalidatePropertyCache(const std::string& prop)
 {
   // Wipe out maps caching information affected by this property.
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index da9d0a1..fe3ea2b 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -545,6 +545,7 @@ public:
                          const std::string& config) const;
   void GetAutoUicOptions(std::vector<std::string> &result,
                          const std::string& config) const;
+  void GetCompileFeatures(std::vector<std::string> &features) const;
 
   bool IsNullImpliedByLinkLibraries(const std::string &p) const;
   bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt
index 471b560..2114f94 100644
--- a/Tests/CompileFeatures/CMakeLists.txt
+++ b/Tests/CompileFeatures/CMakeLists.txt
@@ -22,3 +22,8 @@ add_executable(CompileFeatures main.cpp)
 set_property(TARGET CompileFeatures
   PROPERTY COMPILE_FEATURES "cxx_auto_type"
 )
+
+add_executable(GenexCompileFeatures main.cpp)
+set_property(TARGET GenexCompileFeatures
+  PROPERTY COMPILE_FEATURES "$<1:cxx_auto_type>;$<0:not_a_feature>"
+)
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeatureGenex-result.txt b/Tests/RunCMake/CompileFeatures/NotAFeatureGenex-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeatureGenex-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeatureGenex-stderr.txt b/Tests/RunCMake/CompileFeatures/NotAFeatureGenex-stderr.txt
new file mode 100644
index 0000000..ff60e50
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeatureGenex-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error in CMakeLists.txt:
+  Specified unknown feature "not_a_feature" for target "somelib".
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeatureGenex.cmake b/Tests/RunCMake/CompileFeatures/NotAFeatureGenex.cmake
new file mode 100644
index 0000000..ad2bd37
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeatureGenex.cmake
@@ -0,0 +1,3 @@
+
+add_library(somelib STATIC empty.cpp)
+set_property(TARGET somelib PROPERTY COMPILE_FEATURES "$<1:not_a_feature>")
diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
index 3c999e6..da9477d 100644
--- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
@@ -1,3 +1,4 @@
 include(RunCMake)
 
 run_cmake(NotAFeature)
+run_cmake(NotAFeatureGenex)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0e25b369a4c6797b12123cda6b2cde04c60b3254
commit 0e25b369a4c6797b12123cda6b2cde04c60b3254
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Wed Apr 2 15:34:16 2014 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Mon Apr 7 18:05:00 2014 +0200

    Features: Add cxx_auto_type.
    
    Record the availability of this feature for GNU 4.8 on (UNIX AND
    NOT APPLE) only.  In the future, availability can be recorded for
    earlier GNU, for other platforms and for other compilers. Initially
    the affected configurations are as restricted as possible to allow
    for easy testing while extending the features vector in only one
    dimension.
    
    The error message when using the set_property API directly is not
    very good, but follow up commits will provide origin debugging of
    the property and a target_compile_features command which will
    provide a configure-time backtrace when possible.

diff --git a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
index 7466d44..d49bb68 100644
--- a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
+++ b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
@@ -6,3 +6,10 @@ List of C++ features known to this version of CMake.
 The features listed in this variable may be known to be available to the
 C++ compiler.  If the feature is available with the C++ compiler, it will
 be listed in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable.
+
+The features known to this version of CMake are:
+
+``cxx_auto_type``
+  Automatic type deduction, as defined in N1984_.
+
+  .. _N1984: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf
diff --git a/Modules/Compiler/GNU-CXX-FeatureTests.cmake b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
new file mode 100644
index 0000000..b36315f
--- /dev/null
+++ b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
@@ -0,0 +1,8 @@
+
+# Reference: http://gcc.gnu.org/projects/cxx0x.html
+
+set(_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 408")
+# TODO: Should be supported by GNU 4.4
+set(GNU44_CXX11 "${_oldestSupported} && __cplusplus >= 201103L")
+set(_cmake_feature_test_cxx_auto_type "${GNU44_CXX11}")
+set(_oldestSupported)
diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake
index 3ee8639..7acad52 100644
--- a/Modules/Compiler/GNU-CXX.cmake
+++ b/Modules/Compiler/GNU-CXX.cmake
@@ -23,3 +23,15 @@ elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
   set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++0x")
   set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x")
 endif()
+
+macro(cmake_record_cxx_compile_features)
+  macro(_get_gcc_features std_version list)
+    record_compiler_features(CXX "-std=${std_version}" ${list})
+  endmacro()
+
+  if (UNIX AND NOT APPLE AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
+    _get_gcc_features(c++11 CMAKE_CXX11_COMPILE_FEATURES)
+  else()
+    set(_result 0)
+  endif()
+endmacro()
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 64163de..0b3c43e 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -41,7 +41,8 @@
 #include <ctype.h> // for isspace
 #include <assert.h>
 
-#define FOR_EACH_CXX_FEATURE(F)
+#define FOR_EACH_CXX_FEATURE(F) \
+  F(cxx_auto_type)
 
 class cmMakefile::Internals
 {
@@ -2453,6 +2454,12 @@ const char* cmMakefile::GetDefinition(const std::string& name) const
     {
     this->Internal->VarUsageStack.top().insert(name);
     }
+  if (name == "CMAKE_CXX_KNOWN_FEATURES")
+    {
+#define STRING_LIST_ELEMENT(F) ";" #F
+    return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1;
+#undef STRING_LIST_ELEMENT
+    }
   const char* def = this->Internal->VarStack.top().Get(name);
   if(!def)
     {
@@ -4520,7 +4527,15 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
   if (!isCxxFeature)
     {
     cmOStringStream e;
-    e << "specified unknown feature \"" << feature << "\" specified for "
+    if (error)
+      {
+      e << "specified";
+      }
+    else
+      {
+      e << "Specified";
+      }
+    e << " unknown feature \"" << feature << "\" for "
       "target \"" << target->GetName() << "\".";
     if (error)
       {
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index aaa24c7..fc58f1e 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -197,6 +197,10 @@ if(BUILD_TESTING)
   ADD_TEST_MACRO(TarTest TarTest)
   ADD_TEST_MACRO(SystemInformation SystemInformation)
   ADD_TEST_MACRO(MathTest MathTest)
+  if(CMAKE_CXX_COMPILER_ID STREQUAL GNU
+      AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
+    ADD_TEST_MACRO(CompileFeatures CompileFeatures)
+  endif()
   # assume no resources building to test
   set(TEST_RESOURCES FALSE)
   # for windows and cygwin assume we have resources
diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt
new file mode 100644
index 0000000..471b560
--- /dev/null
+++ b/Tests/CompileFeatures/CMakeLists.txt
@@ -0,0 +1,24 @@
+
+cmake_minimum_required(VERSION 3.0)
+
+project(CompileFeatures)
+
+macro(run_test feature)
+  if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ${feature})
+    add_library(test_${feature} OBJECT ${feature}.cpp)
+    set_property(TARGET test_${feature}
+      PROPERTY COMPILE_FEATURES "${feature}"
+    )
+  else()
+    message("Not supported: ${feature}")
+  endif()
+endmacro()
+
+foreach(feature ${CMAKE_CXX_KNOWN_FEATURES})
+  run_test(${feature})
+endforeach()
+
+add_executable(CompileFeatures main.cpp)
+set_property(TARGET CompileFeatures
+  PROPERTY COMPILE_FEATURES "cxx_auto_type"
+)
diff --git a/Tests/CompileFeatures/main.cpp b/Tests/CompileFeatures/main.cpp
new file mode 100644
index 0000000..3a8e0fc
--- /dev/null
+++ b/Tests/CompileFeatures/main.cpp
@@ -0,0 +1,6 @@
+
+int main(int,char**)
+{
+  auto value = 0;
+  return value;
+}
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 851de42..dd769ac 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -53,6 +53,7 @@ add_RunCMake_test(ObjectLibrary)
 add_RunCMake_test(TargetObjects)
 add_RunCMake_test(TargetSources)
 add_RunCMake_test(find_dependency)
+add_RunCMake_test(CompileFeatures)
 if(NOT WIN32)
   add_RunCMake_test(PositionIndependentCode)
   set(SKIP_VISIBILITY 0)
diff --git a/Tests/RunCMake/CompileFeatures/CMakeLists.txt b/Tests/RunCMake/CompileFeatures/CMakeLists.txt
new file mode 100644
index 0000000..3482e6b
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.0)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature-result.txt b/Tests/RunCMake/CompileFeatures/NotAFeature-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature-stderr.txt b/Tests/RunCMake/CompileFeatures/NotAFeature-stderr.txt
new file mode 100644
index 0000000..ff60e50
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error in CMakeLists.txt:
+  Specified unknown feature "not_a_feature" for target "somelib".
diff --git a/Tests/RunCMake/CompileFeatures/NotAFeature.cmake b/Tests/RunCMake/CompileFeatures/NotAFeature.cmake
new file mode 100644
index 0000000..35246c8
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NotAFeature.cmake
@@ -0,0 +1,3 @@
+
+add_library(somelib STATIC empty.cpp)
+set_property(TARGET somelib PROPERTY COMPILE_FEATURES "not_a_feature")
diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
new file mode 100644
index 0000000..3c999e6
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
@@ -0,0 +1,3 @@
+include(RunCMake)
+
+run_cmake(NotAFeature)
diff --git a/Tests/RunCMake/CompileFeatures/empty.cpp b/Tests/RunCMake/CompileFeatures/empty.cpp
new file mode 100644
index 0000000..bfbbdde
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+  return 0;
+}
diff --git a/Tests/SystemInformation/SystemInformation.in b/Tests/SystemInformation/SystemInformation.in
index 92b24e2..954a2fe 100644
--- a/Tests/SystemInformation/SystemInformation.in
+++ b/Tests/SystemInformation/SystemInformation.in
@@ -25,6 +25,8 @@ CMAKE_CXX98_STANDARD_COMPILE_OPTION == "${CMAKE_CXX98_STANDARD_COMPILE_OPTION}"
 CMAKE_CXX11_STANDARD_COMPILE_OPTION == "${CMAKE_CXX11_STANDARD_COMPILE_OPTION}"
 CMAKE_CXX98_EXTENSION_COMPILE_OPTION == "${CMAKE_CXX98_EXTENSION_COMPILE_OPTION}"
 CMAKE_CXX11_EXTENSION_COMPILE_OPTION == "${CMAKE_CXX11_EXTENSION_COMPILE_OPTION}"
+CMAKE_CXX_COMPILE_FEATURES == "${CMAKE_CXX_COMPILE_FEATURES}"
+CMAKE_CXX11_COMPILE_FEATURES == "${CMAKE_CXX11_COMPILE_FEATURES}"
 
 // C shared library flag
 CMAKE_SHARED_LIBRARY_C_FLAGS == "${CMAKE_SHARED_LIBRARY_C_FLAGS}"

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list