cmCMakePolicyCommand.cxx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 "cmCMakePolicyCommand.h"
  4. #include <sstream>
  5. #include "cmMakefile.h"
  6. #include "cmMessageType.h"
  7. #include "cmPolicies.h"
  8. #include "cmState.h"
  9. #include "cmStateTypes.h"
  10. class cmExecutionStatus;
  11. // cmCMakePolicyCommand
  12. bool cmCMakePolicyCommand::InitialPass(std::vector<std::string> const& args,
  13. cmExecutionStatus&)
  14. {
  15. if (args.empty()) {
  16. this->SetError("requires at least one argument.");
  17. return false;
  18. }
  19. if (args[0] == "SET") {
  20. return this->HandleSetMode(args);
  21. }
  22. if (args[0] == "GET") {
  23. return this->HandleGetMode(args);
  24. }
  25. if (args[0] == "PUSH") {
  26. if (args.size() > 1) {
  27. this->SetError("PUSH may not be given additional arguments.");
  28. return false;
  29. }
  30. this->Makefile->PushPolicy();
  31. return true;
  32. }
  33. if (args[0] == "POP") {
  34. if (args.size() > 1) {
  35. this->SetError("POP may not be given additional arguments.");
  36. return false;
  37. }
  38. this->Makefile->PopPolicy();
  39. return true;
  40. }
  41. if (args[0] == "VERSION") {
  42. return this->HandleVersionMode(args);
  43. }
  44. if (args[0] == "GET_WARNING") {
  45. return this->HandleGetWarningMode(args);
  46. }
  47. std::ostringstream e;
  48. e << "given unknown first argument \"" << args[0] << "\"";
  49. this->SetError(e.str());
  50. return false;
  51. }
  52. bool cmCMakePolicyCommand::HandleSetMode(std::vector<std::string> const& args)
  53. {
  54. if (args.size() != 3) {
  55. this->SetError("SET must be given exactly 2 additional arguments.");
  56. return false;
  57. }
  58. cmPolicies::PolicyStatus status;
  59. if (args[2] == "OLD") {
  60. status = cmPolicies::OLD;
  61. } else if (args[2] == "NEW") {
  62. status = cmPolicies::NEW;
  63. } else {
  64. std::ostringstream e;
  65. e << "SET given unrecognized policy status \"" << args[2] << "\"";
  66. this->SetError(e.str());
  67. return false;
  68. }
  69. if (!this->Makefile->SetPolicy(args[1].c_str(), status)) {
  70. this->SetError("SET failed to set policy.");
  71. return false;
  72. }
  73. if (args[1] == "CMP0001" &&
  74. (status == cmPolicies::WARN || status == cmPolicies::OLD)) {
  75. if (!(this->Makefile->GetState()->GetInitializedCacheValue(
  76. "CMAKE_BACKWARDS_COMPATIBILITY"))) {
  77. // Set it to 2.4 because that is the last version where the
  78. // variable had meaning.
  79. this->Makefile->AddCacheDefinition(
  80. "CMAKE_BACKWARDS_COMPATIBILITY", "2.4",
  81. "For backwards compatibility, what version of CMake "
  82. "commands and "
  83. "syntax should this version of CMake try to support.",
  84. cmStateEnums::STRING);
  85. }
  86. }
  87. return true;
  88. }
  89. bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args)
  90. {
  91. bool parent_scope = false;
  92. if (args.size() == 4 && args[3] == "PARENT_SCOPE") {
  93. // Undocumented PARENT_SCOPE option for use within CMake.
  94. parent_scope = true;
  95. } else if (args.size() != 3) {
  96. this->SetError("GET must be given exactly 2 additional arguments.");
  97. return false;
  98. }
  99. // Get arguments.
  100. std::string const& id = args[1];
  101. std::string const& var = args[2];
  102. // Lookup the policy number.
  103. cmPolicies::PolicyID pid;
  104. if (!cmPolicies::GetPolicyID(id.c_str(), pid)) {
  105. std::ostringstream e;
  106. e << "GET given policy \"" << id << "\" which is not known to this "
  107. << "version of CMake.";
  108. this->SetError(e.str());
  109. return false;
  110. }
  111. // Lookup the policy setting.
  112. cmPolicies::PolicyStatus status =
  113. this->Makefile->GetPolicyStatus(pid, parent_scope);
  114. switch (status) {
  115. case cmPolicies::OLD:
  116. // Report that the policy is set to OLD.
  117. this->Makefile->AddDefinition(var, "OLD");
  118. break;
  119. case cmPolicies::WARN:
  120. // Report that the policy is not set.
  121. this->Makefile->AddDefinition(var, "");
  122. break;
  123. case cmPolicies::NEW:
  124. // Report that the policy is set to NEW.
  125. this->Makefile->AddDefinition(var, "NEW");
  126. break;
  127. case cmPolicies::REQUIRED_IF_USED:
  128. case cmPolicies::REQUIRED_ALWAYS:
  129. // The policy is required to be set before anything needs it.
  130. {
  131. std::ostringstream e;
  132. e << cmPolicies::GetRequiredPolicyError(pid) << "\n"
  133. << "The call to cmake_policy(GET " << id << " ...) at which this "
  134. << "error appears requests the policy, and this version of CMake "
  135. << "requires that the policy be set to NEW before it is checked.";
  136. this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
  137. }
  138. }
  139. return true;
  140. }
  141. bool cmCMakePolicyCommand::HandleVersionMode(
  142. std::vector<std::string> const& args)
  143. {
  144. if (args.size() <= 1) {
  145. this->SetError("VERSION not given an argument");
  146. return false;
  147. }
  148. if (args.size() >= 3) {
  149. this->SetError("VERSION given too many arguments");
  150. return false;
  151. }
  152. std::string const& version_string = args[1];
  153. // Separate the <min> version and any trailing ...<max> component.
  154. std::string::size_type const dd = version_string.find("...");
  155. std::string const version_min = version_string.substr(0, dd);
  156. std::string const version_max = dd != std::string::npos
  157. ? version_string.substr(dd + 3, std::string::npos)
  158. : std::string();
  159. if (dd != std::string::npos &&
  160. (version_min.empty() || version_max.empty())) {
  161. std::ostringstream e;
  162. e << "VERSION \"" << version_string
  163. << R"(" does not have a version on both sides of "...".)";
  164. this->SetError(e.str());
  165. return false;
  166. }
  167. this->Makefile->SetPolicyVersion(version_min, version_max);
  168. return true;
  169. }
  170. bool cmCMakePolicyCommand::HandleGetWarningMode(
  171. std::vector<std::string> const& args)
  172. {
  173. if (args.size() != 3) {
  174. this->SetError(
  175. "GET_WARNING must be given exactly 2 additional arguments.");
  176. return false;
  177. }
  178. // Get arguments.
  179. std::string const& id = args[1];
  180. std::string const& var = args[2];
  181. // Lookup the policy number.
  182. cmPolicies::PolicyID pid;
  183. if (!cmPolicies::GetPolicyID(id.c_str(), pid)) {
  184. std::ostringstream e;
  185. e << "GET_WARNING given policy \"" << id
  186. << "\" which is not known to this version of CMake.";
  187. this->SetError(e.str());
  188. return false;
  189. }
  190. // Lookup the policy warning.
  191. this->Makefile->AddDefinition(var,
  192. cmPolicies::GetPolicyWarning(pid).c_str());
  193. return true;
  194. }