Browse Source

Merge topic 'policy-version-range'

45408b5ea1 cmake_minimum_required: Optionally set policies with version range
6a41aa2abd cmPolicies: Split parsing and impl of ApplyPolicyVersion
1d00ed7cf7 cmPolicies: Drop unnecessary check from ApplyPolicyVersion
0df559832b cmPolicies: Pass policy version as std::string

Acked-by: Kitware Robot <[email protected]>
Merge-request: !1864
Craig Scott 7 năm trước cách đây
mục cha
commit
82df2fe17e

+ 20 - 14
Help/command/cmake_minimum_required.rst

@@ -4,11 +4,15 @@ cmake_minimum_required
 Set the minimum required version of cmake for a project and
 Set the minimum required version of cmake for a project and
 update `Policy Settings`_ to match the version given::
 update `Policy Settings`_ to match the version given::
 
 
-  cmake_minimum_required(VERSION major.minor[.patch[.tweak]]
-                         [FATAL_ERROR])
+  cmake_minimum_required(VERSION <min>[...<max>] [FATAL_ERROR])
 
 
-If the current version of CMake is lower than that required it will
-stop processing the project and report an error.
+``<min>`` and the optional ``<max>`` are each CMake versions of the 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 ``<max>`` version, if specified, must be at least the
+``<min>`` version and affects policy settings as described below.
 
 
 The ``FATAL_ERROR`` option is accepted but ignored by CMake 2.6 and
 The ``FATAL_ERROR`` option is accepted but ignored by CMake 2.6 and
 higher.  It should be specified so CMake versions 2.4 and lower fail
 higher.  It should be specified so CMake versions 2.4 and lower fail
@@ -30,21 +34,23 @@ Policy Settings
 
 
 The ``cmake_minimum_required(VERSION)`` command implicitly invokes the
 The ``cmake_minimum_required(VERSION)`` command implicitly invokes the
 :command:`cmake_policy(VERSION)` command to specify that the current
 :command:`cmake_policy(VERSION)` command to specify that the current
-project code is written for the given version of CMake.
-All policies introduced in the specified version or earlier will be
-set to use NEW behavior.  All policies introduced after the specified
-version will be unset.  This effectively requests behavior preferred
+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.  This effectively requests behavior preferred
 as of a given CMake version and tells newer CMake versions to warn
 as of a given CMake version and tells newer CMake versions to warn
 about their new policies.
 about their new policies.
 
 
-When a version higher than 2.4 is specified the command implicitly
-invokes::
+When a ``<min>`` version higher than 2.4 is specified the command
+implicitly invokes::
 
 
-  cmake_policy(VERSION major[.minor[.patch[.tweak]]])
+  cmake_policy(VERSION <min>[...<max>])
 
 
-which sets the cmake policy version level to the version specified.
-When version 2.4 or lower is given the command implicitly invokes::
+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::
 
 
-  cmake_policy(VERSION 2.4)
+  cmake_policy(VERSION 2.4[...<max>])
 
 
 which enables compatibility features for CMake 2.4 and lower.
 which enables compatibility features for CMake 2.4 and lower.

+ 13 - 8
Help/command/cmake_policy.rst

@@ -24,17 +24,22 @@ The ``cmake_policy`` command is used to set policies to ``OLD`` or ``NEW``
 behavior.  While setting policies individually is supported, we
 behavior.  While setting policies individually is supported, we
 encourage projects to set policies based on CMake versions::
 encourage projects to set policies based on CMake versions::
 
 
-  cmake_policy(VERSION major.minor[.patch[.tweak]])
-
-Specify that the current CMake code is written for the given
-version of CMake.  All policies introduced in the specified version or
-earlier will be set to use ``NEW`` behavior.  All policies introduced
-after the specified version will be unset (unless the
+  cmake_policy(VERSION <min>[...<max>])
+
+``<min>`` and the optional ``<max>`` are each CMake versions of the form
+``major.minor[.patch[.tweak]]``, and the ``...`` is literal.  The ``<min>``
+version must be at least ``2.4`` and at most the running version of CMake.
+The ``<max>`` version, if specified, must be at least the ``<min>`` version
+but may exceed the running version of CMake.
+
+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).
 :variable:`CMAKE_POLICY_DEFAULT_CMP<NNNN>` variable sets a default).
 This effectively requests behavior preferred as of a given CMake
 This effectively requests behavior preferred as of a given CMake
 version and tells newer CMake versions to warn about their new policies.
 version and tells newer CMake versions to warn about their new policies.
