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