cmIncludeDirectoryCommand.cxx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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 "cmIncludeDirectoryCommand.h"
  4. #include <algorithm>
  5. #include <set>
  6. #include "cmMakefile.h"
  7. #include "cmSystemTools.h"
  8. class cmExecutionStatus;
  9. // cmIncludeDirectoryCommand
  10. bool cmIncludeDirectoryCommand::InitialPass(
  11. std::vector<std::string> const& args, cmExecutionStatus&)
  12. {
  13. if (args.empty()) {
  14. return true;
  15. }
  16. std::vector<std::string>::const_iterator i = args.begin();
  17. bool before = this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_BEFORE");
  18. bool system = false;
  19. if ((*i) == "BEFORE") {
  20. before = true;
  21. ++i;
  22. } else if ((*i) == "AFTER") {
  23. before = false;
  24. ++i;
  25. }
  26. std::vector<std::string> beforeIncludes;
  27. std::vector<std::string> afterIncludes;
  28. std::set<std::string> systemIncludes;
  29. for (; i != args.end(); ++i) {
  30. if (*i == "SYSTEM") {
  31. system = true;
  32. continue;
  33. }
  34. if (i->empty()) {
  35. this->SetError("given empty-string as include directory.");
  36. return false;
  37. }
  38. std::vector<std::string> includes;
  39. this->GetIncludes(*i, includes);
  40. if (before) {
  41. beforeIncludes.insert(beforeIncludes.end(), includes.begin(),
  42. includes.end());
  43. } else {
  44. afterIncludes.insert(afterIncludes.end(), includes.begin(),
  45. includes.end());
  46. }
  47. if (system) {
  48. systemIncludes.insert(includes.begin(), includes.end());
  49. }
  50. }
  51. std::reverse(beforeIncludes.begin(), beforeIncludes.end());
  52. this->Makefile->AddIncludeDirectories(afterIncludes);
  53. this->Makefile->AddIncludeDirectories(beforeIncludes, before);
  54. this->Makefile->AddSystemIncludeDirectories(systemIncludes);
  55. return true;
  56. }
  57. static bool StartsWithGeneratorExpression(const std::string& input)
  58. {
  59. return input[0] == '$' && input[1] == '<';
  60. }
  61. // do a lot of cleanup on the arguments because this is one place where folks
  62. // sometimes take the output of a program and pass it directly into this
  63. // command not thinking that a single argument could be filled with spaces
  64. // and newlines etc like below:
  65. //
  66. // " /foo/bar
  67. // /boo/hoo /dingle/berry "
  68. //
  69. // ideally that should be three separate arguments but when sucking the
  70. // output from a program and passing it into a command the cleanup doesn't
  71. // always happen
  72. //
  73. void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg,
  74. std::vector<std::string>& incs)
  75. {
  76. // break apart any line feed arguments
  77. std::string::size_type pos = 0;
  78. std::string::size_type lastPos = 0;
  79. while ((pos = arg.find('\n', lastPos)) != std::string::npos) {
  80. if (pos) {
  81. std::string inc = arg.substr(lastPos, pos);
  82. this->NormalizeInclude(inc);
  83. if (!inc.empty()) {
  84. incs.push_back(std::move(inc));
  85. }
  86. }
  87. lastPos = pos + 1;
  88. }
  89. std::string inc = arg.substr(lastPos);
  90. this->NormalizeInclude(inc);
  91. if (!inc.empty()) {
  92. incs.push_back(std::move(inc));
  93. }
  94. }
  95. void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc)
  96. {
  97. std::string::size_type b = inc.find_first_not_of(" \r");
  98. std::string::size_type e = inc.find_last_not_of(" \r");
  99. if ((b != std::string::npos) && (e != std::string::npos)) {
  100. inc.assign(inc, b, 1 + e - b); // copy the remaining substring
  101. } else {
  102. inc.clear();
  103. return;
  104. }
  105. if (!cmSystemTools::IsOff(inc.c_str())) {
  106. cmSystemTools::ConvertToUnixSlashes(inc);
  107. if (!cmSystemTools::FileIsFullPath(inc)) {
  108. if (!StartsWithGeneratorExpression(inc)) {
  109. std::string tmp = this->Makefile->GetCurrentSourceDirectory();
  110. tmp += "/";
  111. tmp += inc;
  112. inc = tmp;
  113. }
  114. }
  115. }
  116. }