-The policy version specified must be at least 2.4 or the command will
-report an error.
 
 
 Note that the :command:`cmake_minimum_required(VERSION)`
 Note that the :command:`cmake_minimum_required(VERSION)`
 command implicitly calls ``cmake_policy(VERSION)`` too.
 command implicitly calls ``cmake_policy(VERSION)`` too.

+ 8 - 0
Help/release/dev/policy-version-range.rst

@@ -0,0 +1,8 @@
+policy-version-range
+--------------------
+
+* The :command:`cmake_minimum_required` and :command:`cmake_policy(VERSION)`
+  commands now accept a version range using the form ``<min>[...<max>]``.
+  The ``<min>`` version is required but policies are set based on the
+  ``<max>`` version.  This allows projects to specify a range of versions
+  for which they have been updated and avoid explicit policy settings.

+ 2 - 4
Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst

@@ -1,7 +1,5 @@
 CMAKE_MINIMUM_REQUIRED_VERSION
 CMAKE_MINIMUM_REQUIRED_VERSION
 ------------------------------
 ------------------------------
 
 
-Version specified to :command:`cmake_minimum_required` command
-
-Variable containing the ``VERSION`` component specified in the
-:command:`cmake_minimum_required` command.
+The ``<min>`` version of CMake given to the most recent call to the
+:command:`cmake_minimum_required(VERSION)` command.

+ 2 - 1
Source/CPack/cmCPackGenerator.cxx

@@ -1002,7 +1002,8 @@ int cmCPackGenerator::DoPackage()
   { // scope that enables package generators to run internal scripts with
   { // scope that enables package generators to run internal scripts with
     // latest CMake policies enabled
     // latest CMake policies enabled
     cmMakefile::ScopePushPop pp{ this->MakefileMap };
     cmMakefile::ScopePushPop pp{ this->MakefileMap };
-    this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion());
+    this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion(),
+                                        std::string());
 
 
     if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
     if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
       cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"
       cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"

+ 21 - 6
Source/cmCMakeMinimumRequired.cxx

@@ -45,9 +45,24 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
     return this->EnforceUnknownArguments();
     return this->EnforceUnknownArguments();
   }
   }
 
 
+  // Separate the <min> version and any trailing ...<max> component.
+  std::string::size_type const dd = version_string.find("...");
+  std::string const version_min = version_string.substr(0, dd);
+  std::string const version_max = dd != std::string::npos
+    ? version_string.substr(dd + 3, std::string::npos)
+    : std::string();
+  if (dd != std::string::npos &&
+      (version_min.empty() || version_max.empty())) {
+    std::ostringstream e;
+    e << "VERSION \"" << version_string
+      << "\" does not have a version on both sides of \"...\".";
+    this->SetError(e.str());
+    return false;
+  }
+
   // Save the required version string.
   // Save the required version string.
   this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
   this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
-                                version_string.c_str());
+                                version_min.c_str());
 
 
   // Get the current version number.
   // Get the current version number.
   unsigned int current_major = cmVersion::GetMajorVersion();
   unsigned int current_major = cmVersion::GetMajorVersion();
@@ -61,10 +76,10 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
   unsigned int required_minor = 0;
   unsigned int required_minor = 0;
   unsigned int required_patch = 0;
   unsigned int required_patch = 0;
   unsigned int required_tweak = 0;
   unsigned int required_tweak = 0;
-  if (sscanf(version_string.c_str(), "%u.%u.%u.%u", &required_major,
+  if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &required_major,
              &required_minor, &required_patch, &required_tweak) < 2) {
              &required_minor, &required_patch, &required_tweak) < 2) {
     std::ostringstream e;
     std::ostringstream e;
-    e << "could not parse VERSION \"" << version_string << "\".";
+    e << "could not parse VERSION \"" << version_min << "\".";
     this->SetError(e.str());
     this->SetError(e.str());
     return false;
     return false;
   }
   }
@@ -78,7 +93,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
        current_patch == required_patch && current_tweak < required_tweak)) {
        current_patch == required_patch && current_tweak < required_tweak)) {
     // The current version is too low.
     // The current version is too low.
     std::ostringstream e;
     std::ostringstream e;
-    e << "CMake " << version_string
+    e << "CMake " << version_min
       << " or higher is required.  You are running version "
       << " or higher is required.  You are running version "
       << cmVersion::GetCMakeVersion();
       << cmVersion::GetCMakeVersion();
     this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
     this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
@@ -95,9 +110,9 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
     this->Makefile->IssueMessage(
     this->Makefile->IssueMessage(
       cmake::AUTHOR_WARNING,
       cmake::AUTHOR_WARNING,
       "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.");
       "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.");
-    this->Makefile->SetPolicyVersion("2.4");
+    this->Makefile->SetPolicyVersion("2.4", version_max);
   } else {
   } else {
-    this->Makefile->SetPolicyVersion(version_string.c_str());
+    this->Makefile->SetPolicyVersion(version_min, version_max);
   }
   }
 
 
   return true;
   return true;

