cmIncludeDirectoryCommand.cxx 3.9 KB

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