Browse Source

Merge topic 'policy-version-var' into release-4.0

1a35351125 Add CMAKE_POLICY_VERSION_MINIMUM to help configure outdated projects
d723198539 Help: De-duplicate policy version documentation
e5d29e9e00 Help: Drop cmake_minimum_required pre-2.4 behavior

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !10343
Brad King 11 months ago
parent
commit
47689e9253

+ 16 - 0
Help/command/POLICY_VERSION.txt

@@ -0,0 +1,16 @@
+This specifies that the current CMake code is written for the given range of
+CMake versions, ``<min>[...<max>]``. It sets the "policy version" to:
+
+* the range's ``<max>`` version, if specified, or to
+* the ``<min>`` version, or to
+* the value of the :variable:`CMAKE_POLICY_VERSION_MINIMUM` variable
+  if it is higher than the other two versions.
+
+The policy version effectively requests behavior preferred as of a given CMake
+version and tells newer CMake versions to warn about their new policies.
+All policies known to the running version of CMake and introduced
+in that version or earlier will be set to use ``NEW`` behavior.
+All policies introduced in later versions will be unset (unless the
+:variable:`CMAKE_POLICY_DEFAULT_CMP<NNNN>` variable sets a default).
+This effectively requests behavior preferred as of a given CMake
+version and tells newer CMake versions to warn about their new policies.

+ 6 - 26
Help/command/cmake_minimum_required.rst

@@ -19,7 +19,7 @@ form ``major.minor[.patch[.tweak]]``, and the ``...`` is literal.
 If the running version of CMake is lower than the ``<min>`` required
 version it will stop processing the project and report an error.
 The optional ``<policy_max>`` version, if specified, must be at least the
-``<min>`` version and affects policy settings as described in `Policy Settings`_.
+``<min>`` version and sets the `Policy Version`_.
 If the running version of CMake is older than 3.12, the extra ``...``
 dots will be seen as version component separators, resulting in the
 ``...<max>`` part being ignored and preserving the pre-3.12 behavior
@@ -48,38 +48,18 @@ with an error instead of just a warning.
   calling scope, calling ``cmake_minimum_required()`` inside a function
   is generally discouraged.
 
-.. _`Policy Settings`:
+.. _`Policy Version`:
 
-Policy Settings
-^^^^^^^^^^^^^^^
+Policy Version
+^^^^^^^^^^^^^^
 
-The ``cmake_minimum_required(VERSION)`` command implicitly invokes the
-:command:`cmake_policy(VERSION)` command to specify that the current
-project code is written for the given range of CMake versions.
-All policies known to the running version of CMake and introduced
-in the ``<min>`` (or ``<max>``, if specified) version or earlier will
-be set to use ``NEW`` behavior.  All policies introduced in later
-versions will be unset (unless the
-:variable:`CMAKE_POLICY_DEFAULT_CMP<NNNN>` variable sets a default).
-This effectively requests behavior preferred as of a given CMake
-version and tells newer CMake versions to warn about their new policies.
-
-When a ``<min>`` version higher than 2.4 is specified the command
-implicitly invokes
+``cmake_minimum_required(VERSION <min>[...<max>])`` implicitly invokes
 
 .. code-block:: cmake
 
   cmake_policy(VERSION <min>[...<max>])
 
-which sets CMake policies based on the range of versions specified.
-When a ``<min>`` version 2.4 or lower is given the command implicitly
-invokes
-
-.. code-block:: cmake
-
-  cmake_policy(VERSION 2.4[...<max>])
-
-which enables compatibility features for CMake 2.4 and lower.
+.. include:: POLICY_VERSION.txt
 
 .. include:: DEPRECATED_POLICY_VERSIONS.txt
 

+ 1 - 8
Help/command/cmake_policy.rst

@@ -39,14 +39,7 @@ CMake is older than 3.12, the extra ``...`` dots will be seen as version
 component separators, resulting in the ``...<max>`` part being ignored and
 preserving the pre-3.12 behavior of basing policies on ``<min>``.
 