+ 18 - 1
Source/cmCMakePolicyCommand.cxx

@@ -156,6 +156,23 @@ bool cmCMakePolicyCommand::HandleVersionMode(
     this->SetError("VERSION given too many arguments");
     this->SetError("VERSION given too many arguments");
     return false;
     return false;
   }
   }
-  this->Makefile->SetPolicyVersion(args[1].c_str());
+  std::string const& version_string = args[1];
+
+  // Separate the <min> version and any trailing ...<max> component.
+  std::string::size_type const dd = version_string.find("...");
+  std::string const version_min = version_string.substr(0, dd);
+  std::string const version_max = dd != std::string::npos
+    ? version_string.substr(dd + 3, std::string::npos)
+    : std::string();
+  if (dd != std::string::npos &&
+      (version_min.empty() || version_max.empty())) {
+    std::ostringstream e;
+    e << "VERSION \"" << version_string
+      << "\" does not have a version on both sides of \"...\".";
+    this->SetError(e.str());
+    return false;
+  }
+
+  this->Makefile->SetPolicyVersion(version_min, version_max);
   return true;
   return true;
 }
 }

+ 4 - 3
Source/cmMakefile.cxx

@@ -1490,7 +1490,7 @@ void cmMakefile::Configure()
         this->SetCheckCMP0000(true);
         this->SetCheckCMP0000(true);
 
 
         // Implicitly set the version for the user.
         // Implicitly set the version for the user.
-        this->SetPolicyVersion("2.4");
+        this->SetPolicyVersion("2.4", std::string());
       }
       }
     }
     }
     bool hasProject = false;
     bool hasProject = false;
@@ -4175,9 +4175,10 @@ void cmMakefile::PopSnapshot(bool reportError)
   assert(this->StateSnapshot.IsValid());
   assert(this->StateSnapshot.IsValid());
 }
 }
 
 
-bool cmMakefile::SetPolicyVersion(const char* version)
+bool cmMakefile::SetPolicyVersion(std::string const& version_min,
+                                  std::string const& version_max)
 {
 {
-  return cmPolicies::ApplyPolicyVersion(this, version);
+  return cmPolicies::ApplyPolicyVersion(this, version_min, version_max);
 }
 }
 
 
 bool cmMakefile::HasCMP0054AlreadyBeenReported(
 bool cmMakefile::HasCMP0054AlreadyBeenReported(

+ 2 - 1
Source/cmMakefile.h

@@ -285,7 +285,8 @@ public:
   bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
   bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
   bool SetPolicy(const char* id, cmPolicies::PolicyStatus status);
   bool SetPolicy(const char* id, cmPolicies::PolicyStatus status);
   cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id) const;
   cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id) const;
-  bool SetPolicyVersion(const char* version);
+  bool SetPolicyVersion(std::string const& version_min,
+                        std::string const& version_max);
   void RecordPolicies(cmPolicies::PolicyMap& pm);
   void RecordPolicies(cmPolicies::PolicyMap& pm);
   //@}
   //@}
 
 

+ 69 - 28
Source/cmPolicies.cxx

@@ -153,31 +153,26 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy,
   return true;
   return true;
 }
 }
 
 
-bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
+bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf,
+                                    std::string const& version_min,
+                                    std::string const& version_max)
 {
 {
-  std::string ver = "2.4.0";
-
-  if (version && strlen(version) > 0) {
-    ver = version;
-  }
-
-  unsigned int majorVer = 2;
-  unsigned int minorVer = 0;
-  unsigned int patchVer = 0;
-  unsigned int tweakVer = 0;
-
-  // parse the string
-  if (sscanf(ver.c_str(), "%u.%u.%u.%u", &majorVer, &minorVer, &patchVer,
-             &tweakVer) < 2) {
+  // Parse components of the minimum version.
+  unsigned int minMajor = 2;
+  unsigned int minMinor = 0;
+  unsigned int minPatch = 0;
+  unsigned int minTweak = 0;
+  if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &minMajor, &minMinor,
+             &minPatch, &minTweak) < 2) {
     std::ostringstream e;
     std::ostringstream e;
-    e << "Invalid policy version value \"" << ver << "\".  "
+    e << "Invalid policy version value \"" << version_min << "\".  "
       << "A numeric major.minor[.patch[.tweak]] must be given.";
       << "A numeric major.minor[.patch[.tweak]] must be given.";
     mf->IssueMessage(cmake::FATAL_ERROR, e.str());
     mf->IssueMessage(cmake::FATAL_ERROR, e.str());
     return false;
     return false;
   }
   }
 
 
   // it is an error if the policy version is less than 2.4
   // it is an error if the policy version is less than 2.4
