cmCMakeMinimumRequired.cxx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmCMakeMinimumRequired.h"
  4. #include <sstream>
  5. #include <stdio.h>
  6. #include "cmMakefile.h"
  7. #include "cmSystemTools.h"
  8. #include "cmVersion.h"
  9. #include "cmake.h"
  10. class cmExecutionStatus;
  11. // cmCMakeMinimumRequired
  12. bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
  13. cmExecutionStatus&)
  14. {
  15. // Process arguments.
  16. std::string version_string;
  17. bool doing_version = false;
  18. for (std::string const& arg : args) {
  19. if (arg == "VERSION") {
  20. doing_version = true;
  21. } else if (arg == "FATAL_ERROR") {
  22. if (doing_version) {
  23. this->SetError("called with no value for VERSION.");
  24. return false;
  25. }
  26. doing_version = false;
  27. } else if (doing_version) {
  28. doing_version = false;
  29. version_string = arg;
  30. } else {
  31. this->UnknownArguments.push_back(arg);
  32. }
  33. }
  34. if (doing_version) {
  35. this->SetError("called with no value for VERSION.");
  36. return false;
  37. }
  38. // Make sure there was a version to check.
  39. if (version_string.empty()) {
  40. return this->EnforceUnknownArguments();
  41. }
  42. // Save the required version string.
  43. this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
  44. version_string.c_str());
  45. // Get the current version number.
  46. unsigned int current_major = cmVersion::GetMajorVersion();
  47. unsigned int current_minor = cmVersion::GetMinorVersion();
  48. unsigned int current_patch = cmVersion::GetPatchVersion();
  49. unsigned int current_tweak = cmVersion::GetTweakVersion();
  50. // Parse at least two components of the version number.
  51. // Use zero for those not specified.
  52. unsigned int required_major = 0;
  53. unsigned int required_minor = 0;
  54. unsigned int required_patch = 0;
  55. unsigned int required_tweak = 0;
  56. if (sscanf(version_string.c_str(), "%u.%u.%u.%u", &required_major,
  57. &required_minor, &required_patch, &required_tweak) < 2) {
  58. std::ostringstream e;
  59. e << "could not parse VERSION \"" << version_string << "\".";
  60. this->SetError(e.str());
  61. return false;
  62. }
  63. // Compare the version numbers.
  64. if ((current_major < required_major) ||
  65. (current_major == required_major && current_minor < required_minor) ||
  66. (current_major == required_major && current_minor == required_minor &&
  67. current_patch < required_patch) ||
  68. (current_major == required_major && current_minor == required_minor &&
  69. current_patch == required_patch && current_tweak < required_tweak)) {
  70. // The current version is too low.
  71. std::ostringstream e;
  72. e << "CMake " << version_string
  73. << " or higher is required. You are running version "
  74. << cmVersion::GetCMakeVersion();
  75. this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
  76. cmSystemTools::SetFatalErrorOccured();
  77. return true;
  78. }
  79. // The version is not from the future, so enforce unknown arguments.
  80. if (!this->EnforceUnknownArguments()) {
  81. return false;
  82. }
  83. if (required_major < 2 || (required_major == 2 && required_minor < 4)) {
  84. this->Makefile->IssueMessage(
  85. cmake::AUTHOR_WARNING,
  86. "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.");
  87. this->Makefile->SetPolicyVersion("2.4");
  88. } else {
  89. this->Makefile->SetPolicyVersion(version_string.c_str());
  90. }
  91. return true;
  92. }
  93. bool cmCMakeMinimumRequired::EnforceUnknownArguments()
  94. {
  95. if (!this->UnknownArguments.empty()) {
  96. std::ostringstream e;
  97. e << "called with unknown argument \"" << this->UnknownArguments[0]
  98. << "\".";
  99. this->SetError(e.str());
  100. return false;
  101. }
  102. return true;
  103. }