diff options
-rw-r--r-- | Help/manual/cmake-compile-features.7.rst | 130 | ||||
-rw-r--r-- | Modules/WriteCompilerDetectionHeader.cmake | 125 |
2 files changed, 141 insertions, 114 deletions
diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index 2fa469f..2c2b04c 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -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" diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake index 5e6828f..0e4e028 100644 --- a/Modules/WriteCompilerDetectionHeader.cmake +++ b/Modules/WriteCompilerDetectionHeader.cmake @@ -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. |