瀏覽代碼

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/[email protected]/msg10116.html
 (Compiler feature extensions by default, 29 May 2014)
Stephen Kelly 11 年之前
父節點
當前提交
60a981ea8e

+ 1 - 1
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
 feature is not listed in the :variable:`CMAKE_C_COMPILE_FEATURES` variable
 or :variable:`CMAKE_CXX_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
 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.
 automatically.
 
 
 The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
 The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to

+ 11 - 14
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,
 In processing the requirement for the ``cxx_constexpr`` feature,
 :manual:`cmake(1)` will ensure that the in-use C++ compiler is capable
 :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
 to the compile lines of C++ files in the ``mylib`` target.  A
 ``FATAL_ERROR`` is issued if the compiler is not capable of the
 ``FATAL_ERROR`` is issued if the compiler is not capable of the
 feature.
 feature.
@@ -59,8 +59,8 @@ for each target.
 
 
 Such compile flags are added even if the compiler supports the
 Such compile flags are added even if the compiler supports the
 particular feature without the flag. For example, the GNU compiler
 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.
 is specified as a requirement.
 
 
 In the above example, ``mylib`` requires ``cxx_constexpr`` when it
 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
   # cxx_constexpr is a usage-requirement
   target_compile_features(mylib PUBLIC cxx_constexpr)
   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)
   add_executable(myexe main.cpp)
   target_link_libraries(myexe mylib)
   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
 implementation.  See :manual:`cmake-buildsystem(7)` for more on
 transitive behavior of build properties and usage requirements.
 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
 Optional Compile Features
 =========================
 =========================

+ 2 - 1
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
 This property specifies whether compiler specific extensions should be
 used.  For some compilers, this results in adding a flag such
 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
 See the :manual:`cmake-compile-features(7)` manual for information on
 compile features.
 compile features.

+ 3 - 3
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
 This property specifies the C++ standard whose features are requested
 to build this target.  For some compilers, this results in adding a
 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``.
 Supported values are ``98`` and ``11``.
 
 
@@ -17,9 +17,9 @@ means that using:
 
 
   set_property(TARGET tgt PROPERTY CXX_STANDARD 11)
   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
 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.
 with the :prop_tgt:`CXX_STANDARD_REQUIRED` target property.
 
 
 See the :manual:`cmake-compile-features(7)` manual for information on
 See the :manual:`cmake-compile-features(7)` manual for information on

+ 2 - 1
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
 This property specifies whether compiler specific extensions should be
 used.  For some compilers, this results in adding a flag such
 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
 See the :manual:`cmake-compile-features(7)` manual for information on
 compile features.
 compile features.

+ 3 - 3
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
 This property specifies the C standard whose features are requested
 to build this target.  For some compilers, this results in adding a
 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``.
 Supported values are ``90``, ``99`` and ``11``.
 
 
@@ -17,9 +17,9 @@ means that using:
 
 
   set_property(TARGET tgt PROPERTY C_STANDARD 11)
   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
 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.
 be controlled with the :prop_tgt:`C_STANDARD_REQUIRED` target property.
 
 
 See the :manual:`cmake-compile-features(7)` manual for information on
 See the :manual:`cmake-compile-features(7)` manual for information on

+ 10 - 2
Source/cmLocalGenerator.cxx

@@ -2195,8 +2195,16 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
     return;
     return;
     }
     }
   std::string extProp = lang + "_EXTENSIONS";
   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"))
   if (target->GetPropertyAsBool(lang + "_STANDARD_REQUIRED"))
     {
     {

+ 16 - 2
Tests/CxxDialect/CMakeLists.txt

@@ -4,11 +4,25 @@ project(CxxDialect)
 
 
 add_executable(use_typeof use_typeof.cxx)
 add_executable(use_typeof use_typeof.cxx)
 set_property(TARGET use_typeof PROPERTY CXX_STANDARD 98)
 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)
 add_executable(use_constexpr use_constexpr.cxx)
 set_property(TARGET use_constexpr PROPERTY CXX_STANDARD 11)
 set_property(TARGET use_constexpr PROPERTY CXX_STANDARD 11)
 
 
 add_executable(CxxDialect use_constexpr_and_typeof.cxx)
 add_executable(CxxDialect use_constexpr_and_typeof.cxx)
 set_property(TARGET CxxDialect PROPERTY CXX_STANDARD 11)
 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()

+ 1 - 0
Tests/RunCMake/CompileFeatures/RequireCXX11.cmake

@@ -1,4 +1,5 @@
 
 
 add_library(foo empty.cpp)
 add_library(foo empty.cpp)
 set_property(TARGET foo PROPERTY CXX_STANDARD 11)
 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)
 set_property(TARGET foo PROPERTY CXX_STANDARD_REQUIRED TRUE)

+ 0 - 1
Tests/RunCMake/CompileFeatures/RequireCXX11Ext.cmake

@@ -1,5 +1,4 @@
 
 
 add_library(foo empty.cpp)
 add_library(foo empty.cpp)
 set_property(TARGET foo PROPERTY CXX_STANDARD 11)
 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)
 set_property(TARGET foo PROPERTY CXX_STANDARD_REQUIRED TRUE)

+ 0 - 1
Tests/RunCMake/CompileFeatures/RequireCXX11ExtVariable.cmake

@@ -2,4 +2,3 @@
 set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
 set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
 add_library(foo empty.cpp)
 add_library(foo empty.cpp)
 set_property(TARGET foo PROPERTY CXX_STANDARD 11)
 set_property(TARGET foo PROPERTY CXX_STANDARD 11)
-set_property(TARGET foo PROPERTY CXX_EXTENSIONS TRUE)

+ 1 - 0
Tests/RunCMake/CompileFeatures/RequireCXX11Variable.cmake

@@ -2,3 +2,4 @@
 set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
 set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
 add_library(foo empty.cpp)
 add_library(foo empty.cpp)
 set_property(TARGET foo PROPERTY CXX_STANDARD 11)
 set_property(TARGET foo PROPERTY CXX_STANDARD 11)
+set_property(TARGET foo PROPERTY CXX_EXTENSIONS FALSE)

+ 1 - 0
Tests/RunCMake/CompileFeatures/RequireCXX98.cmake

@@ -2,3 +2,4 @@
 add_library(foo empty.cpp)
 add_library(foo empty.cpp)
 set_property(TARGET foo PROPERTY CXX_STANDARD 98)
 set_property(TARGET foo PROPERTY CXX_STANDARD 98)
 set_property(TARGET foo PROPERTY CXX_STANDARD_REQUIRED TRUE)
 set_property(TARGET foo PROPERTY CXX_STANDARD_REQUIRED TRUE)
+set_property(TARGET foo PROPERTY CXX_EXTENSIONS FALSE)

+ 0 - 1
Tests/RunCMake/CompileFeatures/RequireCXX98Ext.cmake

@@ -1,5 +1,4 @@
 
 
 add_library(foo empty.cpp)
 add_library(foo empty.cpp)
 set_property(TARGET foo PROPERTY CXX_STANDARD 98)
 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)
 set_property(TARGET foo PROPERTY CXX_STANDARD_REQUIRED TRUE)

+ 0 - 1
Tests/RunCMake/CompileFeatures/RequireCXX98ExtVariable.cmake

@@ -2,4 +2,3 @@
 set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
 set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
 add_library(foo empty.cpp)
 add_library(foo empty.cpp)
 set_property(TARGET foo PROPERTY CXX_STANDARD 98)
 set_property(TARGET foo PROPERTY CXX_STANDARD 98)
-set_property(TARGET foo PROPERTY CXX_EXTENSIONS TRUE)

+ 1 - 0
Tests/RunCMake/CompileFeatures/RequireCXX98Variable.cmake

@@ -2,3 +2,4 @@
 set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
 set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
 add_library(foo empty.cpp)
 add_library(foo empty.cpp)
 set_property(TARGET foo PROPERTY CXX_STANDARD 98)
 set_property(TARGET foo PROPERTY CXX_STANDARD 98)
+set_property(TARGET foo PROPERTY CXX_EXTENSIONS FALSE)