cmIncludeGuardCommand.cxx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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 "cmIncludeGuardCommand.h"
  4. #include "cmExecutionStatus.h"
  5. #include "cmMakefile.h"
  6. #include "cmProperty.h"
  7. #include "cmStateDirectory.h"
  8. #include "cmStateSnapshot.h"
  9. #include "cmSystemTools.h"
  10. #include "cmake.h"
  11. namespace {
  12. enum IncludeGuardScope
  13. {
  14. VARIABLE,
  15. DIRECTORY,
  16. GLOBAL
  17. };
  18. std::string GetIncludeGuardVariableName(std::string const& filePath)
  19. {
  20. std::string result = "__INCGUARD_";
  21. #ifndef CMAKE_BOOTSTRAP
  22. result += cmSystemTools::ComputeStringMD5(filePath);
  23. #else
  24. result += cmSystemTools::MakeCidentifier(filePath);
  25. #endif
  26. result += "__";
  27. return result;
  28. }
  29. bool CheckIncludeGuardIsSet(cmMakefile* mf, std::string const& includeGuardVar)
  30. {
  31. if (mf->GetProperty(includeGuardVar)) {
  32. return true;
  33. }
  34. cmStateSnapshot dirSnapshot =
  35. mf->GetStateSnapshot().GetBuildsystemDirectoryParent();
  36. while (dirSnapshot.GetState()) {
  37. cmStateDirectory stateDir = dirSnapshot.GetDirectory();
  38. if (stateDir.GetProperty(includeGuardVar)) {
  39. return true;
  40. }
  41. dirSnapshot = dirSnapshot.GetBuildsystemDirectoryParent();
  42. }
  43. return false;
  44. }
  45. } // anonymous namespace
  46. // cmIncludeGuardCommand
  47. bool cmIncludeGuardCommand(std::vector<std::string> const& args,
  48. cmExecutionStatus& status)
  49. {
  50. if (args.size() > 1) {
  51. status.SetError(
  52. "given an invalid number of arguments. The command takes at "
  53. "most 1 argument.");
  54. return false;
  55. }
  56. IncludeGuardScope scope = VARIABLE;
  57. if (!args.empty()) {
  58. std::string const& arg = args[0];
  59. if (arg == "DIRECTORY") {
  60. scope = DIRECTORY;
  61. } else if (arg == "GLOBAL") {
  62. scope = GLOBAL;
  63. } else {
  64. status.SetError("given an invalid scope: " + arg);
  65. return false;
  66. }
  67. }
  68. std::string includeGuardVar = GetIncludeGuardVariableName(
  69. *status.GetMakefile().GetDefinition("CMAKE_CURRENT_LIST_FILE"));
  70. cmMakefile* const mf = &status.GetMakefile();
  71. switch (scope) {
  72. case VARIABLE:
  73. if (mf->IsDefinitionSet(includeGuardVar)) {
  74. status.SetReturnInvoked();
  75. return true;
  76. }
  77. mf->AddDefinitionBool(includeGuardVar, true);
  78. break;
  79. case DIRECTORY:
  80. if (CheckIncludeGuardIsSet(mf, includeGuardVar)) {
  81. status.SetReturnInvoked();
  82. return true;
  83. }
  84. mf->SetProperty(includeGuardVar, "TRUE");
  85. break;
  86. case GLOBAL:
  87. cmake* const cm = mf->GetCMakeInstance();
  88. if (cm->GetProperty(includeGuardVar)) {
  89. status.SetReturnInvoked();
  90. return true;
  91. }
  92. cm->SetProperty(includeGuardVar, "TRUE");
  93. break;
  94. }
  95. return true;
  96. }