Help: Add a manual for compiler feature control.

Link to it from the documentation of related properties, variables
and commands.

Extend the cmake-developer(7) documentation with notes on
extending feature support for compilers.
This commit is contained in:
Stephen Kelly 2014-03-18 23:50:18 +01:00 committed by Brad King
parent b4d33f6484
commit ca5d990f02
24 changed files with 403 additions and 6 deletions

View File

@ -28,4 +28,5 @@ an ``IMPORTED`` target.
Arguments to ``target_compile_features`` may use "generator expressions"
with the syntax ``$<...>``.
See the :manual:`cmake-generator-expressions(7)` manual for available
expressions.
expressions. See the :manual:`cmake-compile-features(7)` manual for
information on compile features.

View File

@ -27,6 +27,7 @@ Reference Manuals
/manual/cmake-buildsystem.7
/manual/cmake-commands.7
/manual/cmake-compile-features.7
/manual/cmake-developer.7
/manual/cmake-generator-expressions.7
/manual/cmake-generators.7

View File

@ -0,0 +1,297 @@
.. cmake-manual-description: CMake Compile Features Reference
cmake-compile-features(7)
*************************
.. only:: html or latex
.. contents::
Introduction
============
Project source code may depend on, or be conditional on, the availability
of certain features of the compiler. There are three use-cases which arise:
`Compile Feature Requirements`_, `Optional Compile Features`_
and `Conditional Compilation Options`_.
While features are typically specified in programming language standards,
CMake provides a primary user interface based on granular handling of
the features, not the language standard that introduced the feature.
The :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and
:prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties contain all the
features known to CMake, regardless of compiler support for the feature.
The :variable:`CMAKE_C_COMPILE_FEATURES` and
:variable:`CMAKE_CXX_COMPILE_FEATURES` variables contain all features
CMake knows are known to the compiler, regardless of language standard
or compile flags needed to use them.
Features known to CMake are named mostly following the same convention
as the Clang feature test macros. The are some execptions, such as
CMake using ``cxx_final`` and ``cxx_override`` instead of the single
``cxx_override_control`` used by Clang.
Compile Feature Requirements
============================
Compile feature requirements may be specified with the
:command:`target_compile_features` command. For example, if a target must
be compiled with compiler support for the
:prop_gbl:`cxx_constexpr <CMAKE_CXX_KNOWN_FEATURES>` feature:
.. code-block:: cmake
add_library(mylib requires_constexpr.cpp)
target_compile_features(mylib PRIVATE cxx_constexpr)
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``
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.
The exact compile flags and language standard are deliberately not part
of the user interface for this use-case. CMake will compute the
appropriate compile flags to use by considering the features specified
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``
is specified as a requirement.
In the above example, ``mylib`` requires ``cxx_constexpr`` when it
is built itself, but consumers of ``mylib`` are not required to use a
compiler which supports ``cxx_constexpr``. If the interface of
``mylib`` does require the ``cxx_constexpr`` feature (or any other
known feature), that may be specified with the ``PUBLIC`` or
``INTERFACE`` signatures of :command:`target_compile_features`:
.. code-block:: cmake
add_library(mylib requires_constexpr.cpp)
# 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.
add_executable(myexe main.cpp)
target_link_libraries(myexe mylib)
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.
Optional Compile Features
=========================
Compile features may be preferred if available, without creating a hard
requirement. For example, a library may provides alternative
implementations depending on whether the ``cxx_variadic_templates``
feature is available:
.. code-block:: c++
#if Foo_COMPILER_CXX_VARIADIC_TEMPLATES
template<int I, int... Is>
struct Interface;
template<int I>
struct Interface<I>
{
static int accumulate()
{
return I;
}
};
template<int I, int... Is>
struct Interface
{
static int accumulate()
{
return I + Interface<Is...>::accumulate();
}
};
#else
template<int I1, int I2 = 0, int I3 = 0, int I4 = 0>
struct Interface
{
static int accumulate() { return I1 + I2 + I3 + I4; }
};
#endif
Such an interface depends on using the correct preprocessor defines for the
compiler features. CMake can generate a header file containing such
defines using the :module:`WriteCompilerDetectionHeader` module. The
module contains the ``write_compiler_detection_header`` function which
accepts parameters to control the content of the generated header file:
.. code-block:: cmake
write_compiler_detection_header(
FILE "${CMAKE_CURRENT_BINARY_DIR}/foo_compiler_detection.h"
PREFIX Foo
COMPILERS GNU
FEATURES
cxx_variadic_templates
)
Such a header file may be used internally in the source code of a project,
and it may be installed and used in the interface of library code.
For each feature listed in ``FEATURES``, a preprocessor definition
is created in the header file, and defined to either ``1`` or ``0``.
Additionally, some features call for additional defines, such as the
``cxx_final`` and ``cxx_override`` features. Rather than being used in
``#ifdef`` code, the ``final`` keyword is abstracted by a symbol
which is defined to either ``final``, a compiler-specific equivalent, or
to empty. That way, C++ code can be written to unconditionally use the
symbol, and compiler support determines what it is expanded to:
.. code-block:: c++
struct Interface {
virtual void Execute() = 0;
};
struct Concrete Foo_CXX_FINAL {
void Execute() Foo_CXX_OVERRIDE;
};
In this case, ``Foo_CXX_FINAL`` will expand to ``final`` if the
compiler supports the keyword, or to empty otherwise.
In this use-case, the CMake code will wish to enable a particular language
standard if available from the compiler. The :prop_tgt:`CXX_STANDARD`
target property variable may be set to the desired language standard
for a particular target, and the :variable:`CMAKE_CXX_STANDARD` may be
set to influence all following targets:
.. code-block:: cmake
write_compiler_detection_header(
FILE "${CMAKE_CURRENT_BINARY_DIR}/foo_compiler_detection.h"
PREFIX Foo
COMPILERS GNU
FEATURES
cxx_final cxx_override
)
# Includes foo_compiler_detection.h and uses the Foo_DECL_CXX_FINAL symbol
# which will expand to 'final' if the compiler supports the requested
# CXX_STANDARD.
add_library(foo foo.cpp)
set_property(TARGET foo PROPERTY CXX_STANDARD 11)
# Includes foo_compiler_detection.h and uses the Foo_DECL_CXX_FINAL symbol
# which will expand to 'final' if the compiler supports the feature,
# even though CXX_STANDARD is not set explicitly. The requirement of
# cxx_constexpr causes CMake to set CXX_STANDARD internally, which
# affects the compile flags.
add_library(foo_impl foo_impl.cpp)
target_compile_features(foo_impl PRIVATE cxx_constexpr)
The ``write_compiler_detection_header`` function also creates compatibility
code for other features which have standard equivalents. For example, the
``cxx_static_assert`` feature is emulated with a template and abstracted
via the ``<PREFIX>_STATIC_ASSERT`` and ``<PREFIX>_STATIC_ASSERT_MSG``
function-macros.
Conditional Compilation Options
===============================
Libraries may provide entirely different header files depending on
requested compiler features.
For example, a header at ``with_variadics/interface.h`` may contain:
.. code-block:: c++
template<int I, int... Is>
struct Interface;
template<int I>
struct Interface<I>
{
static int accumulate()
{
return I;
}
};
template<int I, int... Is>
struct Interface
{
static int accumulate()
{
return I + Interface<Is...>::accumulate();
}
};
while a header at ``no_variadics/interface.h`` may contain:
.. code-block:: c++
template<int I1, int I2 = 0, int I3 = 0, int I4 = 0>
struct Interface
{
static int accumulate() { return I1 + I2 + I3 + I4; }
};
It would be possible to write a abstraction ``interface.h`` header
containing something like:
.. code-block:: c++
#include "foo_compiler_detection.h"
#if Foo_COMPILER_CXX_VARIADIC_TEMPLATES
#include "with_variadics/interface.h"
#else
#include "no_variadics/interface.h"
#endif
However this could be unmaintainable if there are many files to
abstract. What is needed is to use alternative include directories
depending on the compiler capabilities.
CMake provides a ``COMPILE_FEATURES``
:manual:`generator expression <cmake-generator-expressions(7)>` to implement
such conditions. This may be used with the build-property commands such as
:command:`target_include_directories` and :command:`target_link_libraries`
to set the appropriate :manual:`buildsystem <cmake-buildsystem(7)>`
properties:
.. code-block:: cmake
add_library(foo INTERFACE)
target_link_libraries(foo
INTERFACE
"$<$<COMPILE_FEATURES:cxx_variadic_templates>:${CMAKE_CURRENT_SOURCE_DIR}/with_variadics>"
"$<$<NOT:$<COMPILE_FEATURES:cxx_variadic_templates>>:${CMAKE_CURRENT_SOURCE_DIR}/no_variadics>")
Consuming code then simply links to the ``foo`` target as usual and uses
the feature-appropriate include directory
.. code-block:: cmake
add_executable(consumer_with consumer_with.cpp)
target_link_libraries(consumer_with foo)
set_property(TARGET consumer_with CXX_STANDARD 11)
add_executable(consumer_no consumer_no.cpp)
target_link_libraries(consumer_no foo)

