From 60a981ea8eda7a5af679ca3b2e4d54bc50ad61b3 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 30 May 2014 15:03:45 +0200 Subject: Features: Enable compiler extensions by default. Compilers enable their extensions by default, and disabling them implicitly can lead to results which are surprising or non-obvious to debug. http://public.kitware.com/pipermail/cmake-developers/2014-May/010575.html http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/10214 https://www.mail-archive.com/cmake-developers@cmake.org/msg10116.html (Compiler feature extensions by default, 29 May 2014) --- Help/command/target_compile_features.rst | 2 +- Help/manual/cmake-compile-features.7.rst | 25 ++++++++++------------ Help/prop_tgt/CXX_EXTENSIONS.rst | 3 ++- Help/prop_tgt/CXX_STANDARD.rst | 6 +++--- Help/prop_tgt/C_EXTENSIONS.rst | 3 ++- Help/prop_tgt/C_STANDARD.rst | 6 +++--- Source/cmLocalGenerator.cxx | 12 +++++++++-- Tests/CxxDialect/CMakeLists.txt | 18 ++++++++++++++-- Tests/RunCMake/CompileFeatures/RequireCXX11.cmake | 1 + .../RunCMake/CompileFeatures/RequireCXX11Ext.cmake | 1 - .../CompileFeatures/RequireCXX11ExtVariable.cmake | 1 - .../CompileFeatures/RequireCXX11Variable.cmake | 1 + Tests/RunCMake/CompileFeatures/RequireCXX98.cmake | 1 + .../RunCMake/CompileFeatures/RequireCXX98Ext.cmake | 1 - .../CompileFeatures/RequireCXX98ExtVariable.cmake | 1 - .../CompileFeatures/RequireCXX98Variable.cmake | 1 + 16 files changed, 52 insertions(+), 31 deletions(-) diff --git a/Help/command/target_compile_features.rst b/Help/command/target_compile_features.rst index a6503db..29a8b41 100644 --- a/Help/command/target_compile_features.rst +++ b/Help/command/target_compile_features.rst @@ -11,7 +11,7 @@ Specify compiler features required when compiling a given target. If the feature is not listed in the :variable:`CMAKE_C_COMPILE_FEATURES` variable or :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 +an additional compiler flag, such as ``-std=gnu++11``, the flag will be added automatically. The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index c014846..d4bbecc 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -47,7 +47,7 @@ be compiled with compiler support for the In processing the requirement for the ``cxx_constexpr`` feature, :manual:`cmake(1)` will ensure that the in-use C++ compiler is capable -of the feature, and will add any necessary flags such as ``-std=c++11`` +of the feature, and will add any necessary flags such as ``-std=gnu++11`` to the compile lines of C++ files in the ``mylib`` target. A ``FATAL_ERROR`` is issued if the compiler is not capable of the feature. @@ -59,8 +59,8 @@ for each target. Such compile flags are added even if the compiler supports the particular feature without the flag. For example, the GNU compiler -supports variadic templates (with a warning) even if ``-std=c++98`` is -used. CMake adds the ``-std=c++11`` flag if ``cxx_variadic_templates`` +supports variadic templates (with a warning) even if ``-std=gnu++98`` is +used. CMake adds the ``-std=gnu++11`` flag if ``cxx_variadic_templates`` is specified as a requirement. In the above example, ``mylib`` requires ``cxx_constexpr`` when it @@ -76,7 +76,7 @@ known feature), that may be specified with the ``PUBLIC`` or # cxx_constexpr is a usage-requirement target_compile_features(mylib PUBLIC cxx_constexpr) - # main.cpp will be compiled with -std=c++11 on GNU for cxx_constexpr. + # main.cpp will be compiled with -std=gnu++11 on GNU for cxx_constexpr. add_executable(myexe main.cpp) target_link_libraries(myexe mylib) @@ -84,16 +84,13 @@ Feature requirements are evaluated transitively by consuming the link implementation. See :manual:`cmake-buildsystem(7)` for more on transitive behavior of build properties and usage requirements. -Note that new use of compile feature requirements may expose -cross-platform bugs in user code. For example, the GNU compiler uses the -``gnu++98`` language by default as of GCC version 4.8. User code may -be relying on that by expecting the ``typeof`` GNU extension to work. -However, if the :command:`target_compile_features` command is used to -specify the requirement for ``cxx_constexpr``, a ``-std=c++11`` flag may -be added, and the ``typeof`` extension would no longer be available. The -solution is to specify that compiler extensions are relied upon by setting -the :prop_tgt:`CXX_EXTENSIONS` target property to ``ON`` when starting to -use the :command:`target_compile_features` command. +Because the :prop_tgt:`CXX_EXTENSIONS` target property is ``ON`` by default, +CMake uses extended variants of language dialects by default, such as +``-std=gnu++11`` instead of ``-std=c++11``. That target property may be +set to ``OFF`` to use the non-extended variant of the dialect flag. Note +that because most compilers enable extensions by default, this could +expose cross-platform bugs in user code or in the headers of third-party +dependencies. Optional Compile Features ========================= diff --git a/Help/prop_tgt/CXX_EXTENSIONS.rst b/Help/prop_tgt/CXX_EXTENSIONS.rst index d7f87a4..67c5cb0 100644 --- a/Help/prop_tgt/CXX_EXTENSIONS.rst +++ b/Help/prop_tgt/CXX_EXTENSIONS.rst @@ -5,7 +5,8 @@ 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. +as ``-std=gnu++11`` instead of ``-std=c++11`` to the compile line. This +property is ``ON`` by default. See the :manual:`cmake-compile-features(7)` manual for information on compile features. diff --git a/Help/prop_tgt/CXX_STANDARD.rst b/Help/prop_tgt/CXX_STANDARD.rst index 8f299bb..b50cdf9 100644 --- a/Help/prop_tgt/CXX_STANDARD.rst +++ b/Help/prop_tgt/CXX_STANDARD.rst @@ -5,7 +5,7 @@ The C++ standard whose features are requested to build this target. This property specifies the C++ standard whose features are requested to build this target. For some compilers, this results in adding a -flag such as ``-std=c++11`` to the compile line. +flag such as ``-std=gnu++11`` to the compile line. Supported values are ``98`` and ``11``. @@ -17,9 +17,9 @@ means that using: set_property(TARGET tgt PROPERTY CXX_STANDARD 11) -with a compiler which does not support ``-std=c++11`` or an equivalent +with a compiler which does not support ``-std=gnu++11`` or an equivalent flag will not result in an error or warning, but will instead add the -``-std=c++98`` flag if supported. This "decay" behavior may be controlled +``-std=gnu++98`` flag if supported. This "decay" behavior may be controlled with the :prop_tgt:`CXX_STANDARD_REQUIRED` target property. See the :manual:`cmake-compile-features(7)` manual for information on diff --git a/Help/prop_tgt/C_EXTENSIONS.rst b/Help/prop_tgt/C_EXTENSIONS.rst index 0772ecc..dc48cc6 100644 --- a/Help/prop_tgt/C_EXTENSIONS.rst +++ b/Help/prop_tgt/C_EXTENSIONS.rst @@ -5,7 +5,8 @@ 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=gnu11`` instead of ``-std=c11`` to the compile line. +as ``-std=gnu11`` instead of ``-std=c11`` to the compile line. This +property is ``ON`` by default. See the :manual:`cmake-compile-features(7)` manual for information on compile features. diff --git a/Help/prop_tgt/C_STANDARD.rst b/Help/prop_tgt/C_STANDARD.rst index a0c939a..88ca926 100644 --- a/Help/prop_tgt/C_STANDARD.rst +++ b/Help/prop_tgt/C_STANDARD.rst @@ -5,7 +5,7 @@ The C standard whose features are requested to build this target. This property specifies the C standard whose features are requested to build this target. For some compilers, this results in adding a -flag such as ``-std=c11`` to the compile line. +flag such as ``-std=gnu11`` to the compile line. Supported values are ``90``, ``99`` and ``11``. @@ -17,9 +17,9 @@ means that using: set_property(TARGET tgt PROPERTY C_STANDARD 11) -with a compiler which does not support ``-std=c11`` or an equivalent +with a compiler which does not support ``-std=gnu11`` or an equivalent flag will not result in an error or warning, but will instead add the -``-std=c99`` or ``-std=c90`` flag if supported. This "decay" behavior may +``-std=gnu99`` or ``-std=gnu90`` flag if supported. This "decay" behavior may be controlled with the :prop_tgt:`C_STANDARD_REQUIRED` target property. See the :manual:`cmake-compile-features(7)` manual for information on diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index f83981e..543d58d 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2195,8 +2195,16 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target, return; } std::string extProp = lang + "_EXTENSIONS"; - bool ext = target->GetPropertyAsBool(extProp); - std::string type = ext ? "EXTENSION" : "STANDARD"; + std::string type = "EXTENSION"; + bool ext = true; + if (const char* extPropValue = target->GetProperty(extProp)) + { + if (cmSystemTools::IsOff(extPropValue)) + { + ext = false; + type = "STANDARD"; + } + } if (target->GetPropertyAsBool(lang + "_STANDARD_REQUIRED")) { diff --git a/Tests/CxxDialect/CMakeLists.txt b/Tests/CxxDialect/CMakeLists.txt index 0eb6f8f..8c90339 100644 --- a/Tests/CxxDialect/CMakeLists.txt +++ b/Tests/CxxDialect/CMakeLists.txt @@ -4,11 +4,25 @@ 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) + +try_compile(typeof_no_extensions_works + "${CMAKE_CURRENT_BINARY_DIR}/use_typeof_test" + "${CMAKE_CURRENT_SOURCE_DIR}/use_typeof.cxx" + COMPILE_DEFINITIONS + CMAKE_FLAGS + "-DCMAKE_CXX_STANDARD=98" + "-DCMAKE_CXX_EXTENSIONS=FALSE" + OUTPUT_VARIABLE OUTPUT +) + +if (typeof_no_extensions_works) + message("Use of typeof extension with extensions disabled works, but is expected to fail: ${OUTPUT}") +else() + message("Use of typeof extension with extensions disabled fails, as expected") +endif() diff --git a/Tests/RunCMake/CompileFeatures/RequireCXX11.cmake b/Tests/RunCMake/CompileFeatures/RequireCXX11.cmake index 10b251a..f60504f 100644 --- a/Tests/RunCMake/CompileFeatures/RequireCXX11.cmake +++ b/Tests/RunCMake/CompileFeatures/RequireCXX11.cmake @@ -1,4 +1,5 @@ add_library(foo empty.cpp) set_property(TARGET foo PROPERTY CXX_STANDARD 11) +set_property(TARGET foo PROPERTY CXX_EXTENSIONS FALSE) set_property(TARGET foo PROPERTY CXX_STANDARD_REQUIRED TRUE) diff --git a/Tests/RunCMake/CompileFeatures/RequireCXX11Ext.cmake b/Tests/RunCMake/CompileFeatures/RequireCXX11Ext.cmake index 9e726c8..10b251a 100644 --- a/Tests/RunCMake/CompileFeatures/RequireCXX11Ext.cmake +++ b/Tests/RunCMake/CompileFeatures/RequireCXX11Ext.cmake @@ -1,5 +1,4 @@ add_library(foo empty.cpp) set_property(TARGET foo PROPERTY CXX_STANDARD 11) -set_property(TARGET foo PROPERTY CXX_EXTENSIONS TRUE) set_property(TARGET foo PROPERTY CXX_STANDARD_REQUIRED TRUE) diff --git a/Tests/RunCMake/CompileFeatures/RequireCXX11ExtVariable.cmake b/Tests/RunCMake/CompileFeatures/RequireCXX11ExtVariable.cmake index 8f6755f..29703db 100644 --- a/Tests/RunCMake/CompileFeatures/RequireCXX11ExtVariable.cmake +++ b/Tests/RunCMake/CompileFeatures/RequireCXX11ExtVariable.cmake @@ -2,4 +2,3 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE) add_library(foo empty.cpp) set_property(TARGET foo PROPERTY CXX_STANDARD 11) -set_property(TARGET foo PROPERTY CXX_EXTENSIONS TRUE) diff --git a/Tests/RunCMake/CompileFeatures/RequireCXX11Variable.cmake b/Tests/RunCMake/CompileFeatures/RequireCXX11Variable.cmake index 29703db..c480997 100644 --- a/Tests/RunCMake/CompileFeatures/RequireCXX11Variable.cmake +++ b/Tests/RunCMake/CompileFeatures/RequireCXX11Variable.cmake @@ -2,3 +2,4 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE) add_library(foo empty.cpp) set_property(TARGET foo PROPERTY CXX_STANDARD 11) +set_property(TARGET foo PROPERTY CXX_EXTENSIONS FALSE) diff --git a/Tests/RunCMake/CompileFeatures/RequireCXX98.cmake b/Tests/RunCMake/CompileFeatures/RequireCXX98.cmake index 4ea595e..fd9fb60 100644 --- a/Tests/RunCMake/CompileFeatures/RequireCXX98.cmake +++ b/Tests/RunCMake/CompileFeatures/RequireCXX98.cmake @@ -2,3 +2,4 @@ add_library(foo empty.cpp) set_property(TARGET foo PROPERTY CXX_STANDARD 98) set_property(TARGET foo PROPERTY CXX_STANDARD_REQUIRED TRUE) +set_property(TARGET foo PROPERTY CXX_EXTENSIONS FALSE) diff --git a/Tests/RunCMake/CompileFeatures/RequireCXX98Ext.cmake b/Tests/RunCMake/CompileFeatures/RequireCXX98Ext.cmake index fdf4cc7..4ea595e 100644 --- a/Tests/RunCMake/CompileFeatures/RequireCXX98Ext.cmake +++ b/Tests/RunCMake/CompileFeatures/RequireCXX98Ext.cmake @@ -1,5 +1,4 @@ add_library(foo empty.cpp) set_property(TARGET foo PROPERTY CXX_STANDARD 98) -set_property(TARGET foo PROPERTY CXX_EXTENSIONS TRUE) set_property(TARGET foo PROPERTY CXX_STANDARD_REQUIRED TRUE) diff --git a/Tests/RunCMake/CompileFeatures/RequireCXX98ExtVariable.cmake b/Tests/RunCMake/CompileFeatures/RequireCXX98ExtVariable.cmake index a26a22d..0e3ef8d 100644 --- a/Tests/RunCMake/CompileFeatures/RequireCXX98ExtVariable.cmake +++ b/Tests/RunCMake/CompileFeatures/RequireCXX98ExtVariable.cmake @@ -2,4 +2,3 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE) add_library(foo empty.cpp) set_property(TARGET foo PROPERTY CXX_STANDARD 98) -set_property(TARGET foo PROPERTY CXX_EXTENSIONS TRUE) diff --git a/Tests/RunCMake/CompileFeatures/RequireCXX98Variable.cmake b/Tests/RunCMake/CompileFeatures/RequireCXX98Variable.cmake index 0e3ef8d..7562264 100644 --- a/Tests/RunCMake/CompileFeatures/RequireCXX98Variable.cmake +++ b/Tests/RunCMake/CompileFeatures/RequireCXX98Variable.cmake @@ -2,3 +2,4 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE) add_library(foo empty.cpp) set_property(TARGET foo PROPERTY CXX_STANDARD 98) +set_property(TARGET foo PROPERTY CXX_EXTENSIONS FALSE) -- cgit v0.12