cmSearchPath.cxx 6.7 KB

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