View File

@ -197,6 +197,51 @@ Templates
Some template code is permitted, but with some limitations. Member templates
may not be used, and template friends may not be used.
Adding Compile Features
=======================
CMake reports an error if a compiler whose features are known does not report
support for a particular requested feature. A compiler is considered to have
known features if it reports support for at least one feature.
When adding a new compile feature to CMake, it is therefore necessary to list
support for the feature for all CompilerIds which already have one or more
feature supported, if the new feature is available for any version of the
compiler.
When adding the first supported feature to a particular CompilerId, it is
necessary to list support for all features known to cmake (See
:variable:`CMAKE_C_COMPILE_FEATURES` and
:variable:`CMAKE_CXX_COMPILE_FEATURES` as appropriate), where available for
the compiler.
It is sensible to record the features for the most recent version of a
particular CompilerId first, and then work backwards. It is sensible to
try to create a continuous range of versions of feature releases of the
compiler. Gaps in the range indicate incorrect features recorded for
intermediate releases.
Generally, features are made available for a particular version if the
compiler vendor documents availability of the feature with that
version. Note that sometimes partially implemented features appear to
be functional in previous releases (such as ``cxx_constexpr`` in GNU 4.6,
though availability is documented in GNU 4.7), and sometimes compiler vendors
document availability of features, though supporting infrastructure is
not available (such as ``__has_feature(cxx_generic_lambdas)`` indicating
non-availability in Clang 3.4, though it is documented as available, and
fixed in Clang 3.5). Similar cases for other compilers and versions
need to be investigated when extending CMake to support them.
When a vendor releases a new version of a known compiler which supports
a previously unsupported feature, and there are already known features for
that compiler, the feature should be listed as supported in CMake for
that version of the compiler as soon as reasonably possible.
Standard-specific/compiler-specific variables such
``CMAKE_CXX98_COMPILE_FEATURES`` are deliberately not documented. They
only exist for the compiler-specific implementation of adding the ``-std``
compile flag for compilers which need that.
Help
====

