From f97bf4370c283432c4e14fe54ed481d5d9b7ceef Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 2 Apr 2014 15:34:16 +0200 Subject: [PATCH] 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 ++ .../CompileFeatures/NotAFeature.cmake | 3 +++ .../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 7466d444e..d49bb6829 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 000000000..b36315fed --- /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 3ee8639ef..7acad5285 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 64163de17..0b3c43e22 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 aaa24c743..fc58f1e77 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 000000000..471b560c2 --- /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 000000000..7dbf04f67 --- /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 000000000..3a8e0fcea --- /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 851de429d..dd769ac06 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 000000000..3482e6baf --- /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 000000000..d00491fd7 --- /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 000000000..ff60e50a5 --- /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 000000000..35246c8bd --- /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 000000000..3c999e67d --- /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 000000000..bfbbddeb9 --- /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 92b24e2fc..954a2fe58 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}"