-This specifies that the current CMake code is written for the given
-range of CMake versions.  All policies known to the running version of CMake
-and introduced in the ``<min>`` (or ``<max>``, if specified) version
-or earlier will be set to use ``NEW`` behavior.  All policies
-introduced in later versions will be unset (unless the
-:variable:`CMAKE_POLICY_DEFAULT_CMP<NNNN>` variable sets a default).
-This effectively requests behavior preferred as of a given CMake
-version and tells newer CMake versions to warn about their new policies.
+.. include:: POLICY_VERSION.txt
 
 Note that the :command:`cmake_minimum_required(VERSION)`
 command implicitly calls ``cmake_policy(VERSION)`` too.

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -254,6 +254,7 @@ Variables that Change Behavior
    /variable/CMAKE_MFC_FLAG
    /variable/CMAKE_MODULE_PATH
    /variable/CMAKE_POLICY_DEFAULT_CMPNNNN
+   /variable/CMAKE_POLICY_VERSION_MINIMUM
    /variable/CMAKE_POLICY_WARNING_CMPNNNN
    /variable/CMAKE_PREFIX_PATH
    /variable/CMAKE_PROGRAM_PATH

+ 4 - 0
Help/release/4.0.rst

@@ -72,6 +72,10 @@ Variables
   to select runtime checks for compilers targeting the MSVC ABI.
   See policy :policy:`CMP0184`.
 
+* The :variable:`CMAKE_POLICY_VERSION_MINIMUM` variable was added to
+  help pacakgers and end users try to configure existing projects that
+  have not been updated to work with supported CMake versions.
+
 * The :variable:`CMAKE_XCODE_SCHEME_LLDB_INIT_FILE` variable and corresponding
   :prop_tgt:`XCODE_SCHEME_LLDB_INIT_FILE` target property were added to tell
   the :generator:`Xcode` generator what to put in the scheme's "LLDB Init File"

+ 3 - 0
Help/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst

@@ -22,3 +22,6 @@ not itself been updated:
 * Projects may set this variable before a call to :command:`add_subdirectory`
   that adds a third-party project in order to set its policies without
   modifying third-party code.
+
+See :variable:`CMAKE_POLICY_VERSION_MINIMUM` set policies to ``NEW``
+based on the version of CMake that introduced them.

+ 23 - 0
Help/variable/CMAKE_POLICY_VERSION_MINIMUM.rst

@@ -0,0 +1,23 @@
+CMAKE_POLICY_VERSION_MINIMUM
+----------------------------
+
+.. versionadded:: 4.0
+
+Specify a minimum :ref:`Policy Version` for a project without modifying
+its calls to :command:`cmake_minimum_required(VERSION)` and
+:command:`cmake_policy(VERSION)`.
+
+This variable should not be set by a project in CMake code as a way to
+set its own policy version.  Use :command:`cmake_minimum_required(VERSION)`
+and/or :command:`cmake_policy(VERSION)` for that.  This variable is meant
+to externally set policies for which a project has not itself been updated:
+
+* Users running CMake may set this variable in the cache, e.g.,
+  ``-DCMAKE_POLICY_VERSION_MINIMUM=3.5``, to try configuring a project
+  that has not been updated to set at least that policy version itself.
+
+* Projects may set this variable before a call to :command:`add_subdirectory`
+  that adds a third-party project in order to set its policy version without
+  modifying third-party code.
+
+See :variable:`CMAKE_POLICY_DEFAULT_CMP<NNNN>` to set individual policies.

+ 28 - 1
Source/cmPolicies.cxx

@@ -15,6 +15,7 @@
 #include "cmStateSnapshot.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
+#include "cmValue.h"
 #include "cmVersion.h"
 
 static bool stringToId(char const* input, cmPolicies::PolicyID& pid)
