From 59b5fdd37c87dd27205e3756d17a186e02e0d326 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 11 Nov 2013 20:35:52 +0100 Subject: Don't load Clang-CXX from AppleClang-CXX. The Clang-CXX module is going to get version-specific checks, and the version system for AppleClang is not the same as Clang. --- Modules/Compiler/AppleClang-CXX.cmake | 7 ++++++- Modules/Compiler/Clang-CXX.cmake | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Modules/Compiler/AppleClang-CXX.cmake b/Modules/Compiler/AppleClang-CXX.cmake index 680f720..0372e18 100644 --- a/Modules/Compiler/AppleClang-CXX.cmake +++ b/Modules/Compiler/AppleClang-CXX.cmake @@ -1 +1,6 @@ -include(Compiler/Clang-CXX) +include(Compiler/Clang) +__compiler_clang(CXX) + +if(NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") + set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") +endif() diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index 0372e18..ab1b766 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -4,3 +4,8 @@ __compiler_clang(CXX) if(NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") endif() + +cmake_policy(GET CMP0025 appleClangPolicy) +if(NOT appleClangPolicy STREQUAL NEW) + return() +endif() -- cgit v0.12 From 892243fc3bbc2bbd859cf6c6aaa7b1e1c19d59c9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 2 Apr 2014 14:18:32 +0200 Subject: Tests: Require CMake 3.0 for the SystemInformation test. Correctly identify AppleClang. --- Tests/SystemInformation/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/SystemInformation/CMakeLists.txt b/Tests/SystemInformation/CMakeLists.txt index c33380f..db54612 100644 --- a/Tests/SystemInformation/CMakeLists.txt +++ b/Tests/SystemInformation/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 3.0) project(SystemInformation) include_directories("This does not exists") -- cgit v0.12 From 8238a6cd5d2867e709e87a752e0a24c7c2bf28f0 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 13 Oct 2013 01:26:16 +0200 Subject: Add some COMPILE_OPTIONS for specifying C++ dialect. These are compiler-specific, compiler version specific, extension specific and standard version specific. --- Modules/Compiler/Clang-CXX.cmake | 13 +++++++++++++ Modules/Compiler/GNU-CXX.cmake | 13 +++++++++++++ Tests/SystemInformation/SystemInformation.in | 4 ++++ 3 files changed, 30 insertions(+) diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index ab1b766..a1b3a10 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -9,3 +9,16 @@ cmake_policy(GET CMP0025 appleClangPolicy) if(NOT appleClangPolicy STREQUAL NEW) return() endif() + +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1) + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") +endif() + +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11") +elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++0x") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x") +endif() diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index 33d6093..3ee8639 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -10,3 +10,16 @@ else() set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") endif() endif() + +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3) + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") +endif() + +if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11") +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() diff --git a/Tests/SystemInformation/SystemInformation.in b/Tests/SystemInformation/SystemInformation.in index df3bf49..92b24e2 100644 --- a/Tests/SystemInformation/SystemInformation.in +++ b/Tests/SystemInformation/SystemInformation.in @@ -21,6 +21,10 @@ CMAKE_C_COMPILER_ID == "${CMAKE_C_COMPILER_ID}" CMAKE_C_COMPILER_VERSION == "${CMAKE_C_COMPILER_VERSION}" CMAKE_CXX_COMPILER_ID == "${CMAKE_CXX_COMPILER_ID}" CMAKE_CXX_COMPILER_VERSION == "${CMAKE_CXX_COMPILER_VERSION}" +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}" // C shared library flag CMAKE_SHARED_LIBRARY_C_FLAGS == "${CMAKE_SHARED_LIBRARY_C_FLAGS}" -- cgit v0.12 From 913394af249d6b1892a6e609d2abfed001fa1dc4 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 13 Oct 2013 02:00:24 +0200 Subject: cmTarget: Add CXX_STANDARD and CXX_EXTENSION target properties. These are used to determine whether to add -std=c++11, -std=gnu++11 etc flags on the compile line. --- Help/manual/cmake-properties.7.rst | 2 ++ Help/manual/cmake-variables.7.rst | 2 ++ Help/prop_tgt/CXX_EXTENSIONS.rst | 8 +++++++ Help/prop_tgt/CXX_STANDARD.rst | 14 +++++++++++++ Help/release/dev/compile-language-features.rst | 8 +++++++ Help/variable/CMAKE_CXX_EXTENSIONS.rst | 8 +++++++ Help/variable/CMAKE_CXX_STANDARD.rst | 8 +++++++ Source/cmLocalGenerator.cxx | 29 ++++++++++++++++++++++++++ Source/cmLocalGenerator.h | 2 ++ Source/cmTarget.cxx | 2 ++ Tests/CMakeLists.txt | 13 ++++++++++++ Tests/CxxDialect/CMakeLists.txt | 14 +++++++++++++ Tests/CxxDialect/use_constexpr.cxx | 10 +++++++++ Tests/CxxDialect/use_constexpr_and_typeof.cxx | 11 ++++++++++ Tests/CxxDialect/use_typeof.cxx | 6 ++++++ 15 files changed, 137 insertions(+) create mode 100644 Help/prop_tgt/CXX_EXTENSIONS.rst create mode 100644 Help/prop_tgt/CXX_STANDARD.rst create mode 100644 Help/release/dev/compile-language-features.rst create mode 100644 Help/variable/CMAKE_CXX_EXTENSIONS.rst create mode 100644 Help/variable/CMAKE_CXX_STANDARD.rst create mode 100644 Tests/CxxDialect/CMakeLists.txt create mode 100644 Tests/CxxDialect/use_constexpr.cxx create mode 100644 Tests/CxxDialect/use_constexpr_and_typeof.cxx create mode 100644 Tests/CxxDialect/use_typeof.cxx diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index fd16eb9..9ea50de 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -106,6 +106,8 @@ Properties on Targets /prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /prop_tgt/CONFIG_OUTPUT_NAME /prop_tgt/CONFIG_POSTFIX + /prop_tgt/CXX_STANDARD + /prop_tgt/CXX_EXTENSIONS /prop_tgt/DEBUG_POSTFIX /prop_tgt/DEFINE_SYMBOL /prop_tgt/EchoString diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 4fac6a5..62a7cce 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -257,6 +257,8 @@ Variables for Languages :maxdepth: 1 /variable/CMAKE_COMPILER_IS_GNULANG + /variable/CMAKE_CXX_STANDARD + /variable/CMAKE_CXX_EXTENSIONS /variable/CMAKE_Fortran_MODDIR_DEFAULT /variable/CMAKE_Fortran_MODDIR_FLAG /variable/CMAKE_Fortran_MODOUT_FLAG diff --git a/Help/prop_tgt/CXX_EXTENSIONS.rst b/Help/prop_tgt/CXX_EXTENSIONS.rst new file mode 100644 index 0000000..b9c9931 --- /dev/null +++ b/Help/prop_tgt/CXX_EXTENSIONS.rst @@ -0,0 +1,8 @@ +CXX_EXTENSIONS +-------------- + +Boolean specifying whether compiler specific extensions are requested. + +This property specifies whether compiler specific extensions should be +used. For some compilers, this results in adding a flag such +as ``-std=gnu++11`` instead of ``-std=c++11`` to the compile line. diff --git a/Help/prop_tgt/CXX_STANDARD.rst b/Help/prop_tgt/CXX_STANDARD.rst new file mode 100644 index 0000000..e1b6e78 --- /dev/null +++ b/Help/prop_tgt/CXX_STANDARD.rst @@ -0,0 +1,14 @@ +CXX_STANDARD +------------ + +The C++ standard whose features are required to build this target. + +This property specifies the C++ standard whose features are required +to build this target. For some compilers, this results in adding a +flag such as ``-std=c++11`` to the compile line. + +Supported values are ``98`` and ``11``. + +This property is initialized by the value of +the :variable:`CMAKE_CXX_STANDARD` variable if it is set when a target +is created. diff --git a/Help/release/dev/compile-language-features.rst b/Help/release/dev/compile-language-features.rst new file mode 100644 index 0000000..f03e1a3 --- /dev/null +++ b/Help/release/dev/compile-language-features.rst @@ -0,0 +1,8 @@ +target-language-features +------------------------ + +* New :prop_tgt:`CXX_STANDARD` and :prop_tgt:`CXX_EXTENSIONS` target + properties may specify values which CMake uses to compute required + compile options such as ``-std=c++11`` or ``-std=gnu++11``. The + :variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_EXTENSIONS` + variables may be set to initialize the target properties. diff --git a/Help/variable/CMAKE_CXX_EXTENSIONS.rst b/Help/variable/CMAKE_CXX_EXTENSIONS.rst new file mode 100644 index 0000000..734d508 --- /dev/null +++ b/Help/variable/CMAKE_CXX_EXTENSIONS.rst @@ -0,0 +1,8 @@ +CMAKE_CXX_EXTENSIONS +-------------------- + +Default value for ``CXX_EXTENSIONS`` property of targets. + +This variable is used to initialize the :prop_tgt:`CXX_EXTENSIONS` +property on all targets. See that target property for additional +information. diff --git a/Help/variable/CMAKE_CXX_STANDARD.rst b/Help/variable/CMAKE_CXX_STANDARD.rst new file mode 100644 index 0000000..5fd4138 --- /dev/null +++ b/Help/variable/CMAKE_CXX_STANDARD.rst @@ -0,0 +1,8 @@ +CMAKE_CXX_STANDARD +------------------ + +Default value for ``CXX_STANDARD`` property of targets. + +This variable is used to initialize the :prop_tgt:`CXX_STANDARD` +property on all targets. See that target property for additional +information. diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 1e65a02..779a2b8 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1459,6 +1459,7 @@ void cmLocalGenerator::AddCompileOptions( this->AppendFlagEscape(flags, *i); } } + this->AddCompilerRequirementFlag(flags, target, lang); } //---------------------------------------------------------------------------- @@ -2128,6 +2129,34 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags, } } +//---------------------------------------------------------------------------- +void cmLocalGenerator:: +AddCompilerRequirementFlag(std::string &flags, cmTarget* target, + const std::string& lang) +{ + if (lang.empty()) + { + return; + } + std::string stdProp = lang + "_STANDARD"; + const char *standard = target->GetProperty(stdProp); + if (!standard) + { + return; + } + std::string extProp = lang + "_EXTENSIONS"; + bool ext = target->GetPropertyAsBool(extProp); + std::string type = ext ? "EXTENSION" : "STANDARD"; + + std::string compile_option = + "CMAKE_" + lang + std::string(standard) + + "_" + type + "_COMPILE_OPTION"; + if (const char *opt = target->GetMakefile()->GetDefinition(compile_option)) + { + this->AppendFlags(flags, opt); + } +} + static void AddVisibilityCompileOption(std::string &flags, cmTarget* target, cmLocalGenerator *lg, const std::string& lang) diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 8f30149..12a94e4 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -149,6 +149,8 @@ public: const std::string& lang); void AddConfigVariableFlags(std::string& flags, const std::string& var, const std::string& config); + void AddCompilerRequirementFlag(std::string &flags, cmTarget* target, + const std::string& lang); ///! Append flags to a string. virtual void AppendFlags(std::string& flags, const char* newFlags); virtual void AppendFlagEscape(std::string& flags, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index d28ac3f..53c0205 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -307,6 +307,8 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("MACOSX_BUNDLE", 0); this->SetPropertyDefault("MACOSX_RPATH", 0); this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0); + this->SetPropertyDefault("CXX_STANDARD", 0); + this->SetPropertyDefault("CXX_EXTENSIONS", 0); } // Collect the set of configuration types. diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 0e60ed1..aaa24c7 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -283,6 +283,19 @@ if(BUILD_TESTING) ADD_TEST_MACRO(ConfigSources ConfigSources) endif() ADD_TEST_MACRO(SourcesProperty SourcesProperty) + if(CMAKE_CXX_COMPILER_ID STREQUAL GNU + AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) + set(runCxxDialectTest 1) + endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL Clang + AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.9) + if(NOT APPLE OR POLICY CMP0025) + set(runCxxDialectTest 1) + endif() + endif() + if(runCxxDialectTest) + ADD_TEST_MACRO(CxxDialect CxxDialect) + endif() set_tests_properties(EmptyLibrary PROPERTIES PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test") ADD_TEST_MACRO(CrossCompile CrossCompile) diff --git a/Tests/CxxDialect/CMakeLists.txt b/Tests/CxxDialect/CMakeLists.txt new file mode 100644 index 0000000..0eb6f8f --- /dev/null +++ b/Tests/CxxDialect/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8.12) +cmake_policy(SET CMP0025 NEW) +project(CxxDialect) + +add_executable(use_typeof use_typeof.cxx) +set_property(TARGET use_typeof PROPERTY CXX_STANDARD 98) +set_property(TARGET use_typeof PROPERTY CXX_EXTENSIONS ON) + +add_executable(use_constexpr use_constexpr.cxx) +set_property(TARGET use_constexpr PROPERTY CXX_STANDARD 11) + +add_executable(CxxDialect use_constexpr_and_typeof.cxx) +set_property(TARGET CxxDialect PROPERTY CXX_STANDARD 11) +set_property(TARGET CxxDialect PROPERTY CXX_EXTENSIONS ON) diff --git a/Tests/CxxDialect/use_constexpr.cxx b/Tests/CxxDialect/use_constexpr.cxx new file mode 100644 index 0000000..30ccc4c --- /dev/null +++ b/Tests/CxxDialect/use_constexpr.cxx @@ -0,0 +1,10 @@ + +constexpr int foo() +{ + return 0; +} + +int main(int argc, char**) +{ + return foo(); +} diff --git a/Tests/CxxDialect/use_constexpr_and_typeof.cxx b/Tests/CxxDialect/use_constexpr_and_typeof.cxx new file mode 100644 index 0000000..af217b6 --- /dev/null +++ b/Tests/CxxDialect/use_constexpr_and_typeof.cxx @@ -0,0 +1,11 @@ + +constexpr int foo() +{ + return 0; +} + +int main(int argc, char**) +{ + typeof(argc) ret = foo(); + return ret; +} diff --git a/Tests/CxxDialect/use_typeof.cxx b/Tests/CxxDialect/use_typeof.cxx new file mode 100644 index 0000000..dabb61f --- /dev/null +++ b/Tests/CxxDialect/use_typeof.cxx @@ -0,0 +1,6 @@ + +int main(int argc, char**) +{ + typeof(argc) ret = 0; + return ret; +} -- cgit v0.12 From faeddf64f21b592a5663803ca8accdf9f4b73c29 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 17 Oct 2013 11:47:29 +0200 Subject: project: Add infrastructure for recording CXX compiler features Add a feature test using the compiler macros and the preprocessor to determine available features. Add a CMAKE_CXX_COMPILE_FEATURES variable which contains all features known to the loaded compiler, and a CMAKE_CXX_KNOWN_FEATURES variable containing all features known to CMake. Add language standard specific variables for internal use to determine the standard-specific compile flags to use. This will be extended to other languages in the future. Follow-up commits will add features which will be recorded by the feature test. --- Help/manual/cmake-variables.7.rst | 2 + Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst | 8 ++++ Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst | 8 ++++ Modules/CMakeCXXCompiler.cmake.in | 3 ++ Modules/CMakeDetermineCompileFeatures.cmake | 43 +++++++++++++++++++++ Modules/CMakeTestCXXCompiler.cmake | 3 ++ Modules/Internal/FeatureTesting.cmake | 57 ++++++++++++++++++++++++++++ 7 files changed, 124 insertions(+) create mode 100644 Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst create mode 100644 Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst create mode 100644 Modules/CMakeDetermineCompileFeatures.cmake create mode 100644 Modules/Internal/FeatureTesting.cmake diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 62a7cce..dfdd09b 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -257,6 +257,8 @@ Variables for Languages :maxdepth: 1 /variable/CMAKE_COMPILER_IS_GNULANG + /variable/CMAKE_CXX_COMPILE_FEATURES + /variable/CMAKE_CXX_KNOWN_FEATURES /variable/CMAKE_CXX_STANDARD /variable/CMAKE_CXX_EXTENSIONS /variable/CMAKE_Fortran_MODDIR_DEFAULT diff --git a/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst b/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst new file mode 100644 index 0000000..6be0124 --- /dev/null +++ b/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst @@ -0,0 +1,8 @@ +CMAKE_CXX_COMPILE_FEATURES +-------------------------- + +List of features known to the C++ compiler + +These features are known to be available for use with the C++ compiler. This +list is a subset of the features listed in the :variable:`CMAKE_CXX_KNOWN_FEATURES` +variable. diff --git a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst new file mode 100644 index 0000000..7466d44 --- /dev/null +++ b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst @@ -0,0 +1,8 @@ +CMAKE_CXX_KNOWN_FEATURES +------------------------ + +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. diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index c75611a..fdee336 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -2,6 +2,9 @@ set(CMAKE_CXX_COMPILER "@CMAKE_CXX_COMPILER@") set(CMAKE_CXX_COMPILER_ARG1 "@CMAKE_CXX_COMPILER_ARG1@") set(CMAKE_CXX_COMPILER_ID "@CMAKE_CXX_COMPILER_ID@") set(CMAKE_CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@") +set(CMAKE_CXX_COMPILE_FEATURES "@CMAKE_CXX_COMPILE_FEATURES@") +set(CMAKE_CXX11_COMPILE_FEATURES "@CMAKE_CXX11_COMPILE_FEATURES@") + set(CMAKE_CXX_PLATFORM_ID "@CMAKE_CXX_PLATFORM_ID@") set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@") set(CMAKE_CXX_SIMULATE_VERSION "@CMAKE_CXX_SIMULATE_VERSION@") diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake new file mode 100644 index 0000000..40aa9d6 --- /dev/null +++ b/Modules/CMakeDetermineCompileFeatures.cmake @@ -0,0 +1,43 @@ + +#============================================================================= +# Copyright 2013 Stephen Kelly +# +# 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. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +function(cmake_determine_compile_features lang) + + if(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features) + message(STATUS "Detecting ${lang} compile features") + + set(CMAKE_CXX11_COMPILE_FEATURES) + + include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake") + + cmake_record_cxx_compile_features() + + if(NOT _result EQUAL 0) + message(STATUS "Detecting ${lang} compile features - failed") + return() + endif() + + if(NOT CMAKE_CXX_COMPILE_FEATURES) + set(CMAKE_CXX_COMPILE_FEATURES + ${CMAKE_CXX11_COMPILE_FEATURES} + ) + endif() + + set(CMAKE_CXX_COMPILE_FEATURES ${CMAKE_CXX_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_CXX11_COMPILE_FEATURES ${CMAKE_CXX11_COMPILE_FEATURES} PARENT_SCOPE) + + message(STATUS "Detecting ${lang} compile features - done") + endif() + +endfunction() diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake index a06c92a..81561b2 100644 --- a/Modules/CMakeTestCXXCompiler.cmake +++ b/Modules/CMakeTestCXXCompiler.cmake @@ -66,6 +66,9 @@ else() # Try to identify the ABI and configure it into CMakeCXXCompiler.cmake include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) CMAKE_DETERMINE_COMPILER_ABI(CXX ${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp) + # Try to identify the compiler features + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake) + CMAKE_DETERMINE_COMPILE_FEATURES(CXX) # Re-configure to save learned information. configure_file( diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake new file mode 100644 index 0000000..92d262c --- /dev/null +++ b/Modules/Internal/FeatureTesting.cmake @@ -0,0 +1,57 @@ + +macro(record_compiler_features lang compile_flags feature_list) + include("${CMAKE_ROOT}/Modules/Compiler/${CMAKE_${lang}_COMPILER_ID}-${lang}-FeatureTests.cmake" OPTIONAL) + + string(TOLOWER ${lang} lang_lc) + file(REMOVE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin") + file(WRITE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" " + extern const char features[] = {\"\"\n") + foreach(feature ${CMAKE_${lang}_KNOWN_FEATURES}) + if (_cmake_feature_test_${feature}) + if (${_cmake_feature_test_${feature}} STREQUAL 1) + set(_feature_condition "\"1\" ") + else() + set(_feature_condition "#if ${_cmake_feature_test_${feature}}\n\"1\"\n#else\n\"0\"\n#endif\n") + endif() + file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" "\"${lang}_FEATURE:\"\n${_feature_condition}\"${feature}\\n\"\n") + endif() + endforeach() + file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" + "\n};\n\nint main(int, char **) { return 0; }\n") + + try_compile(CMAKE_${lang}_FEATURE_TEST + ${CMAKE_BINARY_DIR} "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" + COMPILE_DEFINITIONS "${compile_flags}" + OUTPUT_VARIABLE _output + COPY_FILE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin" + COPY_FILE_ERROR _copy_error + ) + if(CMAKE_${lang}_FEATURE_TEST AND NOT _copy_error) + set(_result 0) + else() + set(_result 255) + endif() + unset(CMAKE_${lang}_FEATURE_TEST CACHE) + + if (_result EQUAL 0) + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "\n\nDetecting ${lang} [${compile_flags}] compiler features compiled with the following output:\n${_output}\n\n") + if(EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin") + file(STRINGS "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin" + features REGEX "${lang}_FEATURE:.*") + foreach(info ${features}) + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + " Feature record: ${info}\n") + string(REPLACE "${lang}_FEATURE:" "" info ${info}) + string(SUBSTRING ${info} 0 1 has_feature) + if(has_feature) + string(REGEX REPLACE "^1" "" feature ${info}) + list(APPEND ${feature_list} ${feature}) + endif() + endforeach() + endif() + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Detecting ${lang} [${compile_flags}] compiler features failed to compile with the following output:\n${_output}\n${_copy_error}\n\n") + endif() +endmacro() -- cgit v0.12 From 03355d6b5b382020e7dafb28605e6d8d2f20de3c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 2 Apr 2014 15:57:15 +0200 Subject: cmTarget: Add COMPILE_FEATURES target property. Use the contents of it to upgrade the CXX_STANDARD target property, if appropriate. This will have the effect of adding the -std=c++11 compile flag or other language specification on GNU when that is needed for the feature. --- Help/manual/cmake-properties.7.rst | 1 + Help/prop_tgt/COMPILE_FEATURES.rst | 7 ++ Help/release/dev/compile-language-features.rst | 6 ++ Source/cmLocalGenerator.cxx | 13 +++ Source/cmMakefile.cxx | 113 +++++++++++++++++++++++++ Source/cmMakefile.h | 4 + Source/cmTarget.cxx | 40 +++++++++ 7 files changed, 184 insertions(+) create mode 100644 Help/prop_tgt/COMPILE_FEATURES.rst diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 9ea50de..30413ae 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -98,6 +98,7 @@ Properties on Targets /prop_tgt/COMPATIBLE_INTERFACE_STRING /prop_tgt/COMPILE_DEFINITIONS_CONFIG /prop_tgt/COMPILE_DEFINITIONS + /prop_tgt/COMPILE_FEATURES /prop_tgt/COMPILE_FLAGS /prop_tgt/COMPILE_OPTIONS /prop_tgt/COMPILE_PDB_NAME diff --git a/Help/prop_tgt/COMPILE_FEATURES.rst b/Help/prop_tgt/COMPILE_FEATURES.rst new file mode 100644 index 0000000..b2c6145 --- /dev/null +++ b/Help/prop_tgt/COMPILE_FEATURES.rst @@ -0,0 +1,7 @@ +COMPILE_FEATURES +---------------- + +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. diff --git a/Help/release/dev/compile-language-features.rst b/Help/release/dev/compile-language-features.rst index f03e1a3..74fe209 100644 --- a/Help/release/dev/compile-language-features.rst +++ b/Help/release/dev/compile-language-features.rst @@ -6,3 +6,9 @@ target-language-features compile options such as ``-std=c++11`` or ``-std=gnu++11``. The :variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_EXTENSIONS` variables may be set to initialize the target properties. + +* New :prop_tgt:`COMPILE_FEATURES` target property may contain a list + of features required to compile a target. CMake uses this + 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. diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 779a2b8..0f8e7dc 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1459,6 +1459,19 @@ void cmLocalGenerator::AddCompileOptions( this->AppendFlagEscape(flags, *i); } } + if (const char* featureProp = target->GetProperty("COMPILE_FEATURES")) + { + std::vector features; + cmSystemTools::ExpandListArgument(featureProp, features); + for(std::vector::const_iterator it = features.begin(); + it != features.end(); ++it) + { + if (!this->Makefile->AddRequiredTargetFeature(target, *it)) + { + return; + } + } + } this->AddCompilerRequirementFlag(flags, target, lang); } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 1328974..64163de 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -41,6 +41,8 @@ #include // for isspace #include +#define FOR_EACH_CXX_FEATURE(F) + class cmMakefile::Internals { public: @@ -4494,3 +4496,114 @@ void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm) pm[pid] = this->GetPolicyStatus(pid); } } + +#define FEATURE_STRING(F) , #F + +static const char * const CXX_FEATURES[] = { + 0 + FOR_EACH_CXX_FEATURE(FEATURE_STRING) +}; + +static const char * const CXX_STANDARDS[] = { + "98" + , "11" +}; + +//---------------------------------------------------------------------------- +bool cmMakefile:: +AddRequiredTargetFeature(cmTarget *target, const std::string& feature, + std::string *error) const +{ + bool isCxxFeature = std::find_if(cmArrayBegin(CXX_FEATURES) + 1, + cmArrayEnd(CXX_FEATURES), cmStrCmp(feature)) + != cmArrayEnd(CXX_FEATURES); + if (!isCxxFeature) + { + cmOStringStream e; + e << "specified unknown feature \"" << feature << "\" specified for " + "target \"" << target->GetName() << "\"."; + if (error) + { + *error = e.str(); + } + else + { + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + } + return false; + } + + std::string lang = "CXX"; + + const char* featuresKnown = + this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES"); + + if (!featuresKnown || !*featuresKnown) + { + // We know of no features for the compiler at all. + return true; + } + + std::vector availableFeatures; + cmSystemTools::ExpandListArgument(featuresKnown, availableFeatures); + if (std::find(availableFeatures.begin(), + availableFeatures.end(), + feature) == availableFeatures.end()) + { + cmOStringStream e; + e << "The compiler feature \"" << feature + << "\" is not known to compiler\n\"" + << this->GetDefinition("CMAKE_" + lang + "_COMPILER_ID") + << "\"\nversion " + << this->GetDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << "."; + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + + target->AppendProperty("COMPILE_FEATURES", feature.c_str()); + + bool needCxx11 = false; + + if (const char *propCxx11 = + this->GetDefinition("CMAKE_CXX11_COMPILE_FEATURES")) + { + std::vector props; + cmSystemTools::ExpandListArgument(propCxx11, props); + needCxx11 = std::find(props.begin(), props.end(), feature) != props.end(); + } + + const char *existingCxxStandard = target->GetProperty("CXX_STANDARD"); + if (existingCxxStandard) + { + if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), + cmStrCmp(existingCxxStandard)) == cmArrayEnd(CXX_STANDARDS)) + { + cmOStringStream e; + e << "The CXX_STANDARD property on target \"" << target->GetName() + << "\" contained an invalid value: \"" << existingCxxStandard << "\"."; + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + } + const char * const *existingCxxIt = existingCxxStandard + ? std::find_if(cmArrayBegin(CXX_STANDARDS), + cmArrayEnd(CXX_STANDARDS), + cmStrCmp(existingCxxStandard)) + : cmArrayEnd(CXX_STANDARDS); + + bool setCxx11 = needCxx11 && !existingCxxStandard; + + if (needCxx11 && existingCxxStandard && existingCxxIt < + std::find_if(cmArrayBegin(CXX_STANDARDS), + cmArrayEnd(CXX_STANDARDS), + cmStrCmp("11"))) + { + setCxx11 = true; + } + + if (setCxx11) + { + target->SetProperty("CXX_STANDARD", "11"); + } + return true; +} diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 7695d6e..3bccb63 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -885,6 +885,10 @@ public: bool PolicyOptionalWarningEnabled(std::string const& var); + bool AddRequiredTargetFeature(cmTarget *target, + const std::string& feature, + std::string *error = 0) const; + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const std::string& name, cmTarget& target); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 53c0205..6f53009 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -153,6 +153,7 @@ public: }; std::vector IncludeDirectoriesEntries; std::vector CompileOptionsEntries; + std::vector CompileFeaturesEntries; std::vector CompileDefinitionsEntries; std::vector SourceEntries; std::vector LinkImplementationPropertyEntries; @@ -1722,6 +1723,17 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) new cmTargetInternals::TargetPropertyEntry(cge)); return; } + if(prop == "COMPILE_FEATURES") + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + deleteAndClear(this->Internal->CompileFeaturesEntries); + cmsys::auto_ptr cge = ge.Parse(value); + this->Internal->CompileFeaturesEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } if(prop == "COMPILE_DEFINITIONS") { cmListFileBacktrace lfbt; @@ -1812,6 +1824,15 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); return; } + if(prop == "COMPILE_FEATURES") + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + this->Internal->CompileFeaturesEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + return; + } if(prop == "COMPILE_DEFINITIONS") { cmListFileBacktrace lfbt; @@ -3109,6 +3130,24 @@ const char *cmTarget::GetProperty(const std::string& prop, } return output.c_str(); } + if(prop == "COMPILE_FEATURES") + { + static std::string output; + output = ""; + std::string sep; + typedef cmTargetInternals::TargetPropertyEntry + TargetPropertyEntry; + for (std::vector::const_iterator + it = this->Internal->CompileFeaturesEntries.begin(), + end = this->Internal->CompileFeaturesEntries.end(); + it != end; ++it) + { + output += sep; + output += (*it)->ge->GetInput(); + sep = ";"; + } + return output.c_str(); + } if(prop == "COMPILE_DEFINITIONS") { static std::string output; @@ -6886,6 +6925,7 @@ cmTargetInternalPointer::~cmTargetInternalPointer() { deleteAndClear(this->Pointer->IncludeDirectoriesEntries); deleteAndClear(this->Pointer->CompileOptionsEntries); + deleteAndClear(this->Pointer->CompileFeaturesEntries); deleteAndClear(this->Pointer->CompileDefinitionsEntries); deleteAndClear(this->Pointer->SourceEntries); delete this->Pointer; -- cgit v0.12 From f97bf4370c283432c4e14fe54ed481d5d9b7ceef Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 2 Apr 2014 15:34:16 +0200 Subject: 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. --- Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst | 7 +++++++ Modules/Compiler/GNU-CXX-FeatureTests.cmake | 8 ++++++++ Modules/Compiler/GNU-CXX.cmake | 12 +++++++++++ Source/cmMakefile.cxx | 19 +++++++++++++++-- Tests/CMakeLists.txt | 4 ++++ Tests/CompileFeatures/CMakeLists.txt | 24 ++++++++++++++++++++++ Tests/CompileFeatures/cxx_auto_type.cpp | 5 +++++ Tests/CompileFeatures/main.cpp | 6 ++++++ Tests/RunCMake/CMakeLists.txt | 1 + Tests/RunCMake/CompileFeatures/CMakeLists.txt | 3 +++ .../CompileFeatures/NotAFeature-result.txt | 1 + .../CompileFeatures/NotAFeature-stderr.txt | 2 ++ Tests/RunCMake/CompileFeatures/NotAFeature.cmake | 3 +++ Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake | 3 +++ Tests/RunCMake/CompileFeatures/empty.cpp | 7 +++++++ Tests/SystemInformation/SystemInformation.in | 2 ++ 16 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 Modules/Compiler/GNU-CXX-FeatureTests.cmake create mode 100644 Tests/CompileFeatures/CMakeLists.txt create mode 100644 Tests/CompileFeatures/cxx_auto_type.cpp create mode 100644 Tests/CompileFeatures/main.cpp create mode 100644 Tests/RunCMake/CompileFeatures/CMakeLists.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature-result.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature-stderr.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature.cmake create mode 100644 Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/CompileFeatures/empty.cpp 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 // for isspace #include -#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/cxx_auto_type.cpp b/Tests/CompileFeatures/cxx_auto_type.cpp new file mode 100644 index 0000000..7dbf04f --- /dev/null +++ b/Tests/CompileFeatures/cxx_auto_type.cpp @@ -0,0 +1,5 @@ + +void someFunc() +{ + auto x = 3.14; +} 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}" -- cgit v0.12 From baff44345cff8e635766e020d316da514616c16e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 22 Oct 2013 15:05:49 +0200 Subject: 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. --- Help/prop_tgt/COMPILE_FEATURES.rst | 4 ++++ Source/cmLocalGenerator.cxx | 15 ++++++--------- Source/cmMakefile.cxx | 5 +++++ Source/cmTarget.cxx | 16 ++++++++++++++++ Source/cmTarget.h | 1 + Tests/CompileFeatures/CMakeLists.txt | 5 +++++ .../RunCMake/CompileFeatures/NotAFeatureGenex-result.txt | 1 + .../RunCMake/CompileFeatures/NotAFeatureGenex-stderr.txt | 2 ++ Tests/RunCMake/CompileFeatures/NotAFeatureGenex.cmake | 3 +++ Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake | 1 + 10 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeatureGenex-result.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeatureGenex-stderr.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeatureGenex.cmake 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 features; + target->GetCompileFeatures(features); + for(std::vector::const_iterator it = features.begin(); + it != features.end(); ++it) { - std::vector features; - cmSystemTools::ExpandListArgument(featureProp, features); - for(std::vector::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 &list, } //---------------------------------------------------------------------------- +void cmTarget::GetCompileFeatures(std::vector &features) const +{ + assert(this->GetType() != INTERFACE_LIBRARY); + for(std::vector::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 &result, const std::string& config) const; + void GetCompileFeatures(std::vector &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) -- cgit v0.12 From 5412deded1073e9a217c771ae24e8c5a8a581a96 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 22 Oct 2013 01:40:47 +0200 Subject: 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. --- Help/manual/cmake-properties.7.rst | 1 + Help/prop_tgt/INTERFACE_COMPILE_FEATURES.rst | 14 +++ Help/variable/CMAKE_DEBUG_TARGET_PROPERTIES.rst | 2 +- Source/cmGeneratorExpressionDAGChecker.h | 3 +- Source/cmLocalGenerator.cxx | 2 +- Source/cmTarget.cxx | 121 +++++++++++++++++++-- Source/cmTarget.h | 4 +- Tests/CompileFeatures/CMakeLists.txt | 7 ++ .../NotAFeatureTransitive-result.txt | 1 + .../NotAFeatureTransitive-stderr.txt | 2 + .../CompileFeatures/NotAFeatureTransitive.cmake | 6 + .../NotAFeature_OriginDebug-result.txt | 1 + .../NotAFeature_OriginDebug-stderr.txt | 11 ++ .../CompileFeatures/NotAFeature_OriginDebug.cmake | 4 + .../NotAFeature_OriginDebugGenex-result.txt | 1 + .../NotAFeature_OriginDebugGenex-stderr.txt | 11 ++ .../NotAFeature_OriginDebugGenex.cmake | 4 + .../NotAFeature_OriginDebugTransitive-result.txt | 1 + .../NotAFeature_OriginDebugTransitive-stderr.txt | 11 ++ .../NotAFeature_OriginDebugTransitive.cmake | 6 + Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake | 4 + 21 files changed, 203 insertions(+), 14 deletions(-) create mode 100644 Help/prop_tgt/INTERFACE_COMPILE_FEATURES.rst create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeatureTransitive-result.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeatureTransitive-stderr.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeatureTransitive.cmake create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug-result.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug-stderr.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug.cmake create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex-result.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex-stderr.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugGenex.cmake create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive-result.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive-stderr.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebugTransitive.cmake 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 ``$`` +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 features; - target->GetCompileFeatures(features); + target->GetCompileFeatures(features, config); for(std::vector::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 > CachedLinkInterfaceSourcesEntries; + mutable std::map > + CachedLinkInterfaceCompileFeaturesEntries; mutable std::map CacheLinkInterfaceIncludeDirectoriesDone; mutable std::map CacheLinkInterfaceCompileDefinitionsDone; mutable std::map CacheLinkInterfaceCompileOptionsDone; mutable std::map CacheLinkInterfaceSourcesDone; + mutable std::map 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 &list, } //---------------------------------------------------------------------------- -void cmTarget::GetCompileFeatures(std::vector &features) const +static void processCompileFeatures(cmTarget const* tgt, + const std::vector &entries, + std::vector &options, + std::set &uniqueOptions, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string& config, bool debugOptions) { - assert(this->GetType() != INTERFACE_LIBRARY); - for(std::vector::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 &result, + const std::string& config) const +{ + std::set uniqueFeatures; + cmListFileBacktrace lfbt; + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "COMPILE_FEATURES", + 0, 0); + + std::vector 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::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 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 = "$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 = "$<$Value + ">:" + featureGenex + ">"; + } + cmGeneratorExpression ge(it->Backtrace); + cmsys::auto_ptr 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 &result, const std::string& config) const; - void GetCompileFeatures(std::vector &features) const; + void GetCompileFeatures(std::vector &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 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) -- cgit v0.12 From 4e6ca504459640ff39eac48eb62fcae95c8fc8d2 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 9 Nov 2013 00:18:35 +0100 Subject: 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. --- Source/cmTargetCompileDefinitionsCommand.cxx | 3 ++- Source/cmTargetCompileDefinitionsCommand.h | 2 +- Source/cmTargetCompileOptionsCommand.cxx | 3 ++- Source/cmTargetCompileOptionsCommand.h | 2 +- Source/cmTargetIncludeDirectoriesCommand.cxx | 3 ++- Source/cmTargetIncludeDirectoriesCommand.h | 2 +- Source/cmTargetPropCommandBase.cxx | 14 ++++++++------ Source/cmTargetPropCommandBase.h | 4 ++-- Source/cmTargetSourcesCommand.cxx | 3 ++- Source/cmTargetSourcesCommand.h | 2 +- 10 files changed, 22 insertions(+), 16 deletions(-) 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 &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 &content, bool prepend, bool system); virtual std::string Join(const std::vector &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 &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 &content, bool prepend, bool system); virtual std::string Join(const std::vector &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 &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 &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 &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 &content, bool prepend, bool system) = 0; @@ -52,7 +52,7 @@ private: bool ProcessContentArgs(std::vector const& args, unsigned int &argIndex, bool prepend, bool system); - void PopulateTargetProperies(const std::string &scope, + bool PopulateTargetProperies(const std::string &scope, const std::vector &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 &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 &content, bool prepend, bool system); -- cgit v0.12 From 8ed59fc207fd028d5b2b1f8cb8a323291ef04ffc Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 13 Oct 2013 14:25:08 +0200 Subject: 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. --- Help/command/target_compile_features.rst | 30 ++++++++++ Help/manual/cmake-commands.7.rst | 1 + Help/release/dev/compile-language-features.rst | 4 ++ Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst | 3 + Source/CMakeLists.txt | 1 + Source/cmTargetCompileFeaturesCommand.cxx | 70 ++++++++++++++++++++++ Source/cmTargetCompileFeaturesCommand.h | 41 +++++++++++++ .../target_compile_features/CMakeLists.txt | 17 ++++++ .../target_compile_features/dummy.cpp | 5 ++ .../target_compile_features/lib_auto_type.cpp | 6 ++ .../target_compile_features/lib_auto_type.h | 8 +++ .../target_compile_features/lib_user.cpp | 7 +++ .../CMakeCommands/target_compile_features/main.cpp | 6 ++ Tests/CMakeLists.txt | 1 + Tests/RunCMake/CMakeLists.txt | 4 ++ ..._OriginDebug_target_compile_features-result.txt | 1 + ..._OriginDebug_target_compile_features-stderr.txt | 5 ++ ...ature_OriginDebug_target_compile_features.cmake | 4 ++ Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake | 1 + .../target_compile_features/CMakeLists.txt | 3 + .../target_compile_features/RunCMakeTest.cmake | 11 ++++ .../alias_target-result.txt | 1 + .../alias_target-stderr.txt | 4 ++ .../target_compile_features/alias_target.cmake | 4 ++ Tests/RunCMake/target_compile_features/empty.cpp | 7 +++ .../imported_target-result.txt | 1 + .../imported_target-stderr.txt | 4 ++ .../target_compile_features/imported_target.cmake | 3 + .../invalid_args-result.txt | 1 + .../invalid_args-stderr.txt | 4 ++ .../target_compile_features/invalid_args.cmake | 3 + .../invalid_args_on_interface-result.txt | 1 + .../invalid_args_on_interface-stderr.txt | 5 ++ .../invalid_args_on_interface.cmake | 3 + .../no_matching_cxx_feature-result.txt | 1 + .../no_matching_cxx_feature-stderr.txt | 8 +++ .../no_matching_cxx_feature.cmake | 26 ++++++++ .../target_compile_features/no_target-result.txt | 1 + .../target_compile_features/no_target-stderr.txt | 5 ++ .../target_compile_features/no_target.cmake | 2 + .../not_a_cxx_feature-result.txt | 1 + .../not_a_cxx_feature-stderr.txt | 5 ++ .../not_a_cxx_feature.cmake | 6 ++ .../not_enough_args-result.txt | 1 + .../not_enough_args-stderr.txt | 4 ++ .../target_compile_features/not_enough_args.cmake | 3 + .../utility_target-result.txt | 1 + .../utility_target-stderr.txt | 4 ++ .../target_compile_features/utility_target.cmake | 4 ++ 49 files changed, 342 insertions(+) create mode 100644 Help/command/target_compile_features.rst create mode 100644 Source/cmTargetCompileFeaturesCommand.cxx create mode 100644 Source/cmTargetCompileFeaturesCommand.h create mode 100644 Tests/CMakeCommands/target_compile_features/CMakeLists.txt create mode 100644 Tests/CMakeCommands/target_compile_features/dummy.cpp create mode 100644 Tests/CMakeCommands/target_compile_features/lib_auto_type.cpp create mode 100644 Tests/CMakeCommands/target_compile_features/lib_auto_type.h create mode 100644 Tests/CMakeCommands/target_compile_features/lib_user.cpp create mode 100644 Tests/CMakeCommands/target_compile_features/main.cpp create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features-result.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features-stderr.txt create mode 100644 Tests/RunCMake/CompileFeatures/NotAFeature_OriginDebug_target_compile_features.cmake create mode 100644 Tests/RunCMake/target_compile_features/CMakeLists.txt create mode 100644 Tests/RunCMake/target_compile_features/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/target_compile_features/alias_target-result.txt create mode 100644 Tests/RunCMake/target_compile_features/alias_target-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/alias_target.cmake create mode 100644 Tests/RunCMake/target_compile_features/empty.cpp create mode 100644 Tests/RunCMake/target_compile_features/imported_target-result.txt create mode 100644 Tests/RunCMake/target_compile_features/imported_target-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/imported_target.cmake create mode 100644 Tests/RunCMake/target_compile_features/invalid_args-result.txt create mode 100644 Tests/RunCMake/target_compile_features/invalid_args-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/invalid_args.cmake create mode 100644 Tests/RunCMake/target_compile_features/invalid_args_on_interface-result.txt create mode 100644 Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake create mode 100644 Tests/RunCMake/target_compile_features/no_matching_cxx_feature-result.txt create mode 100644 Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake create mode 100644 Tests/RunCMake/target_compile_features/no_target-result.txt create mode 100644 Tests/RunCMake/target_compile_features/no_target-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/no_target.cmake create mode 100644 Tests/RunCMake/target_compile_features/not_a_cxx_feature-result.txt create mode 100644 Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake create mode 100644 Tests/RunCMake/target_compile_features/not_enough_args-result.txt create mode 100644 Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/not_enough_args.cmake create mode 100644 Tests/RunCMake/target_compile_features/utility_target-result.txt create mode 100644 Tests/RunCMake/target_compile_features/utility_target-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/utility_target.cmake 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( [...]) + +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 ````. +``PUBLIC`` and ``INTERFACE`` items will populate the +:prop_tgt:`INTERFACE_COMPILE_FEATURES` property of ````. Repeated +calls for the same ```` append items. + +The named ```` 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 + + 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 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 &content) +{ + std::string defs; + std::string sep; + for(std::vector::const_iterator it = content.begin(); + it != content.end(); ++it) + { + defs += sep + *it; + sep = ";"; + } + return defs; +} + +//---------------------------------------------------------------------------- +bool cmTargetCompileFeaturesCommand +::HandleDirectContent(cmTarget *tgt, const std::vector &content, + bool, bool) +{ + for(std::vector::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 + + 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 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 &content, + bool prepend, bool system); + virtual std::string Join(const std::vector &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) -- cgit v0.12 From 9eaf3755987821080908a289cefbf546773071f9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 17 Dec 2013 19:23:40 +0100 Subject: Export: Populate INTERFACE_COMPILE_FEATURES property. --- Source/cmExportBuildFileGenerator.cxx | 3 +++ Source/cmExportInstallFileGenerator.cxx | 4 ++++ Tests/ExportImport/Export/Interface/CMakeLists.txt | 5 ++++- Tests/ExportImport/Import/CMakeLists.txt | 1 + Tests/ExportImport/Import/Interface/CMakeLists.txt | 17 +++++++++++++++++ 5 files changed, 29 insertions(+), 1 deletion(-) 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..189f7a2 100644 --- a/Tests/ExportImport/Import/CMakeLists.txt +++ b/Tests/ExportImport/Import/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required (VERSION 2.7.20090711) +cmake_policy(SET CMP0025 NEW) 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) -- cgit v0.12