cmFindCommon.cxx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmFindCommon.h"
  14. //----------------------------------------------------------------------------
  15. cmFindCommon::cmFindCommon()
  16. {
  17. this->FindRootPathMode = RootPathModeBoth;
  18. this->NoDefaultPath = false;
  19. this->NoCMakePath = false;
  20. this->NoCMakeEnvironmentPath = false;
  21. this->NoSystemEnvironmentPath = false;
  22. this->NoCMakeSystemPath = false;
  23. // OS X Bundle and Framework search policy. The default is to
  24. // search frameworks first on apple.
  25. #if defined(__APPLE__)
  26. this->SearchFrameworkFirst = true;
  27. this->SearchAppBundleFirst = true;
  28. #else
  29. this->SearchFrameworkFirst = false;
  30. this->SearchAppBundleFirst = false;
  31. #endif
  32. this->SearchFrameworkOnly = false;
  33. this->SearchFrameworkLast = false;
  34. this->SearchAppBundleOnly = false;
  35. this->SearchAppBundleLast = false;
  36. // Documentation components.
  37. this->GenericDocumentationMacPolicy =
  38. "On Darwin or systems supporting OS X Frameworks, the cmake variable"
  39. " CMAKE_FIND_FRAMEWORK can be set to empty or one of the following:\n"
  40. " \"FIRST\" - Try to find frameworks before standard\n"
  41. " libraries or headers. This is the default on Darwin.\n"
  42. " \"LAST\" - Try to find frameworks after standard\n"
  43. " libraries or headers.\n"
  44. " \"ONLY\" - Only try to find frameworks.\n"
  45. " \"NEVER\". - Never try to find frameworks.\n"
  46. "On Darwin or systems supporting OS X Application Bundles, the cmake "
  47. "variable CMAKE_FIND_APPBUNDLE can be set to empty or one of the "
  48. "following:\n"
  49. " \"FIRST\" - Try to find application bundles before standard\n"
  50. " programs. This is the default on Darwin.\n"
  51. " \"LAST\" - Try to find application bundles after standard\n"
  52. " programs.\n"
  53. " \"ONLY\" - Only try to find application bundles.\n"
  54. " \"NEVER\". - Never try to find application bundles.\n";
  55. this->GenericDocumentationRootPath =
  56. "The CMake variable CMAKE_FIND_ROOT_PATH specifies one or more "
  57. "directories to be prepended to all other search directories. "
  58. "This effectively \"re-roots\" the entire search under given locations. "
  59. "By default it is empty. It is especially useful when "
  60. "cross-compiling to point to the root directory of the "
  61. "target environment and CMake will search there too. By default at first "
  62. "the directories listed in CMAKE_FIND_ROOT_PATH and then the non-rooted "
  63. "directories will be searched. "
  64. "The default behavior can be adjusted by setting "
  65. "CMAKE_FIND_ROOT_PATH_MODE_XXX. This behavior can be manually "
  66. "overridden on a per-call basis. "
  67. "By using CMAKE_FIND_ROOT_PATH_BOTH the search order will "
  68. "be as described above. If NO_CMAKE_FIND_ROOT_PATH is used "
  69. "then CMAKE_FIND_ROOT_PATH will not be used. If ONLY_CMAKE_FIND_ROOT_PATH "
  70. "is used then only the re-rooted directories will be searched.\n";
  71. this->GenericDocumentationPathsOrder =
  72. "The reason the paths listed in the call to the command are searched "
  73. "last is that most users of CMake would expect things to be found "
  74. "first in the locations specified by their environment. Projects may "
  75. "override this behavior by simply calling the command twice:\n"
  76. " FIND_XXX(FIND_ARGS_XXX PATHS paths... NO_DEFAULT_PATH)\n"
  77. " FIND_XXX(FIND_ARGS_XXX)\n"
  78. "Once one of these calls succeeds the result variable will be set "
  79. "and stored in the cache so that neither call will search again.";
  80. }
  81. //----------------------------------------------------------------------------
  82. cmFindCommon::~cmFindCommon()
  83. {
  84. }
  85. //----------------------------------------------------------------------------
  86. void cmFindCommon::SelectDefaultRootPathMode()
  87. {
  88. // Use both by default.
  89. this->FindRootPathMode = RootPathModeBoth;
  90. // Check the policy variable for this find command type.
  91. std::string findRootPathVar = "CMAKE_FIND_ROOT_PATH_MODE_";
  92. findRootPathVar += this->CMakePathName;
  93. std::string rootPathMode =
  94. this->Makefile->GetSafeDefinition(findRootPathVar.c_str());
  95. if (rootPathMode=="NEVER")
  96. {
  97. this->FindRootPathMode = RootPathModeNoRootPath;
  98. }
  99. else if (rootPathMode=="ONLY")
  100. {
  101. this->FindRootPathMode = RootPathModeOnlyRootPath;
  102. }
  103. else if (rootPathMode=="BOTH")
  104. {
  105. this->FindRootPathMode = RootPathModeBoth;
  106. }
  107. }
  108. //----------------------------------------------------------------------------
  109. void cmFindCommon::SelectDefaultMacMode()
  110. {
  111. std::string ff = this->Makefile->GetSafeDefinition("CMAKE_FIND_FRAMEWORK");
  112. if(ff == "NEVER")
  113. {
  114. this->SearchFrameworkLast = false;
  115. this->SearchFrameworkFirst = false;
  116. this->SearchFrameworkOnly = false;
  117. }
  118. else if(ff == "ONLY")
  119. {
  120. this->SearchFrameworkLast = false;
  121. this->SearchFrameworkFirst = false;
  122. this->SearchFrameworkOnly = true;
  123. }
  124. else if(ff == "FIRST")
  125. {
  126. this->SearchFrameworkLast = false;
  127. this->SearchFrameworkFirst = true;
  128. this->SearchFrameworkOnly = false;
  129. }
  130. else if(ff == "LAST")
  131. {
  132. this->SearchFrameworkLast = true;
  133. this->SearchFrameworkFirst = false;
  134. this->SearchFrameworkOnly = false;
  135. }
  136. std::string fab = this->Makefile->GetSafeDefinition("CMAKE_FIND_APPBUNDLE");
  137. if(fab == "NEVER")
  138. {
  139. this->SearchAppBundleLast = false;
  140. this->SearchAppBundleFirst = false;
  141. this->SearchAppBundleOnly = false;
  142. }
  143. else if(fab == "ONLY")
  144. {
  145. this->SearchAppBundleLast = false;
  146. this->SearchAppBundleFirst = false;
  147. this->SearchAppBundleOnly = true;
  148. }
  149. else if(fab == "FIRST")
  150. {
  151. this->SearchAppBundleLast = false;
  152. this->SearchAppBundleFirst = true;
  153. this->SearchAppBundleOnly = false;
  154. }
  155. else if(fab == "LAST")
  156. {
  157. this->SearchAppBundleLast = true;
  158. this->SearchAppBundleFirst = false;
  159. this->SearchAppBundleOnly = false;
  160. }
  161. }
  162. //----------------------------------------------------------------------------
  163. void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
  164. {
  165. #if 0
  166. for(std::vector<std::string>::const_iterator i = paths.begin();
  167. i != paths.end(); ++i)
  168. {
  169. fprintf(stderr, "[%s]\n", i->c_str());
  170. }
  171. #endif
  172. // Short-circuit if there is nothing to do.
  173. if(this->FindRootPathMode == RootPathModeNoRootPath)
  174. {
  175. return;
  176. }
  177. const char* rootPath =
  178. this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
  179. if((rootPath == 0) || (strlen(rootPath) == 0))
  180. {
  181. return;
  182. }
  183. // Construct the list of path roots with no trailing slashes.
  184. std::vector<std::string> roots;
  185. cmSystemTools::ExpandListArgument(rootPath, roots);
  186. for(std::vector<std::string>::iterator ri = roots.begin();
  187. ri != roots.end(); ++ri)
  188. {
  189. cmSystemTools::ConvertToUnixSlashes(*ri);
  190. }
  191. // Copy the original set of unrooted paths.
  192. std::vector<std::string> unrootedPaths = paths;
  193. paths.clear();
  194. for(std::vector<std::string>::const_iterator ri = roots.begin();
  195. ri != roots.end(); ++ri)
  196. {
  197. for(std::vector<std::string>::const_iterator ui = unrootedPaths.begin();
  198. ui != unrootedPaths.end(); ++ui)
  199. {
  200. // Place the unrooted path under the current root if it is not
  201. // already inside. Skip the unrooted path if it is relative to
  202. // a user home directory or is empty.
  203. std::string rootedDir;
  204. if(cmSystemTools::IsSubDirectory(ui->c_str(), ri->c_str()))
  205. {
  206. rootedDir = *ui;
  207. }
  208. else if(!ui->empty() && (*ui)[0] != '~')
  209. {
  210. // Start with the new root.
  211. rootedDir = *ri;
  212. rootedDir += "/";
  213. // Append the original path with its old root removed.
  214. rootedDir += cmSystemTools::SplitPathRootComponent(ui->c_str());
  215. }
  216. // Store the new path.
  217. paths.push_back(rootedDir);
  218. }
  219. }
  220. // If searching both rooted and unrooted paths add the original
  221. // paths again.
  222. if(this->FindRootPathMode == RootPathModeBoth)
  223. {
  224. paths.insert(paths.end(), unrootedPaths.begin(), unrootedPaths.end());
  225. }
  226. }
  227. //----------------------------------------------------------------------------
  228. bool cmFindCommon::CheckCommonArgument(std::string const& arg)
  229. {
  230. if(arg == "NO_DEFAULT_PATH")
  231. {
  232. this->NoDefaultPath = true;
  233. }
  234. else if(arg == "NO_CMAKE_ENVIRONMENT_PATH")
  235. {
  236. this->NoCMakeEnvironmentPath = true;
  237. }
  238. else if(arg == "NO_CMAKE_PATH")
  239. {
  240. this->NoCMakePath = true;
  241. }
  242. else if(arg == "NO_SYSTEM_ENVIRONMENT_PATH")
  243. {
  244. this->NoSystemEnvironmentPath = true;
  245. }
  246. else if(arg == "NO_CMAKE_SYSTEM_PATH")
  247. {
  248. this->NoCMakeSystemPath = true;
  249. }
  250. else if(arg == "NO_CMAKE_FIND_ROOT_PATH")
  251. {
  252. this->FindRootPathMode = RootPathModeNoRootPath;
  253. }
  254. else if(arg == "ONLY_CMAKE_FIND_ROOT_PATH")
  255. {
  256. this->FindRootPathMode = RootPathModeOnlyRootPath;
  257. }
  258. else if(arg == "CMAKE_FIND_ROOT_PATH_BOTH")
  259. {
  260. this->FindRootPathMode = RootPathModeBoth;
  261. }
  262. else
  263. {
  264. // The argument is not one of the above.
  265. return false;
  266. }
  267. // The argument is one of the above.
  268. return true;
  269. }
  270. //----------------------------------------------------------------------------
  271. void cmFindCommon::AddPathSuffix(std::string const& arg)
  272. {
  273. std::string suffix = arg;
  274. // Strip leading and trailing slashes.
  275. if(suffix.empty())
  276. {
  277. return;
  278. }
  279. if(suffix[0] == '/')
  280. {
  281. suffix = suffix.substr(1, suffix.npos);
  282. }
  283. if(suffix.empty())
  284. {
  285. return;
  286. }
  287. if(suffix[suffix.size()-1] == '/')
  288. {
  289. suffix = suffix.substr(0, suffix.size()-1);
  290. }
  291. if(suffix.empty())
  292. {
  293. return;
  294. }
  295. // Store the suffix.
  296. this->SearchPathSuffixes.push_back(suffix);
  297. }
  298. //----------------------------------------------------------------------------
  299. void cmFindCommon::AddUserPath(std::string const& p)
  300. {
  301. // We should view the registry as the target application would view
  302. // it.
  303. cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32;
  304. cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64;
  305. if(const char* psize =
  306. this->Makefile->GetDefinition("CMAKE_SIZEOF_VOID_P"))
  307. {
  308. if(atoi(psize) == 8)
  309. {
  310. view = cmSystemTools::KeyWOW64_64;
  311. other_view = cmSystemTools::KeyWOW64_32;
  312. }
  313. }
  314. // Expand using the view of the target application.
  315. std::string expanded = p;
  316. cmSystemTools::ExpandRegistryValues(expanded, view);
  317. cmSystemTools::GlobDirs(expanded.c_str(), this->UserPaths);
  318. // Executables can be either 32-bit or 64-bit, so expand using the
  319. // alternative view.
  320. if(expanded != p && this->CMakePathName == "PROGRAM")
  321. {
  322. expanded = p;
  323. cmSystemTools::ExpandRegistryValues(expanded, other_view);
  324. cmSystemTools::GlobDirs(expanded.c_str(), this->UserPaths);
  325. }
  326. }
  327. //----------------------------------------------------------------------------
  328. void cmFindCommon::AddCMakePath(const char* variable)
  329. {
  330. // Get a path from a CMake variable.
  331. if(const char* varPath = this->Makefile->GetDefinition(variable))
  332. {
  333. std::vector<std::string> tmp;
  334. cmSystemTools::ExpandListArgument(varPath, tmp);
  335. // Relative paths are interpreted with respect to the current
  336. // source directory.
  337. this->AddPathsInternal(tmp, CMakePath);
  338. }
  339. }
  340. //----------------------------------------------------------------------------
  341. void cmFindCommon::AddEnvPath(const char* variable)
  342. {
  343. // Get a path from the environment.
  344. std::vector<std::string> tmp;
  345. cmSystemTools::GetPath(tmp, variable);
  346. // Relative paths are interpreted with respect to the current
  347. // working directory.
  348. this->AddPathsInternal(tmp, EnvPath);
  349. }
  350. //----------------------------------------------------------------------------
  351. void cmFindCommon::AddPathsInternal(std::vector<std::string> const& in_paths,
  352. PathType pathType)
  353. {
  354. for(std::vector<std::string>::const_iterator i = in_paths.begin();
  355. i != in_paths.end(); ++i)
  356. {
  357. this->AddPathInternal(*i, pathType);
  358. }
  359. }
  360. //----------------------------------------------------------------------------
  361. void cmFindCommon::AddPathInternal(std::string const& in_path,
  362. PathType pathType)
  363. {
  364. if(in_path.empty())
  365. {
  366. return;
  367. }
  368. // Select the base path with which to interpret relative paths.
  369. const char* relbase = 0;
  370. if(pathType == CMakePath)
  371. {
  372. relbase = this->Makefile->GetCurrentDirectory();
  373. }
  374. // Convert to clean full path.
  375. std::string fullPath =
  376. cmSystemTools::CollapseFullPath(in_path.c_str(), relbase);
  377. // Insert the path if has not already been emitted.
  378. if(this->SearchPathsEmitted.insert(fullPath).second)
  379. {
  380. this->SearchPaths.push_back(fullPath.c_str());
  381. }
  382. }
  383. //----------------------------------------------------------------------------
  384. void cmFindCommon::AddTrailingSlashes(std::vector<std::string>& paths)
  385. {
  386. // Add a trailing slash to all paths to aid the search process.
  387. for(std::vector<std::string>::iterator i = paths.begin();
  388. i != paths.end(); ++i)
  389. {
  390. std::string& p = *i;
  391. if(!p.empty() && p[p.size()-1] != '/')
  392. {
  393. p += "/";
  394. }
  395. }
  396. }