cmPolicies.cxx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. #include "cmPolicies.h"
  2. #include "cmake.h"
  3. #include "cmMakefile.h"
  4. #include "cmSourceFile.h"
  5. #include <map>
  6. #include <set>
  7. #include <queue>
  8. #include <assert.h>
  9. const char* cmPolicies::PolicyStatusNames[] = {
  10. "OLD", "WARN", "NEW", "REQUIRED_IF_USED", "REQUIRED_ALWAYS"
  11. };
  12. class cmPolicy
  13. {
  14. public:
  15. cmPolicy(cmPolicies::PolicyID iD,
  16. const char *idString,
  17. const char *shortDescription,
  18. const char *longDescription,
  19. unsigned int majorVersionIntroduced,
  20. unsigned int minorVersionIntroduced,
  21. unsigned int patchVersionIntroduced,
  22. cmPolicies::PolicyStatus status)
  23. {
  24. if (!idString || !shortDescription || ! longDescription)
  25. {
  26. cmSystemTools::Error("Attempt to define a policy without "
  27. "all parameters being specified!");
  28. return;
  29. }
  30. this->ID = iD;
  31. this->IDString = idString;
  32. this->ShortDescription = shortDescription;
  33. this->LongDescription = longDescription;
  34. this->MajorVersionIntroduced = majorVersionIntroduced;
  35. this->MinorVersionIntroduced = minorVersionIntroduced;
  36. this->PatchVersionIntroduced = patchVersionIntroduced;
  37. this->Status = status;
  38. }
  39. std::string GetVersionString()
  40. {
  41. cmOStringStream error;
  42. error << this->MajorVersionIntroduced << "." <<
  43. this->MinorVersionIntroduced << "." <<
  44. this->PatchVersionIntroduced;
  45. return error.str();
  46. }
  47. bool IsPolicyNewerThan(unsigned int majorV,
  48. unsigned int minorV,
  49. unsigned int patchV)
  50. {
  51. if (majorV < this->MajorVersionIntroduced)
  52. {
  53. return true;
  54. }
  55. if (majorV > this->MajorVersionIntroduced)
  56. {
  57. return false;
  58. }
  59. if (minorV < this->MinorVersionIntroduced)
  60. {
  61. return true;
  62. }
  63. if (minorV > this->MinorVersionIntroduced)
  64. {
  65. return false;
  66. }
  67. return (patchV < this->PatchVersionIntroduced);
  68. }
  69. cmPolicies::PolicyID ID;
  70. std::string IDString;
  71. std::string ShortDescription;
  72. std::string LongDescription;
  73. unsigned int MajorVersionIntroduced;
  74. unsigned int MinorVersionIntroduced;
  75. unsigned int PatchVersionIntroduced;
  76. cmPolicies::PolicyStatus Status;
  77. };
  78. cmPolicies::cmPolicies()
  79. {
  80. // define all the policies
  81. this->DefinePolicy(CMP_0000, "CMP_0000",
  82. "Missing a CMake version specification. You must have a cmake_policy "
  83. "call.",
  84. "CMake requires that projects specify what version of CMake they have "
  85. "been written to. The easiest way to do this is by placing a call to "
  86. "cmake_policy at the top of your CMakeLists file. For example: "
  87. "cmake_policy(VERSION 2.6) Replace "
  88. "2.6 in that example with the verison of CMake you are writing to. "
  89. "This policy is being put in place because it aids us in detecting "
  90. "and maintaining backwards compatibility.",
  91. 2,6,0, cmPolicies::WARN);
  92. // this->PolicyStringMap["CMP_POLICY_SPECIFICATION"] = CMP_0000;
  93. this->DefinePolicy(CMP_0001, "CMP_0001",
  94. "CMake does not allow target names to include slash characters.",
  95. "CMake requires that target names not include any / or \\ characters "
  96. "please change the name of any targets to not use such characters."
  97. ,
  98. 2,4,0, cmPolicies::REQUIRED_IF_USED);
  99. // this->PolicyStringMap["CMP_TARGET_NAMES_WITH_SLASHES"] = CMP_0001;
  100. this->DefinePolicy(CMP_0002, "CMP_0002",
  101. "CMake requires that target names be globaly unique.",
  102. "CMake requires that target names not include any / or \\ characters "
  103. "please change the name of any targets to not use such characters."
  104. ,
  105. 2,6,0, cmPolicies::WARN);
  106. // this->PolicyStringMap["CMP_REQUIRE_UNIQUE_TARGET_NAMES"] = CMP_0002;
  107. this->DefinePolicy(CMP_0003, "CMP_0003",
  108. "CMake configures file immediately after 2.0.",
  109. "In CMake 2.0 and earlier the configure_file command would not "
  110. "configure the file until after processing all CMakeLists files. "
  111. "In CMake 2.2 and later the default behavior is that it will "
  112. "configure the file right when the command is invoked."
  113. ,
  114. 2,6,0, cmPolicies::NEW);
  115. // this->PolicyStringMap["CMP_CONFIGURE_FILE_IMMEDIATE"] = CMP_0003;
  116. }
  117. cmPolicies::~cmPolicies()
  118. {
  119. // free the policies
  120. std::map<cmPolicies::PolicyID,cmPolicy *>::iterator i
  121. = this->Policies.begin();
  122. for (;i != this->Policies.end(); ++i)
  123. {
  124. delete i->second;
  125. }
  126. }
  127. void cmPolicies::DefinePolicy(cmPolicies::PolicyID iD,
  128. const char *idString,
  129. const char *shortDescription,
  130. const char *longDescription,
  131. unsigned int majorVersionIntroduced,
  132. unsigned int minorVersionIntroduced,
  133. unsigned int patchVersionIntroduced,
  134. cmPolicies::PolicyStatus status)
  135. {
  136. // a policy must be unique and can only be defined once
  137. if (this->Policies.find(iD) != this->Policies.end())
  138. {
  139. cmSystemTools::Error("Attempt to redefine a CMake policy for policy "
  140. "ID ", this->GetPolicyIDString(iD).c_str());
  141. return;
  142. }
  143. this->Policies[iD] = new cmPolicy(iD, idString,
  144. shortDescription,
  145. longDescription,
  146. majorVersionIntroduced,
  147. minorVersionIntroduced,
  148. patchVersionIntroduced,
  149. status);
  150. this->PolicyStringMap[idString] = iD;
  151. }
  152. bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf,
  153. const char *version)
  154. {
  155. std::string ver = "2.4.0";
  156. if (version && strlen(version) > 0)
  157. {
  158. ver = version;
  159. }
  160. unsigned int majorVer = 2;
  161. unsigned int minorVer = 0;
  162. unsigned int patchVer = 0;
  163. // parse the string
  164. if(sscanf(ver.c_str(), "%u.%u.%u",
  165. &majorVer, &minorVer, &patchVer) < 2)
  166. {
  167. return false;
  168. }
  169. // now loop over all the policies and set them as appropriate
  170. std::map<cmPolicies::PolicyID,cmPolicy *>::iterator i
  171. = this->Policies.begin();
  172. for (;i != this->Policies.end(); ++i)
  173. {
  174. if (i->second->IsPolicyNewerThan(majorVer,minorVer,patchVer))
  175. {
  176. if (!mf->SetPolicy(i->second->ID, cmPolicies::WARN))
  177. {
  178. return false;
  179. }
  180. }
  181. else
  182. {
  183. if (!mf->SetPolicy(i->second->ID, cmPolicies::NEW))
  184. {
  185. return false;
  186. }
  187. }
  188. }
  189. return true;
  190. }
  191. // is this a valid status the listfile can set this policy to?
  192. bool cmPolicies::IsValidPolicyStatus(cmPolicies::PolicyID id,
  193. cmPolicies::PolicyStatus status)
  194. {
  195. // if they are setting a feature to anything other than OLD or WARN and the
  196. // feature is not known about then that is an error
  197. if (this->Policies.find(id) == this->Policies.end())
  198. {
  199. if (status == cmPolicies::WARN ||
  200. status == cmPolicies::OLD)
  201. {
  202. return true;
  203. }
  204. cmOStringStream error;
  205. error <<
  206. "Error: an attempt was made to enable the new behavior for " <<
  207. "a new feature that is in a later version of CMake than "
  208. "what you are runing, please upgrade to a newer version "
  209. "of CMake.";
  210. cmSystemTools::Error(error.str().c_str());
  211. return false;
  212. }
  213. // now we know the feature is defined, so the only issue is if someone is
  214. // setting it to WARN or OLD when the feature is REQUIRED_ALWAYS
  215. if ((status == cmPolicies::WARN ||
  216. status == cmPolicies::OLD) &&
  217. this->Policies[id]->Status == cmPolicies::REQUIRED_ALWAYS)
  218. {
  219. cmOStringStream error;
  220. error <<
  221. "Error: an attempt was made to enable the old behavior for " <<
  222. "a feature that is no longer supported. The feature in " <<
  223. "question is feature " <<
  224. id <<
  225. " which had new behavior introduced in CMake version " <<
  226. this->Policies[id]->GetVersionString() <<
  227. " please either update your CMakeLists files to conform to " <<
  228. "the new behavior " <<
  229. "or use an older version of CMake that still supports " <<
  230. "the old behavior. Run cmake --help-policies " <<
  231. id << " for more information.";
  232. cmSystemTools::Error(error.str().c_str());
  233. return false;
  234. }
  235. return true;
  236. }
  237. // is this a valid status the listfile can set this policy to?
  238. bool cmPolicies::IsValidUsedPolicyStatus(cmPolicies::PolicyID id,
  239. cmPolicies::PolicyStatus status)
  240. {
  241. // if they are setting a feature to anything other than OLD or WARN and the
  242. // feature is not known about then that is an error
  243. if (this->Policies.find(id) == this->Policies.end())
  244. {
  245. if (status == cmPolicies::WARN ||
  246. status == cmPolicies::OLD)
  247. {
  248. return true;
  249. }
  250. cmOStringStream error;
  251. error <<
  252. "Error: an attempt was made to enable the new behavior for " <<
  253. "a new feature that is in a later version of CMake than "
  254. "what you are runing, please upgrade to a newer version "
  255. "of CMake.";
  256. cmSystemTools::Error(error.str().c_str());
  257. return false;
  258. }
  259. // now we know the feature is defined, so the only issue is if someone is
  260. // setting it to WARN or OLD when the feature is REQUIRED_ALWAYS
  261. if ((status == cmPolicies::WARN ||
  262. status == cmPolicies::OLD) &&
  263. (this->Policies[id]->Status == cmPolicies::REQUIRED_ALWAYS ||
  264. this->Policies[id]->Status == cmPolicies::REQUIRED_IF_USED))
  265. {
  266. cmOStringStream error;
  267. error <<
  268. "Error: an attempt was made to enable the old behavior for " <<
  269. "a feature that is no longer supported. The feature in " <<
  270. "question is feature " <<
  271. id <<
  272. " which had new behavior introduced in CMake version " <<
  273. this->Policies[id]->GetVersionString() <<
  274. " please either update your CMakeLists files to conform to " <<
  275. "the new behavior " <<
  276. "or use an older version of CMake that still supports " <<
  277. "the old behavior. Run cmake --help-policies " <<
  278. id << " for more information.";
  279. cmSystemTools::Error(error.str().c_str());
  280. return false;
  281. }
  282. return true;
  283. }
  284. bool cmPolicies::GetPolicyID(const char *id, cmPolicies::PolicyID &pid)
  285. {
  286. if (!id || strlen(id) < 1)
  287. {
  288. return false;
  289. }
  290. std::map<std::string,cmPolicies::PolicyID>::iterator pos =
  291. this->PolicyStringMap.find(id);
  292. if (pos == this->PolicyStringMap.end())
  293. {
  294. return false;
  295. }
  296. pid = pos->second;
  297. return true;
  298. }
  299. std::string cmPolicies::GetPolicyIDString(cmPolicies::PolicyID pid)
  300. {
  301. std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos =
  302. this->Policies.find(pid);
  303. if (pos == this->Policies.end())
  304. {
  305. return "";
  306. }
  307. return pos->second->IDString;
  308. }
  309. ///! return a warning string for a given policy
  310. std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id)
  311. {
  312. std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos =
  313. this->Policies.find(id);
  314. if (pos == this->Policies.end())
  315. {
  316. cmSystemTools::Error(
  317. "Request for warning text for undefined policy!");
  318. return "Request for warning text for undefined policy!";
  319. }
  320. cmOStringStream msg;
  321. msg <<
  322. "Policy " << pos->second->IDString << " is not set: "
  323. "" << pos->second->ShortDescription << "\n"
  324. "Run \"cmake --help-policy " << pos->second->IDString << "\" for "
  325. "policy details.\n"
  326. "Use the cmake_policy command to set the policy "
  327. "and suppress this warning.";
  328. return msg.str();
  329. }
  330. ///! return an error string for when a required policy is unspecified
  331. std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id)
  332. {
  333. std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos =
  334. this->Policies.find(id);
  335. if (pos == this->Policies.end())
  336. {
  337. cmSystemTools::Error(
  338. "Request for error text for undefined policy!");
  339. return "Request for warning text for undefined policy!";
  340. }
  341. cmOStringStream error;
  342. error <<
  343. "Policy " << pos->second->IDString << " is not set to NEW: "
  344. "" << pos->second->ShortDescription << "\n"
  345. "Run \"cmake --help-policy " << pos->second->IDString << "\" for "
  346. "policy details.\n"
  347. "CMake now requires this policy to be set to NEW by the project. "
  348. "The policy may be set explicitly using the code\n"
  349. " cmake_policy(SET " << pos->second->IDString << " NEW)\n"
  350. "or by upgrading all policies with the code\n"
  351. " cmake_policy(VERSION " << pos->second->GetVersionString() <<
  352. ") # or later\n"
  353. "Run \"cmake --help-command cmake_policy\" for more information.";
  354. return error.str();
  355. }
  356. ///! Get the default status for a policy
  357. cmPolicies::PolicyStatus
  358. cmPolicies::GetPolicyStatus(cmPolicies::PolicyID id)
  359. {
  360. // if the policy is not know then what?
  361. std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos =
  362. this->Policies.find(id);
  363. if (pos == this->Policies.end())
  364. {
  365. // TODO is this right?
  366. return cmPolicies::WARN;
  367. }
  368. return pos->second->Status;
  369. }
  370. void cmPolicies::GetDocumentation(std::vector<cmDocumentationEntry>& v)
  371. {
  372. // now loop over all the policies and set them as appropriate
  373. std::map<cmPolicies::PolicyID,cmPolicy *>::iterator i
  374. = this->Policies.begin();
  375. for (;i != this->Policies.end(); ++i)
  376. {
  377. std::string full;
  378. full += i->second->LongDescription;
  379. full += "\nThis policy was introduced in CMake version ";
  380. full += i->second->GetVersionString();
  381. full += ". The version of CMake you are running ";
  382. // add in some more text here based on status
  383. switch (i->second->Status)
  384. {
  385. case cmPolicies::WARN:
  386. full += "defaults to warning about this policy. You can either "
  387. "suppress the warning without fixing the issue by adding a "
  388. "cmake_policy(SET ";
  389. full += i->second->IDString;
  390. full += " OLD) command to the top of your CMakeLists file or "
  391. "you can change your code to use the new behavior and add "
  392. "cmake_policy(SET ";
  393. full += i->second->IDString;
  394. full += " NEW) to your CMakeList file. If you are fixing all "
  395. "issues with a new version of CMake you can add "
  396. "cmake_policy(VERSION #.#) where #.# is the verison of CMake "
  397. "you are updating to. This will tell CMake that you have fixed "
  398. "all issues to use the new behavior.";
  399. case cmPolicies::OLD:
  400. full += "defaults to the old behavior for this policy.";
  401. break;
  402. case cmPolicies::NEW:
  403. full += "defaults to the new behavior for this policy.";
  404. break;
  405. case cmPolicies::REQUIRED_IF_USED:
  406. full += "requires the new behavior for this policy."
  407. "if you usee it.";
  408. break;
  409. case cmPolicies::REQUIRED_ALWAYS:
  410. full += "requires the new behavior for this policy.";
  411. break;
  412. }
  413. cmDocumentationEntry e(i->second->IDString.c_str(),
  414. i->second->ShortDescription.c_str(),
  415. full.c_str());
  416. v.push_back(e);
  417. }
  418. }