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)
This commit is contained in:
Stephen Kelly 2014-05-30 15:03:45 +02:00
parent 8afbb346c6
commit 60a981ea8e
16 changed files with 52 additions and 31 deletions

View File

@ -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

View File

@ -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
=========================

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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"))
{

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)