Commit 60a981ea authored by Stephen Kelly's avatar Stephen Kelly

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)
parent 8afbb346
...@@ -11,7 +11,7 @@ Specify compiler features required when compiling a given target. If the ...@@ -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
......
...@@ -47,7 +47,7 @@ be compiled with compiler support for the ...@@ -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. ...@@ -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 supports variadic templates (with a warning) even if ``-std=gnu++98`` is
used. CMake adds the ``-std=c++11`` flag if ``cxx_variadic_templates`` 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 ...@@ -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 ...@@ -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 Because the :prop_tgt:`CXX_EXTENSIONS` target property is ``ON`` by default,
cross-platform bugs in user code. For example, the GNU compiler uses the CMake uses extended variants of language dialects by default, such as
``gnu++98`` language by default as of GCC version 4.8. User code may ``-std=gnu++11`` instead of ``-std=c++11``. That target property may be
be relying on that by expecting the ``typeof`` GNU extension to work. set to ``OFF`` to use the non-extended variant of the dialect flag. Note
However, if the :command:`target_compile_features` command is used to that because most compilers enable extensions by default, this could
specify the requirement for ``cxx_constexpr``, a ``-std=c++11`` flag may expose cross-platform bugs in user code or in the headers of third-party
be added, and the ``typeof`` extension would no longer be available. The dependencies.
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.
Optional Compile Features Optional Compile Features
========================= =========================
......
...@@ -5,7 +5,8 @@ Boolean specifying whether compiler specific extensions are requested. ...@@ -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.
......
...@@ -5,7 +5,7 @@ The C++ standard whose features are requested to build this target. ...@@ -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: ...@@ -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
......
...@@ -5,7 +5,8 @@ Boolean specifying whether compiler specific extensions are requested. ...@@ -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.
......
...@@ -5,7 +5,7 @@ The C standard whose features are requested to build this target. ...@@ -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: ...@@ -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
......
...@@ -2195,8 +2195,16 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target, ...@@ -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 = "EXTENSION";
std::string type = ext ? "EXTENSION" : "STANDARD"; 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"))
{ {
......
...@@ -4,11 +4,25 @@ project(CxxDialect) ...@@ -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()
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)
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)
...@@ -2,4 +2,3 @@ ...@@ -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)
...@@ -2,3 +2,4 @@ ...@@ -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)
...@@ -2,3 +2,4 @@ ...@@ -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)
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)
...@@ -2,4 +2,3 @@ ...@@ -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)
...@@ -2,3 +2,4 @@ ...@@ -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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment