Commit 8bc64a0c authored by Brad King's avatar Brad King Committed by Kitware Robot
Browse files

Merge topic 'doc-compile-features-wcdh'

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

 Help: Fix typos in cmake-compile-features(7)
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !6037
parents 28cb4df4 1f4ec3f4
......@@ -130,118 +130,21 @@ 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_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 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_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
===============================
......@@ -284,13 +187,12 @@ while a header at ``no_variadics/interface.h`` may contain:
static int accumulate() { return I1 + I2 + I3 + I4; }
};
It would be possible to write a abstraction ``interface.h`` header
It may be possible to write an abstraction ``interface.h`` header
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