cmCMakePolicyCommand.cxx 6.8 KB

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