From 1f4ec3f4a78a084638e11e73ca6be83899cf79ae Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Fri, 23 Apr 2021 10:39:02 -0400
Subject: [PATCH] Help: Do not recommend WCDH in cmake-compile-features(7)

Since commit da7ad7997e (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.
---
 Help/manual/cmake-compile-features.7.rst   | 130 +++------------------
 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 2fa469f224..2c2b04cbe2 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 5e6828f3bb..0e4e028051 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.
-- 
GitLab