View File

@ -88,7 +88,9 @@ otherwise expands to nothing.
target, and ``0`` otherwise. If this expression is used while evaluating
the link implementation of a target and if any dependency transitively
increases the required :prop_tgt:`C_STANDARD` or :prop_tgt:`CXX_STANDARD`
for the 'head' target, an error is reported.
for the 'head' target, an error is reported. See the
:manual:`cmake-compile-features(7)` manual for information on
compile features.
Informational Expressions
=========================

View File

@ -8,7 +8,9 @@ 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 listed here may be used with the :command:`target_compile_features`
command.
command. See the :manual:`cmake-compile-features(7)` manual for information on
compile features.
The features known to this version of CMake are:

View File

@ -8,7 +8,8 @@ C compiler. If the feature is available with the C compiler, it will
be listed in the :variable:`CMAKE_C_COMPILE_FEATURES` variable.
The features listed here may be used with the :command:`target_compile_features`
command.
command. See the :manual:`cmake-compile-features(7)` manual for information on
compile features.
The features known to this version of CMake are:

View File

@ -8,4 +8,5 @@ in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable.
Contents of ``COMPILE_FEATURES`` may use "generator expressions" with the
syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for
available expressions.
available expressions. See the :manual:`cmake-compile-features(7)` manual
for information on compile features.

