diff options
Diffstat (limited to 'Source/cmCMakeMinimumRequired.cxx')
-rw-r--r-- | Source/cmCMakeMinimumRequired.cxx | 115 |
1 files changed, 82 insertions, 33 deletions
diff --git a/Source/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx index 942688cee..1b03873d0 100644 --- a/Source/cmCMakeMinimumRequired.cxx +++ b/Source/cmCMakeMinimumRequired.cxx @@ -2,52 +2,73 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakeMinimumRequired.h" +#include <cstdio> #include <sstream> -#include <stdio.h> +#include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmVersion.h" -#include "cmake.h" -class cmExecutionStatus; +namespace { +bool EnforceUnknownArguments(std::string const& version_max, + std::vector<std::string> const& unknown_arguments, + cmExecutionStatus& status); +} // cmCMakeMinimumRequired -bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmCMakeMinimumRequired(std::vector<std::string> const& args, + cmExecutionStatus& status) { // Process arguments. std::string version_string; bool doing_version = false; - for (unsigned int i = 0; i < args.size(); ++i) { - if (args[i] == "VERSION") { + std::vector<std::string> unknown_arguments; + for (std::string const& arg : args) { + if (arg == "VERSION") { doing_version = true; - } else if (args[i] == "FATAL_ERROR") { + } else if (arg == "FATAL_ERROR") { if (doing_version) { - this->SetError("called with no value for VERSION."); + status.SetError("called with no value for VERSION."); return false; } doing_version = false; } else if (doing_version) { doing_version = false; - version_string = args[i]; + version_string = arg; } else { - this->UnknownArguments.push_back(args[i]); + unknown_arguments.push_back(arg); } } if (doing_version) { - this->SetError("called with no value for VERSION."); + status.SetError("called with no value for VERSION."); return false; } // Make sure there was a version to check. if (version_string.empty()) { - return this->EnforceUnknownArguments(); + return EnforceUnknownArguments(std::string(), unknown_arguments, status); + } + + // 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 + << R"(" does not have a version on both sides of "...".)"; + status.SetError(e.str()); + return false; } // Save the required version string. - this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION", - version_string.c_str()); + status.GetMakefile().AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION", + version_min); // Get the current version number. unsigned int current_major = cmVersion::GetMajorVersion(); @@ -61,11 +82,11 @@ 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 << "\"."; - this->SetError(e.str()); + e << "could not parse VERSION \"" << version_min << "\"."; + status.SetError(e.str()); return false; } @@ -78,39 +99,67 @@ 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()); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return true; } // The version is not from the future, so enforce unknown arguments. - if (!this->EnforceUnknownArguments()) { + if (!EnforceUnknownArguments(version_max, unknown_arguments, status)) { return false; } if (required_major < 2 || (required_major == 2 && required_minor < 4)) { - this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + status.GetMakefile().IssueMessage( + MessageType::AUTHOR_WARNING, "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0."); - this->Makefile->SetPolicyVersion("2.4"); + status.GetMakefile().SetPolicyVersion("2.4", version_max); } else { - this->Makefile->SetPolicyVersion(version_string.c_str()); + status.GetMakefile().SetPolicyVersion(version_min, version_max); } return true; } -bool cmCMakeMinimumRequired::EnforceUnknownArguments() +namespace { +bool EnforceUnknownArguments(std::string const& version_max, + std::vector<std::string> const& unknown_arguments, + cmExecutionStatus& status) { - if (!this->UnknownArguments.empty()) { - std::ostringstream e; - e << "called with unknown argument \"" << this->UnknownArguments[0] - << "\"."; - this->SetError(e.str()); - return false; + if (unknown_arguments.empty()) { + return true; } - return true; + + // Consider the max version if at least two components were given. + unsigned int max_major = 0; + unsigned int max_minor = 0; + unsigned int max_patch = 0; + unsigned int max_tweak = 0; + if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &max_major, &max_minor, + &max_patch, &max_tweak) >= 2) { + unsigned int current_major = cmVersion::GetMajorVersion(); + unsigned int current_minor = cmVersion::GetMinorVersion(); + unsigned int current_patch = cmVersion::GetPatchVersion(); + unsigned int current_tweak = cmVersion::GetTweakVersion(); + + if ((current_major < max_major) || + (current_major == max_major && current_minor < max_minor) || + (current_major == max_major && current_minor == max_minor && + current_patch < max_patch) || + (current_major == max_major && current_minor == max_minor && + current_patch == max_patch && current_tweak < max_tweak)) { + // A ...<max> version was given that is larger than the current + // version of CMake, so tolerate unknown arguments. + return true; + } + } + + std::ostringstream e; + e << "called with unknown argument \"" << unknown_arguments[0] << "\"."; + status.SetError(e.str()); + return false; +} } |