@@ -294,6 +295,30 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
                                     unsigned int patchVer,
                                     WarnCompat warnCompat)
 {
+  cmValue varVer = mf->GetDefinition("CMAKE_POLICY_VERSION_MINIMUM");
+  if (!varVer.IsEmpty()) {
+    unsigned int varMajor = 0;
+    unsigned int varMinor = 0;
+    unsigned int varPatch = 0;
+    unsigned int varTweak = 0;
+    if (sscanf(varVer.GetCStr(), "%u.%u.%u.%u", &varMajor, &varMinor,
+               &varPatch, &varTweak) < 2) {
+      mf->IssueMessage(
+        MessageType::FATAL_ERROR,
+        cmStrCat("Invalid CMAKE_POLICY_VERSION_MINIMUM value \"", varVer,
+                 "\".  "
+                 "A numeric major.minor[.patch[.tweak]] must be given."));
+      return false;
+    }
+    if (varMajor > majorVer || (varMajor == majorVer && varMinor > minorVer) ||
+        (varMajor == majorVer && varMinor == minorVer &&
+         varPatch > patchVer)) {
+      majorVer = varMajor;
+      minorVer = varMinor;
+      patchVer = varPatch;
+    }
+  }
+
   // Error on policy versions for which support has been removed.
   if (majorVer < 3 || (majorVer == 3 && minorVer < 5)) {
     if (IsFromLegacyInstallEXPORT(mf, majorVer, minorVer, patchVer)) {
@@ -305,7 +330,9 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
     } else {
       mf->IssueMessage(MessageType::FATAL_ERROR,
                        "Compatibility with CMake < 3.5 has been removed "
-                       "from CMake.\n" ADVICE_UPDATE_VERSION_ARGUMENT);
+                       "from CMake.\n" ADVICE_UPDATE_VERSION_ARGUMENT "\n"
+                       "Or, add -DCMAKE_POLICY_VERSION_MINIMUM=3.5 to try "
+                       "configuring anyway.");
       cmSystemTools::SetFatalErrorOccurred();
       return false;
     }

+ 2 - 0
Tests/RunCMake/cmake_minimum_required/BeforeVersionRemoved-stderr.txt

@@ -4,5 +4,7 @@
   Update the VERSION argument <min> value\.  Or, use the <min>\.\.\.<max> syntax
   to tell CMake that the project requires at least <min> but has been updated
   to work with policies introduced by <max> or earlier\.
+
+  Or, add -DCMAKE_POLICY_VERSION_MINIMUM=3\.5 to try configuring anyway\.
 Call Stack \(most recent call first\):
   CMakeLists\.txt:[0-9]+ \(include\)$

+ 2 - 0
Tests/RunCMake/cmake_minimum_required/PolicyBeforeVersionRemoved-stderr.txt

@@ -4,5 +4,7 @@
   Update the VERSION argument <min> value\.  Or, use the <min>\.\.\.<max> syntax
   to tell CMake that the project requires at least <min> but has been updated
   to work with policies introduced by <max> or earlier\.
+
+  Or, add -DCMAKE_POLICY_VERSION_MINIMUM=3\.5 to try configuring anyway\.
 Call Stack \(most recent call first\):
   CMakeLists\.txt:[0-9]+ \(include\)$

+ 3 - 0
Tests/RunCMake/cmake_minimum_required/PolicyVersionVariable-stderr.txt

@@ -0,0 +1,3 @@
+^CMAKE_MINIMUM_REQUIRED_VERSION='3\.1'
+CMP0071='NEW'
+CMP0072=''$

+ 7 - 0
Tests/RunCMake/cmake_minimum_required/PolicyVersionVariable.cmake

@@ -0,0 +1,7 @@
+set(CMAKE_POLICY_VERSION_MINIMUM 3.10)
+cmake_minimum_required(VERSION 3.1...3.4)
+message("CMAKE_MINIMUM_REQUIRED_VERSION='${CMAKE_MINIMUM_REQUIRED_VERSION}'")
+foreach(policy CMP0071 CMP0072)
+  cmake_policy(GET ${policy} status)
+  message("${policy}='${status}'")
+endforeach()

+ 1 - 0
Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad-stderr.txt

@@ -0,0 +1,5 @@
+^CMake Error at PolicyVersionVariableBad\.cmake:2 \(cmake_minimum_required\):
+  Invalid CMAKE_POLICY_VERSION_MINIMUM value "\.\.\.3\.10"\.  A numeric
+  major\.minor\[\.patch\[\.tweak\]\] must be given\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$

+ 2 - 0
Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad.cmake

@@ -0,0 +1,2 @@
+set(CMAKE_POLICY_VERSION_MINIMUM ...3.10)
+cmake_minimum_required(VERSION 3.1...3.4)

+ 2 - 0
Tests/RunCMake/cmake_minimum_required/RunCMakeTest.cmake

@@ -7,3 +7,5 @@ run_cmake(BeforeVersionDeprecated)
 run_cmake(Range)
 run_cmake(RangeBad)
 run_cmake(Unknown)
+run_cmake(PolicyVersionVariable)
+run_cmake(PolicyVersionVariableBad)