View File

@ -7,6 +7,9 @@ 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.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.
This property is initialized by the value of
the :variable:`CMAKE_CXX_EXTENSIONS` variable if it is set when a target
is created.

View File

@ -22,6 +22,9 @@ 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
with the :prop_tgt:`CXX_STANDARD_REQUIRED` target property.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.
This property is initialized by the value of
the :variable:`CMAKE_CXX_STANDARD` variable if it is set when a target
is created.

View File

@ -9,6 +9,9 @@ property is ``OFF`` or unset, the :prop_tgt:`CXX_STANDARD` target property is
treated as optional and may "decay" to a previous standard if the requested is
not available.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.
This property is initialized by the value of
the :variable:`CMAKE_CXX_STANDARD_REQUIRED` variable if it is set when a
target is created.

View File

@ -7,6 +7,9 @@ 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.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.
This property is initialized by the value of
the :variable:`CMAKE_C_EXTENSIONS` variable if it is set when a target
is created.

View File

@ -22,6 +22,9 @@ 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
be controlled with the :prop_tgt:`C_STANDARD_REQUIRED` target property.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.
This property is initialized by the value of
the :variable:`CMAKE_C_STANDARD` variable if it is set when a target
is created.

View File

@ -9,6 +9,9 @@ property is ``OFF`` or unset, the :prop_tgt:`C_STANDARD` target property is
treated as optional and may "decay" to a previous standard if the requested is
not available.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.
This property is initialized by the value of
the :variable:`CMAKE_C_STANDARD_REQUIRED` variable if it is set when a
target is created.

View File

@ -11,4 +11,6 @@ to require the features specified in the interface of ``foo``.
Contents of ``INTERFACE_COMPILE_FEATURES`` may use "generator expressions"
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions.
manual for available expressions. See the
:manual:`cmake-compile-features(7)` manual for information on compile
features.

View File

@ -6,3 +6,6 @@ List of features known to the C++ compiler
These features are known to be available for use with the C++ compiler. This
list is a subset of the features listed in the :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES`
global property.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.

View File

@ -6,3 +6,6 @@ Default value for ``CXX_EXTENSIONS`` property of targets.
This variable is used to initialize the :prop_tgt:`CXX_EXTENSIONS`
property on all targets. See that target property for additional
information.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.

View File

@ -6,3 +6,6 @@ Default value for ``CXX_STANDARD`` property of targets.
This variable is used to initialize the :prop_tgt:`CXX_STANDARD`
property on all targets. See that target property for additional
information.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.

View File

@ -6,3 +6,6 @@ Default value for ``CXX_STANDARD_REQUIRED`` property of targets.
This variable is used to initialize the :prop_tgt:`CXX_STANDARD_REQUIRED`
property on all targets. See that target property for additional
information.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.

View File

@ -6,3 +6,6 @@ List of features known to the C compiler
These features are known to be available for use with the C compiler. This
list is a subset of the features listed in the :prop_gbl:`CMAKE_C_KNOWN_FEATURES`
global property.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.

View File

@ -6,3 +6,6 @@ Default value for ``C_EXTENSIONS`` property of targets.
This variable is used to initialize the :prop_tgt:`C_EXTENSIONS`
property on all targets. See that target property for additional
information.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.

View File

@ -6,3 +6,6 @@ Default value for ``C_STANDARD`` property of targets.
This variable is used to initialize the :prop_tgt:`C_STANDARD`
property on all targets. See that target property for additional
information.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.

View File

@ -6,3 +6,6 @@ Default value for ``C_STANDARD_REQUIRED`` property of targets.
This variable is used to initialize the :prop_tgt:`C_STANDARD_REQUIRED`
property on all targets. See that target property for additional
information.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.

View File

@ -46,6 +46,9 @@
# :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and
# :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties.
#
# See the :manual:`cmake-compile-features(7)` manual for information on
# compile features.
#
# Feature Test Macros
# ===================
#