mirror of
https://github.com/reactos/CMake.git
synced 2025-01-09 05:00:35 +00:00
cmake_minimum_required: Optionally set policies with version range
Teach `cmake_minimum_required` and `cmake_policy(VERSION)` to support a version range of the form `<min>[...<max>]`. Define this to mean that version `<min>` is required, but known policies up to those introduced by `<max>` will be set to `NEW`. This will allow projects to easily specify a range of versions for which they have been updated.
This commit is contained in:
parent
6a41aa2abd
commit
45408b5ea1
@ -4,11 +4,15 @@ cmake_minimum_required
|
||||
Set the minimum required version of cmake for a project and
|
||||
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
|
||||
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
|
||||
: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
|
||||
about their new policies.
|
||||
|
||||
When a version higher than 2.4 is specified the command implicitly
|
||||
When a ``<min>`` version higher than 2.4 is specified the command
|
||||
implicitly invokes::
|
||||
|
||||
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::
|
||||
|
||||
cmake_policy(VERSION major[.minor[.patch[.tweak]]])
|
||||
|
||||
which sets the cmake policy version level to the version specified.
|
||||
When 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.
|
||||
|
@ -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
|
||||
encourage projects to set policies based on CMake versions::
|
||||
|
||||
cmake_policy(VERSION major.minor[.patch[.tweak]])
|
||||
cmake_policy(VERSION <min>[...<max>])
|
||||
|
||||
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
|
||||
``<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).
|
||||
This effectively requests behavior preferred as of a given CMake
|
||||
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)`
|
||||
command implicitly calls ``cmake_policy(VERSION)`` too.
|
||||
|
8
Help/release/dev/policy-version-range.rst
Normal file
8
Help/release/dev/policy-version-range.rst
Normal file
@ -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.
|
@ -1,7 +1,5 @@
|
||||
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.
|
||||
|
@ -1002,7 +1002,8 @@ int cmCPackGenerator::DoPackage()
|
||||
{ // scope that enables package generators to run internal scripts with
|
||||
// latest CMake policies enabled
|
||||
cmMakefile::ScopePushPop pp{ this->MakefileMap };
|
||||
this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion());
|
||||
this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion(),
|
||||
std::string());
|
||||
|
||||
if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
|
||||
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"
|
||||
|
@ -45,9 +45,24 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
|
||||
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.
|
||||
this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
|
||||
version_string.c_str());
|
||||
version_min.c_str());
|
||||
|
||||
// Get the current version number.
|
||||
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_patch = 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) {
|
||||
std::ostringstream e;
|
||||
e << "could not parse VERSION \"" << version_string << "\".";
|
||||
e << "could not parse VERSION \"" << version_min << "\".";
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
@ -78,7 +93,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
|
||||
current_patch == required_patch && current_tweak < required_tweak)) {
|
||||
// The current version is too low.
|
||||
std::ostringstream e;
|
||||
e << "CMake " << version_string
|
||||
e << "CMake " << version_min
|
||||
<< " or higher is required. You are running version "
|
||||
<< cmVersion::GetCMakeVersion();
|
||||
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
@ -95,9 +110,9 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
|
||||
this->Makefile->IssueMessage(
|
||||
cmake::AUTHOR_WARNING,
|
||||
"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 {
|
||||
this->Makefile->SetPolicyVersion(version_string.c_str());
|
||||
this->Makefile->SetPolicyVersion(version_min, version_max);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -156,6 +156,23 @@ bool cmCMakePolicyCommand::HandleVersionMode(
|
||||
this->SetError("VERSION given too many arguments");
|
||||
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;
|
||||
}
|
||||
|
@ -1464,7 +1464,7 @@ void cmMakefile::Configure()
|
||||
this->SetCheckCMP0000(true);
|
||||
|
||||
// Implicitly set the version for the user.
|
||||
this->SetPolicyVersion("2.4");
|
||||
this->SetPolicyVersion("2.4", std::string());
|
||||
}
|
||||
}
|
||||
bool hasProject = false;
|
||||
@ -4149,9 +4149,10 @@ void cmMakefile::PopSnapshot(bool reportError)
|
||||
assert(this->StateSnapshot.IsValid());
|
||||
}
|
||||
|
||||
bool cmMakefile::SetPolicyVersion(std::string const& version_min)
|
||||
bool cmMakefile::SetPolicyVersion(std::string const& version_min,
|
||||
std::string const& version_max)
|
||||
{
|
||||
return cmPolicies::ApplyPolicyVersion(this, version_min);
|
||||
return cmPolicies::ApplyPolicyVersion(this, version_min, version_max);
|
||||
}
|
||||
|
||||
bool cmMakefile::HasCMP0054AlreadyBeenReported(
|
||||
|
@ -285,7 +285,8 @@ public:
|
||||
bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
|
||||
bool SetPolicy(const char* id, cmPolicies::PolicyStatus status);
|
||||
cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id) const;
|
||||
bool SetPolicyVersion(std::string const& version_min);
|
||||
bool SetPolicyVersion(std::string const& version_min,
|
||||
std::string const& version_max);
|
||||
void RecordPolicies(cmPolicies::PolicyMap& pm);
|
||||
//@}
|
||||
|
||||
|
@ -154,7 +154,8 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy,
|
||||
}
|
||||
|
||||
bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf,
|
||||
std::string const& version_min)
|
||||
std::string const& version_min,
|
||||
std::string const& version_max)
|
||||
{
|
||||
// Parse components of the minimum version.
|
||||
unsigned int minMajor = 2;
|
||||
@ -205,6 +206,42 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,8 @@ public:
|
||||
|
||||
///! Set a policy level for this listfile
|
||||
static bool ApplyPolicyVersion(cmMakefile* mf,
|
||||
std::string const& version_min);
|
||||
std::string const& version_min,
|
||||
std::string const& version_max);
|
||||
static bool ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
|
||||
unsigned int minorVer, unsigned int patchVer);
|
||||
|
||||
|
@ -612,7 +612,7 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile,
|
||||
auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
|
||||
// The OLD/WARN behavior for policy CMP0053 caused a speed regression.
|
||||
// https://gitlab.kitware.com/cmake/cmake/issues/17570
|
||||
makefile->SetPolicyVersion("3.9");
|
||||
makefile->SetPolicyVersion("3.9", std::string());
|
||||
gg.SetCurrentMakefile(makefile.get());
|
||||
success = this->Init(makefile.get());
|
||||
}
|
||||
|
4
Tests/RunCMake/cmake_minimum_required/Range-stderr.txt
Normal file
4
Tests/RunCMake/cmake_minimum_required/Range-stderr.txt
Normal file
@ -0,0 +1,4 @@
|
||||
^CMAKE_MINIMUM_REQUIRED_VERSION='3\.10'
|
||||
CMP0071='NEW'
|
||||
CMP0072='NEW'
|
||||
CMP0073=''$
|
6
Tests/RunCMake/cmake_minimum_required/Range.cmake
Normal file
6
Tests/RunCMake/cmake_minimum_required/Range.cmake
Normal file
@ -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()
|
@ -0,0 +1 @@
|
||||
1
|
56
Tests/RunCMake/cmake_minimum_required/RangeBad-stderr.txt
Normal file
56
Tests/RunCMake/cmake_minimum_required/RangeBad-stderr.txt
Normal file
@ -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
Tests/RunCMake/cmake_minimum_required/RangeBad.cmake
Normal file
10
Tests/RunCMake/cmake_minimum_required/RangeBad.cmake
Normal file
@ -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)
|
@ -3,3 +3,5 @@ include(RunCMake)
|
||||
run_cmake(Before24)
|
||||
run_cmake(CompatBefore24)
|
||||
run_cmake(PolicyBefore24)
|
||||
run_cmake(Range)
|
||||
run_cmake(RangeBad)
|
||||
|
Loading…
Reference in New Issue
Block a user