-  if (majorVer < 2 || (majorVer == 2 && minorVer < 4)) {
+  if (minMajor < 2 || (minMajor == 2 && minMinor < 4)) {
     mf->IssueMessage(
     mf->IssueMessage(
       cmake::FATAL_ERROR,
       cmake::FATAL_ERROR,
       "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.  "
       "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.  "
@@ -188,19 +183,19 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
 
 
   // It is an error if the policy version is greater than the running
   // It is an error if the policy version is greater than the running
   // CMake.
   // CMake.
-  if (majorVer > cmVersion::GetMajorVersion() ||
-      (majorVer == cmVersion::GetMajorVersion() &&
-       minorVer > cmVersion::GetMinorVersion()) ||
-      (majorVer == cmVersion::GetMajorVersion() &&
-       minorVer == cmVersion::GetMinorVersion() &&
-       patchVer > cmVersion::GetPatchVersion()) ||
-      (majorVer == cmVersion::GetMajorVersion() &&
-       minorVer == cmVersion::GetMinorVersion() &&
-       patchVer == cmVersion::GetPatchVersion() &&
-       tweakVer > cmVersion::GetTweakVersion())) {
+  if (minMajor > cmVersion::GetMajorVersion() ||
+      (minMajor == cmVersion::GetMajorVersion() &&
+       minMinor > cmVersion::GetMinorVersion()) ||
+      (minMajor == cmVersion::GetMajorVersion() &&
+       minMinor == cmVersion::GetMinorVersion() &&
+       minPatch > cmVersion::GetPatchVersion()) ||
+      (minMajor == cmVersion::GetMajorVersion() &&
+       minMinor == cmVersion::GetMinorVersion() &&
+       minPatch == cmVersion::GetPatchVersion() &&
+       minTweak > cmVersion::GetTweakVersion())) {
     std::ostringstream e;
     std::ostringstream e;
     e << "An attempt was made to set the policy version of CMake to \""
     e << "An attempt was made to set the policy version of CMake to \""
-      << version << "\" which is greater than this version of CMake.  "
+      << version_min << "\" which is greater than this version of CMake.  "
       << "This is not allowed because the greater version may have new "
       << "This is not allowed because the greater version may have new "
       << "policies not known to this CMake.  "
       << "policies not known to this CMake.  "
       << "You may need a newer CMake version to build this project.";
       << "You may need a newer CMake version to build this project.";
@@ -208,6 +203,52 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
     return false;
     return false;
   }
   }
 
 
+  unsigned int polMajor = minMajor;
+  unsigned int polMinor = minMinor;
+  unsigned int polPatch = minPatch;
+
+  if (!version_max.empty()) {
+    // Parse components of the maximum version.
+    unsigned int maxMajor = 0;
+    unsigned int maxMinor = 0;
+    unsigned int maxPatch = 0;
+    unsigned int maxTweak = 0;
+    if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &maxMajor, &maxMinor,
+               &maxPatch, &maxTweak) < 2) {
+      std::ostringstream e;
+      e << "Invalid policy max version value \"" << version_max << "\".  "
+        << "A numeric major.minor[.patch[.tweak]] must be given.";
+      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return false;
+    }
+
+    // It is an error if the min version is greater than the max version.
+    if (minMajor > maxMajor || (minMajor == maxMajor && minMinor > maxMinor) ||
+        (minMajor == maxMajor && minMinor == maxMinor &&
+         minPatch > maxPatch) ||
+        (minMajor == maxMajor && minMinor == maxMinor &&
+         minPatch == maxPatch && minTweak > maxTweak)) {
+      std::ostringstream e;
+      e << "Policy VERSION range \"" << version_min << "..." << version_max
+        << "\""
+        << " specifies a larger minimum than maximum.";
+      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return false;
+    }
+
+    // Use the max version as the policy version.
+    polMajor = maxMajor;
+    polMinor = maxMinor;
+    polPatch = maxPatch;
+  }
+
+  return cmPolicies::ApplyPolicyVersion(mf, polMajor, polMinor, polPatch);
+}
+
+bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
+                                    unsigned int minorVer,
+                                    unsigned int patchVer)
+{
   // now loop over all the policies and set them as appropriate
   // now loop over all the policies and set them as appropriate
   std::vector<cmPolicies::PolicyID> ancientPolicies;
   std::vector<cmPolicies::PolicyID> ancientPolicies;
   for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;
   for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;

+ 5 - 1
Source/cmPolicies.h

@@ -290,7 +290,11 @@ public:
   static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id);
   static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id);
 
 
   ///! Set a policy level for this listfile
   ///! Set a policy level for this listfile
