Commit 1f4ec3f4 authored by Brad King's avatar Brad King
Browse files

Help: Do not recommend WCDH in cmake-compile-features(7)

Since commit da7ad799 (WriteCompilerDetectionHeader: Add policy to
remove module, 2020-12-04, v3.20.0-rc1~350^2), the WCDH module is
deprecated.  Update the `cmake-compile-features(7)` manual section that
previously recommended WCDH to make such detection the project's
responsibility instead.  Move the old content of the section over to the
WCDH module to preserve it.
parent 1cc63f2c
Pipeline #225519 waiting for manual action with stages
in 8 minutes and 34 seconds
......@@ -130,118 +130,21 @@ Optional Compile Features
=========================
Compile features may be preferred if available, without creating a hard
requirement. For example, a library may provide 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_FINAL {
void Execute() Foo_OVERRIDE;
};
In this case, ``Foo_FINAL`` will expand to ``final`` if the
compiler supports the keyword, or to empty otherwise.
In this use-case, the project code may wish to enable a particular language
standard if available from the compiler. The :prop_tgt:`CXX_STANDARD`
target property may be set to the desired language standard for a particular
target, and the :variable:`CMAKE_CXX_STANDARD` variable 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_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_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.
requirement. This can be achieved by *not* specifying features with
:command:`target_compile_features` and instead checking the compiler
capabilities with preprocessor conditions in project code.
In this use-case, the project may wish to establish a particular language
standard if available from the compiler, and use preprocessor conditions
to detect the features actually available. A language standard may be
established by `Requiring Language Standards`_ using
:command:`target_compile_features` with meta-features like ``cxx_std_11``,
or by setting the :prop_tgt:`CXX_STANDARD` target property or
:variable:`CMAKE_CXX_STANDARD` variable.
See also policy :policy:`CMP0120` and legacy documentation on
:ref:`Example Usage <WCDH Example Usage>` of the deprecated
:module:`WriteCompilerDetectionHeader` module.
Conditional Compilation Options
===============================
......@@ -289,8 +192,7 @@ containing something like:
.. code-block:: c++
#include "foo_compiler_detection.h"
#if Foo_COMPILER_CXX_VARIADIC_TEMPLATES
#ifdef HAVE_CXX_VARIADIC_TEMPLATES
#include "with_variadics/interface.h"
#else
#include "no_variadics/interface.h"
......
......@@ -245,6 +245,131 @@ library:
PRIVATE
CompatSupport_DEPRECATED=
)
.. _`WCDH Example Usage`:
Example Usage
=============
.. note::
This section was migrated from the :manual:`cmake-compile-features(7)`
manual since it relies on the ``WriteCompilerDetectionHeader`` module
which is removed by policy :policy:`CMP0120`.
Compile features may be preferred if available, without creating a hard
requirement. For example, a library may provide 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_FINAL {
void Execute() Foo_OVERRIDE;
};
In this case, ``Foo_FINAL`` will expand to ``final`` if the
compiler supports the keyword, or to empty otherwise.
In this use-case, the project code may wish to enable a particular language
standard if available from the compiler. The :prop_tgt:`CXX_STANDARD`
target property may be set to the desired language standard for a particular
target, and the :variable:`CMAKE_CXX_STANDARD` variable 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_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_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.
#]=======================================================================]
# Guard against inclusion by absolute path.
......
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