From e5d29e9e008b0de0a30dd94125d71131abb13634 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 13 Feb 2025 12:20:40 -0500 Subject: [PATCH 1/3] Help: Drop cmake_minimum_required pre-2.4 behavior The long outdated pre-2.4 compatibility behavior is no longer relevant since CMake 4.0 dropped support for pre-3.5 compatibility. --- Help/command/cmake_minimum_required.rst | 29 ++++++++----------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/Help/command/cmake_minimum_required.rst b/Help/command/cmake_minimum_required.rst index 2833ed7a0b..d671008529 100644 --- a/Help/command/cmake_minimum_required.rst +++ b/Help/command/cmake_minimum_required.rst @@ -53,9 +53,15 @@ with an error instead of just a warning. Policy Settings ^^^^^^^^^^^^^^^ -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. +``cmake_minimum_required(VERSION [...])`` implicitly invokes + +.. code-block:: cmake + + cmake_policy(VERSION [...]) + +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 ```` (or ````, if specified) version or earlier will be set to use ``NEW`` behavior. All policies introduced in later @@ -64,23 +70,6 @@ versions will be unset (unless the This effectively requests behavior preferred as of a given CMake version and tells newer CMake versions to warn about their new policies. -When a ```` version higher than 2.4 is specified the command -implicitly invokes - -.. code-block:: cmake - - cmake_policy(VERSION [...]) - -which sets CMake policies based on the range of versions specified. -When a ```` version 2.4 or lower is given the command implicitly -invokes - -.. code-block:: cmake - - cmake_policy(VERSION 2.4[...]) - -which enables compatibility features for CMake 2.4 and lower. - .. include:: DEPRECATED_POLICY_VERSIONS.txt See Also From d723198539ea9881c42d928fae3cc759aee1d03e Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 13 Feb 2025 12:29:38 -0500 Subject: [PATCH 2/3] Help: De-duplicate policy version documentation --- Help/command/POLICY_VERSION.txt | 14 ++++++++++++++ Help/command/cmake_minimum_required.rst | 19 +++++-------------- Help/command/cmake_policy.rst | 9 +-------- 3 files changed, 20 insertions(+), 22 deletions(-) create mode 100644 Help/command/POLICY_VERSION.txt diff --git a/Help/command/POLICY_VERSION.txt b/Help/command/POLICY_VERSION.txt new file mode 100644 index 0000000000..9ac998c134 --- /dev/null +++ b/Help/command/POLICY_VERSION.txt @@ -0,0 +1,14 @@ +This specifies that the current CMake code is written for the given range of +CMake versions, ``[...]``. It sets the "policy version" to: + +* the range's ```` version, if specified, or to +* the ```` version. + +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` 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. diff --git a/Help/command/cmake_minimum_required.rst b/Help/command/cmake_minimum_required.rst index d671008529..47e8e6bafc 100644 --- a/Help/command/cmake_minimum_required.rst +++ b/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 ```` required version it will stop processing the project and report an error. The optional ```` version, if specified, must be at least the -```` version and affects policy settings as described in `Policy Settings`_. +```` 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 ``...`` part being ignored and preserving the pre-3.12 behavior @@ -48,10 +48,10 @@ 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 +^^^^^^^^^^^^^^ ``cmake_minimum_required(VERSION [...])`` implicitly invokes @@ -59,16 +59,7 @@ Policy Settings cmake_policy(VERSION [...]) -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 ```` (or ````, 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` 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 .. include:: DEPRECATED_POLICY_VERSIONS.txt diff --git a/Help/command/cmake_policy.rst b/Help/command/cmake_policy.rst index 4a08c01364..276e160f08 100644 --- a/Help/command/cmake_policy.rst +++ b/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 ``...`` part being ignored and preserving the pre-3.12 behavior of basing policies on ````. -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 ```` (or ````, 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` 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. From 1a353511250a7191086bf15645fe7c8f79caac1a Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 13 Feb 2025 12:37:32 -0500 Subject: [PATCH 3/3] Add CMAKE_POLICY_VERSION_MINIMUM to help configure outdated projects Provide packagers and end users with a way to try configuring projects that have not been updated to set their policy version to a supported level. Closes: #26698 --- Help/command/POLICY_VERSION.txt | 4 ++- Help/manual/cmake-variables.7.rst | 1 + Help/release/4.0.rst | 4 +++ .../variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst | 3 ++ .../variable/CMAKE_POLICY_VERSION_MINIMUM.rst | 23 +++++++++++++++ Source/cmPolicies.cxx | 29 ++++++++++++++++++- .../BeforeVersionRemoved-stderr.txt | 2 ++ .../PolicyBeforeVersionRemoved-stderr.txt | 2 ++ .../PolicyVersionVariable-stderr.txt | 3 ++ .../PolicyVersionVariable.cmake | 7 +++++ .../PolicyVersionVariableBad-result.txt | 1 + .../PolicyVersionVariableBad-stderr.txt | 5 ++++ .../PolicyVersionVariableBad.cmake | 2 ++ .../cmake_minimum_required/RunCMakeTest.cmake | 2 ++ 14 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 Help/variable/CMAKE_POLICY_VERSION_MINIMUM.rst create mode 100644 Tests/RunCMake/cmake_minimum_required/PolicyVersionVariable-stderr.txt create mode 100644 Tests/RunCMake/cmake_minimum_required/PolicyVersionVariable.cmake create mode 100644 Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad-result.txt create mode 100644 Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad-stderr.txt create mode 100644 Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad.cmake diff --git a/Help/command/POLICY_VERSION.txt b/Help/command/POLICY_VERSION.txt index 9ac998c134..424849d60a 100644 --- a/Help/command/POLICY_VERSION.txt +++ b/Help/command/POLICY_VERSION.txt @@ -2,7 +2,9 @@ This specifies that the current CMake code is written for the given range of CMake versions, ``[...]``. It sets the "policy version" to: * the range's ```` version, if specified, or to -* the ```` version. +* the ```` 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. diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 200fc18e86..cbf8a920ce 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/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 diff --git a/Help/release/4.0.rst b/Help/release/4.0.rst index 80a55bf872..b1102d5b79 100644 --- a/Help/release/4.0.rst +++ b/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" diff --git a/Help/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst index d643fb8df1..5f47d4e61c 100644 --- a/Help/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst +++ b/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. diff --git a/Help/variable/CMAKE_POLICY_VERSION_MINIMUM.rst b/Help/variable/CMAKE_POLICY_VERSION_MINIMUM.rst new file mode 100644 index 0000000000..cf48ecfe9b --- /dev/null +++ b/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` to set individual policies. diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 9de978ec6d..908a7867cb 100644 --- a/Source/cmPolicies.cxx +++ b/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; } diff --git a/Tests/RunCMake/cmake_minimum_required/BeforeVersionRemoved-stderr.txt b/Tests/RunCMake/cmake_minimum_required/BeforeVersionRemoved-stderr.txt index 62145e638b..f2f41aff54 100644 --- a/Tests/RunCMake/cmake_minimum_required/BeforeVersionRemoved-stderr.txt +++ b/Tests/RunCMake/cmake_minimum_required/BeforeVersionRemoved-stderr.txt @@ -4,5 +4,7 @@ Update the VERSION argument value\. Or, use the \.\.\. syntax to tell CMake that the project requires at least but has been updated to work with policies introduced by 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\)$ diff --git a/Tests/RunCMake/cmake_minimum_required/PolicyBeforeVersionRemoved-stderr.txt b/Tests/RunCMake/cmake_minimum_required/PolicyBeforeVersionRemoved-stderr.txt index c9eba0fbd5..bf4035a1a6 100644 --- a/Tests/RunCMake/cmake_minimum_required/PolicyBeforeVersionRemoved-stderr.txt +++ b/Tests/RunCMake/cmake_minimum_required/PolicyBeforeVersionRemoved-stderr.txt @@ -4,5 +4,7 @@ Update the VERSION argument value\. Or, use the \.\.\. syntax to tell CMake that the project requires at least but has been updated to work with policies introduced by 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\)$ diff --git a/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariable-stderr.txt b/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariable-stderr.txt new file mode 100644 index 0000000000..4f161bf084 --- /dev/null +++ b/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariable-stderr.txt @@ -0,0 +1,3 @@ +^CMAKE_MINIMUM_REQUIRED_VERSION='3\.1' +CMP0071='NEW' +CMP0072=''$ diff --git a/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariable.cmake b/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariable.cmake new file mode 100644 index 0000000000..553fc94d14 --- /dev/null +++ b/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() diff --git a/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad-result.txt b/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad-stderr.txt b/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad-stderr.txt new file mode 100644 index 0000000000..3a59bb77a6 --- /dev/null +++ b/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\)$ diff --git a/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad.cmake b/Tests/RunCMake/cmake_minimum_required/PolicyVersionVariableBad.cmake new file mode 100644 index 0000000000..763997b40f --- /dev/null +++ b/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) diff --git a/Tests/RunCMake/cmake_minimum_required/RunCMakeTest.cmake b/Tests/RunCMake/cmake_minimum_required/RunCMakeTest.cmake index cd63093c4e..d91f171546 100644 --- a/Tests/RunCMake/cmake_minimum_required/RunCMakeTest.cmake +++ b/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)