cmSearchPath.cxx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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 "cmSearchPath.h"
  4. #include <algorithm>
  5. #include <cassert>
  6. #include <utility>
  7. #include "cmAlgorithms.h"
  8. #include "cmFindCommon.h"
  9. #include "cmMakefile.h"
  10. #include "cmSystemTools.h"
  11. cmSearchPath::cmSearchPath(cmFindCommon* findCmd)
  12. : FC(findCmd)
  13. {
  14. }
  15. cmSearchPath::~cmSearchPath()
  16. {
  17. }
  18. void cmSearchPath::ExtractWithout(const std::set<std::string>& ignore,
  19. std::vector<std::string>& outPaths,
  20. bool clear) const
  21. {
  22. if (clear) {
  23. outPaths.clear();
  24. }
  25. for (std::string const& path : this->Paths) {
  26. if (ignore.count(path) == 0) {
  27. outPaths.push_back(path);
  28. }
  29. }
  30. }
  31. void cmSearchPath::AddPath(const std::string& path)
  32. {
  33. this->AddPathInternal(path);
  34. }
  35. void cmSearchPath::AddUserPath(const std::string& path)
  36. {
  37. assert(this->FC != nullptr);
  38. std::vector<std::string> outPaths;
  39. // We should view the registry as the target application would view
  40. // it.
  41. cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32;
  42. cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64;
  43. if (this->FC->Makefile->PlatformIs64Bit()) {
  44. view = cmSystemTools::KeyWOW64_64;
  45. other_view = cmSystemTools::KeyWOW64_32;
  46. }
  47. // Expand using the view of the target application.
  48. std::string expanded = path;
  49. cmSystemTools::ExpandRegistryValues(expanded, view);
  50. cmSystemTools::GlobDirs(expanded, outPaths);
  51. // Executables can be either 32-bit or 64-bit, so expand using the
  52. // alternative view.
  53. if (expanded != path && this->FC->CMakePathName == "PROGRAM") {
  54. expanded = path;
  55. cmSystemTools::ExpandRegistryValues(expanded, other_view);
  56. cmSystemTools::GlobDirs(expanded, outPaths);
  57. }
  58. // Process them all from the current directory
  59. for (std::string const& p : outPaths) {
  60. this->AddPathInternal(p, this->FC->Makefile->GetCurrentSourceDirectory());
  61. }
  62. }
  63. void cmSearchPath::AddCMakePath(const std::string& variable)
  64. {
  65. assert(this->FC != nullptr);
  66. // Get a path from a CMake variable.
  67. if (const char* value = this->FC->Makefile->GetDefinition(variable)) {
  68. std::vector<std::string> expanded;
  69. cmSystemTools::ExpandListArgument(value, expanded);
  70. for (std::string const& p : expanded) {
  71. this->AddPathInternal(p,
  72. this->FC->Makefile->GetCurrentSourceDirectory());
  73. }
  74. }
  75. }
  76. void cmSearchPath::AddEnvPath(const std::string& variable)
  77. {
  78. std::vector<std::string> expanded;
  79. cmSystemTools::GetPath(expanded, variable.c_str());
  80. for (std::string const& p : expanded) {
  81. this->AddPathInternal(p);
  82. }
  83. }
  84. void cmSearchPath::AddCMakePrefixPath(const std::string& variable)
  85. {
  86. assert(this->FC != nullptr);
  87. // Get a path from a CMake variable.
  88. if (const char* value = this->FC->Makefile->GetDefinition(variable)) {
  89. std::vector<std::string> expanded;
  90. cmSystemTools::ExpandListArgument(value, expanded);
  91. this->AddPrefixPaths(expanded,
  92. this->FC->Makefile->GetCurrentSourceDirectory());
  93. }
  94. }
  95. static std::string cmSearchPathStripBin(std::string const& s)
  96. {
  97. // If the path is a PREFIX/bin case then add its parent instead.
  98. if ((cmHasLiteralSuffix(s, "/bin")) || (cmHasLiteralSuffix(s, "/sbin"))) {
  99. return cmSystemTools::GetFilenamePath(s);
  100. }
  101. return s;
  102. }
  103. void cmSearchPath::AddEnvPrefixPath(const std::string& variable, bool stripBin)
  104. {
  105. std::vector<std::string> expanded;
  106. cmSystemTools::GetPath(expanded, variable.c_str());
  107. if (stripBin) {
  108. std::transform(expanded.begin(), expanded.end(), expanded.begin(),
  109. cmSearchPathStripBin);
  110. }
  111. this->AddPrefixPaths(expanded);
  112. }
  113. void cmSearchPath::AddSuffixes(const std::vector<std::string>& suffixes)
  114. {
  115. std::vector<std::string> inPaths;
  116. inPaths.swap(this->Paths);
  117. this->Paths.reserve(inPaths.size() * (suffixes.size() + 1));
  118. for (std::string& inPath : inPaths) {
  119. cmSystemTools::ConvertToUnixSlashes(inPath);
  120. // if *i is only / then do not add a //
  121. // this will get incorrectly considered a network
  122. // path on windows and cause huge delays.
  123. std::string p = inPath;
  124. if (!p.empty() && *p.rbegin() != '/') {
  125. p += "/";
  126. }
  127. // Combine with all the suffixes
  128. for (std::string const& suffix : suffixes) {
  129. this->Paths.push_back(p + suffix);
  130. }
  131. // And now the original w/o any suffix
  132. this->Paths.push_back(std::move(inPath));
  133. }
  134. }
  135. void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths,
  136. const char* base)
  137. {
  138. assert(this->FC != nullptr);
  139. // default for programs
  140. std::string subdir = "bin";
  141. if (this->FC->CMakePathName == "INCLUDE") {
  142. subdir = "include";
  143. } else if (this->FC->CMakePathName == "LIBRARY") {
  144. subdir = "lib";
  145. } else if (this->FC->CMakePathName == "FRAMEWORK") {
  146. subdir.clear(); // ? what to do for frameworks ?
  147. }
  148. for (std::string const& path : paths) {
  149. std::string dir = path;
  150. if (!subdir.empty() && !dir.empty() && *dir.rbegin() != '/') {
  151. dir += "/";
  152. }
  153. if (subdir == "include" || subdir == "lib") {
  154. const char* arch =
  155. this->FC->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE");
  156. if (arch && *arch) {
  157. this->AddPathInternal(dir + subdir + "/" + arch, base);
  158. }
  159. }
  160. std::string add = dir + subdir;
  161. if (add != "/") {
  162. this->AddPathInternal(add, base);
  163. }
  164. if (subdir == "bin") {
  165. this->AddPathInternal(dir + "sbin", base);
  166. }
  167. if (!subdir.empty() && path != "/") {
  168. this->AddPathInternal(path, base);
  169. }
  170. }
  171. }
  172. void cmSearchPath::AddPathInternal(const std::string& path, const char* base)
  173. {
  174. assert(this->FC != nullptr);
  175. std::string collapsed = cmSystemTools::CollapseFullPath(path, base);
  176. if (collapsed.empty()) {
  177. return;
  178. }
  179. // Insert the path if has not already been emitted.
  180. if (this->FC->SearchPathsEmitted.insert(collapsed).second) {
  181. this->Paths.push_back(std::move(collapsed));
  182. }
  183. }