-  static bool ApplyPolicyVersion(cmMakefile* mf, const char* version);
+  static bool ApplyPolicyVersion(cmMakefile* mf,
+                                 std::string const& version_min,
+                                 std::string const& version_max);
+  static bool ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
+                                 unsigned int minorVer, unsigned int patchVer);
 
 
   ///! return a warning string for a given policy
   ///! return a warning string for a given policy
   static std::string GetPolicyWarning(cmPolicies::PolicyID id);
   static std::string GetPolicyWarning(cmPolicies::PolicyID id);

+ 1 - 1
Source/cmQtAutoGenerator.cxx

@@ -612,7 +612,7 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile,
     auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
     auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
     // The OLD/WARN behavior for policy CMP0053 caused a speed regression.
     // The OLD/WARN behavior for policy CMP0053 caused a speed regression.
     // https://gitlab.kitware.com/cmake/cmake/issues/17570
     // https://gitlab.kitware.com/cmake/cmake/issues/17570
-    makefile->SetPolicyVersion("3.9");
+    makefile->SetPolicyVersion("3.9", std::string());
     gg.SetCurrentMakefile(makefile.get());
     gg.SetCurrentMakefile(makefile.get());
     success = this->Init(makefile.get());
     success = this->Init(makefile.get());
   }
   }

+ 4 - 0
Tests/RunCMake/cmake_minimum_required/Range-stderr.txt

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

+ 6 - 0
Tests/RunCMake/cmake_minimum_required/Range.cmake

@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.10...3.11)
+message("CMAKE_MINIMUM_REQUIRED_VERSION='${CMAKE_MINIMUM_REQUIRED_VERSION}'")
+foreach(policy CMP0071 CMP0072 CMP0073)
+  cmake_policy(GET ${policy} status)
+  message("${policy}='${status}'")
+endforeach()

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

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

+ 56 - 0
Tests/RunCMake/cmake_minimum_required/RangeBad-stderr.txt

@@ -0,0 +1,56 @@
+^CMake Error at RangeBad.cmake:1 \(cmake_minimum_required\):
+  cmake_minimum_required VERSION "3.11..." does not have a version on both
+  sides of "...".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:2 \(cmake_minimum_required\):
+  cmake_minimum_required VERSION "...3.11" does not have a version on both
+  sides of "...".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:3 \(cmake_minimum_required\):
+  cmake_minimum_required VERSION "..." does not have a version on both sides
+  of "...".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:4 \(cmake_minimum_required\):
+  Invalid policy max version value "4".  A numeric
+  major.minor\[.patch\[.tweak\]\] must be given.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:5 \(cmake_minimum_required\):
+  Policy VERSION range "3.11...3.10" specifies a larger minimum than maximum.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:6 \(cmake_policy\):
+  cmake_policy VERSION "3.11..." does not have a version on both sides of
+  "...".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:7 \(cmake_policy\):
+  cmake_policy VERSION "...3.11" does not have a version on both sides of
+  "...".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:8 \(cmake_policy\):
+  cmake_policy VERSION "..." does not have a version on both sides of "...".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:9 \(cmake_policy\):
+  Invalid policy max version value "4".  A numeric
+  major.minor\[.patch\[.tweak\]\] must be given.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at RangeBad.cmake:10 \(cmake_policy\):
+  Policy VERSION range "3.11...3.10" specifies a larger minimum than maximum.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$

+ 10 - 0
Tests/RunCMake/cmake_minimum_required/RangeBad.cmake

@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.11...)
+cmake_minimum_required(VERSION ...3.11)
+cmake_minimum_required(VERSION ...)
+cmake_minimum_required(VERSION 3.11...4)
+cmake_minimum_required(VERSION 3.11...3.10)
+cmake_policy(VERSION 3.11...)
+cmake_policy(VERSION ...3.11)
+cmake_policy(VERSION ...)
+cmake_policy(VERSION 3.11...4)
+cmake_policy(VERSION 3.11...3.10)

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

@@ -3,3 +3,5 @@ include(RunCMake)
 run_cmake(Before24)
 run_cmake(Before24)
 run_cmake(CompatBefore24)
 run_cmake(CompatBefore24)
 run_cmake(PolicyBefore24)
 run_cmake(PolicyBefore24)
+run_cmake(Range)
+run_cmake(RangeBad)