/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakeMinimumRequired.h" #include #include #include "cmMakefile.h" #include "cmMessageType.h" #include "cmSystemTools.h" #include "cmVersion.h" class cmExecutionStatus; // cmCMakeMinimumRequired bool cmCMakeMinimumRequired::InitialPass(std::vector const& args, cmExecutionStatus&) { // Process arguments. std::string version_string; bool doing_version = false; for (std::string const& arg : args) { if (arg == "VERSION") { doing_version = true; } else if (arg == "FATAL_ERROR") { if (doing_version) { this->SetError("called with no value for VERSION."); return false; } doing_version = false; } else if (doing_version) { doing_version = false; version_string = arg; } else { this->UnknownArguments.push_back(arg); } } if (doing_version) { this->SetError("called with no value for VERSION."); return false; } // Make sure there was a version to check. if (version_string.empty()) { return this->EnforceUnknownArguments(std::string()); } // Separate the version and any trailing ... 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 "...".)"; this->SetError(e.str()); return false; } // Save the required version string. this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION", version_min.c_str()); // Get the current version number. unsigned int current_major = cmVersion::GetMajorVersion(); unsigned int current_minor = cmVersion::GetMinorVersion(); unsigned int current_patch = cmVersion::GetPatchVersion(); unsigned int current_tweak = cmVersion::GetTweakVersion(); // Parse at least two components of the version number. // Use zero for those not specified. unsigned int required_major = 0; unsigned int required_minor = 0; unsigned int required_patch = 0; unsigned int required_tweak = 0; 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_min << "\"."; this->SetError(e.str()); return false; } // Compare the version numbers. if ((current_major < required_major) || (current_major == required_major && current_minor < required_minor) || (current_major == required_major && current_minor == required_minor && current_patch < required_patch) || (current_major == required_major && current_minor == required_minor && current_patch == required_patch && current_tweak < required_tweak)) { // The current version is too low. std::ostringstream e; e << "CMake " << version_min << " or higher is required. You are running version " << cmVersion::GetCMakeVersion(); this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return true; } // The version is not from the future, so enforce unknown arguments. if (!this->EnforceUnknownArguments(version_max)) { return false; } if (required_major < 2 || (required_major == 2 && required_minor < 4)) { this->Makefile->IssueMessage( MessageType::AUTHOR_WARNING, "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0."); this->Makefile->SetPolicyVersion("2.4", version_max); } else { this->Makefile->SetPolicyVersion(version_min, version_max); } return true; } bool cmCMakeMinimumRequired::EnforceUnknownArguments( std::string const& version_max) { if (this->UnknownArguments.empty()) { 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 ... 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 \"" << this->UnknownArguments[0] << "\"."; this->SetError(e.str()); return false; }