packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmFindCommon.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmFindCommon.h"
13
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
24   // OS X Bundle and Framework search policy.  The default is to
25   // search frameworks first on apple.
26 #if defined(__APPLE__)
27   this->SearchFrameworkFirst = true;
28   this->SearchAppBundleFirst = true;
29 #else
30   this->SearchFrameworkFirst = false;
31   this->SearchAppBundleFirst = false;
32 #endif
33   this->SearchFrameworkOnly = false;
34   this->SearchFrameworkLast = false;
35   this->SearchAppBundleOnly = false;
36   this->SearchAppBundleLast = false;
37 }
38
39 //----------------------------------------------------------------------------
40 void cmFindCommon::GenerateDocumentation()
41 {
42   // Documentation components.
43   this->GenericDocumentationMacPolicy =
44     "On Darwin or systems supporting OS X Frameworks, the cmake variable"
45     "    CMAKE_FIND_FRAMEWORK can be set to empty or one of the following:\n"
46     "   \"FIRST\"  - Try to find frameworks before standard\n"
47     "              libraries or headers. This is the default on Darwin.\n"
48     "   \"LAST\"   - Try to find frameworks after standard\n"
49     "              libraries or headers.\n"
50     "   \"ONLY\"   - Only try to find frameworks.\n"
51     "   \"NEVER\" - Never try to find frameworks.\n"
52     "On Darwin or systems supporting OS X Application Bundles, the cmake "
53     "variable CMAKE_FIND_APPBUNDLE can be set to empty or one of the "
54     "following:\n"
55     "   \"FIRST\"  - Try to find application bundles before standard\n"
56     "              programs. This is the default on Darwin.\n"
57     "   \"LAST\"   - Try to find application bundles after standard\n"
58     "              programs.\n"
59     "   \"ONLY\"   - Only try to find application bundles.\n"
60     "   \"NEVER\" - Never try to find application bundles.\n";
61   this->GenericDocumentationRootPath =
62     "The CMake variable CMAKE_FIND_ROOT_PATH specifies one or more "
63     "directories to be prepended to all other search directories. "
64     "This effectively \"re-roots\" the entire search under given locations. "
65     "By default it is empty. It is especially useful when "
66     "cross-compiling to point to the root directory of the "
67     "target environment and CMake will search there too. By default at first "
68     "the directories listed in CMAKE_FIND_ROOT_PATH and then the non-rooted "
69     "directories will be searched. "
70     "The default behavior can be adjusted by setting "
71     "CMAKE_FIND_ROOT_PATH_MODE_XXX.  This behavior can be manually "
72     "overridden on a per-call basis. "
73     "By using CMAKE_FIND_ROOT_PATH_BOTH the search order will "
74     "be as described above. If NO_CMAKE_FIND_ROOT_PATH is used "
75     "then CMAKE_FIND_ROOT_PATH will not be used. If ONLY_CMAKE_FIND_ROOT_PATH "
76     "is used then only the re-rooted directories will be searched.\n";
77   this->GenericDocumentationPathsOrder =
78     "The default search order is designed to be most-specific to "
79     "least-specific for common use cases.  "
80     "Projects may override the order by simply calling the command "
81     "multiple times and using the NO_* options:\n"
82     "   FIND_XXX(FIND_ARGS_XXX PATHS paths... NO_DEFAULT_PATH)\n"
83     "   FIND_XXX(FIND_ARGS_XXX)\n"
84     "Once one of the calls succeeds the result variable will be set "
85     "and stored in the cache so that no call will search again.";
86 }
87
88 //----------------------------------------------------------------------------
89 cmFindCommon::~cmFindCommon()
90 {
91 }
92
93 //----------------------------------------------------------------------------
94 void cmFindCommon::SelectDefaultRootPathMode()
95 {
96   // Use both by default.
97   this->FindRootPathMode = RootPathModeBoth;
98
99   // Check the policy variable for this find command type.
100   std::string findRootPathVar = "CMAKE_FIND_ROOT_PATH_MODE_";
101   findRootPathVar += this->CMakePathName;
102   std::string rootPathMode =
103     this->Makefile->GetSafeDefinition(findRootPathVar.c_str());
104   if (rootPathMode=="NEVER")
105     {
106     this->FindRootPathMode = RootPathModeNoRootPath;
107     }
108   else if (rootPathMode=="ONLY")
109     {
110     this->FindRootPathMode = RootPathModeOnlyRootPath;
111     }
112   else if (rootPathMode=="BOTH")
113     {
114     this->FindRootPathMode = RootPathModeBoth;
115     }
116 }
117
118 //----------------------------------------------------------------------------
119 void cmFindCommon::SelectDefaultMacMode()
120 {
121   std::string ff = this->Makefile->GetSafeDefinition("CMAKE_FIND_FRAMEWORK");
122   if(ff == "NEVER")
123     {
124     this->SearchFrameworkLast = false;
125     this->SearchFrameworkFirst = false;
126     this->SearchFrameworkOnly = false;
127     }
128   else if(ff == "ONLY")
129     {
130     this->SearchFrameworkLast = false;
131     this->SearchFrameworkFirst = false;
132     this->SearchFrameworkOnly = true;
133     }
134   else if(ff == "FIRST")
135     {
136     this->SearchFrameworkLast = false;
137     this->SearchFrameworkFirst = true;
138     this->SearchFrameworkOnly = false;
139     }
140   else if(ff == "LAST")
141     {
142     this->SearchFrameworkLast = true;
143     this->SearchFrameworkFirst = false;
144     this->SearchFrameworkOnly = false;
145     }
146
147   std::string fab = this->Makefile->GetSafeDefinition("CMAKE_FIND_APPBUNDLE");
148   if(fab == "NEVER")
149     {
150     this->SearchAppBundleLast = false;
151     this->SearchAppBundleFirst = false;
152     this->SearchAppBundleOnly = false;
153     }
154   else if(fab == "ONLY")
155     {
156     this->SearchAppBundleLast = false;
157     this->SearchAppBundleFirst = false;
158     this->SearchAppBundleOnly = true;
159     }
160   else if(fab == "FIRST")
161     {
162     this->SearchAppBundleLast = false;
163     this->SearchAppBundleFirst = true;
164     this->SearchAppBundleOnly = false;
165     }
166   else if(fab == "LAST")
167     {
168     this->SearchAppBundleLast = true;
169     this->SearchAppBundleFirst = false;
170     this->SearchAppBundleOnly = false;
171     }
172 }
173
174 //----------------------------------------------------------------------------
175 void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
176 {
177 #if 0
178   for(std::vector<std::string>::const_iterator i = paths.begin();
179       i != paths.end(); ++i)
180     {
181     fprintf(stderr, "[%s]\n", i->c_str());
182     }
183 #endif
184
185   // Short-circuit if there is nothing to do.
186   if(this->FindRootPathMode == RootPathModeNoRootPath)
187     {
188     return;
189     }
190   const char* rootPath =
191     this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
192   if((rootPath == 0) || (strlen(rootPath) == 0))
193     {
194     return;
195     }
196
197   // Construct the list of path roots with no trailing slashes.
198   std::vector<std::string> roots;
199   cmSystemTools::ExpandListArgument(rootPath, roots);
200   for(std::vector<std::string>::iterator ri = roots.begin();
201       ri != roots.end(); ++ri)
202     {
203     cmSystemTools::ConvertToUnixSlashes(*ri);
204     }
205
206   // Copy the original set of unrooted paths.
207   std::vector<std::string> unrootedPaths = paths;
208   paths.clear();
209
210   for(std::vector<std::string>::const_iterator ri = roots.begin();
211       ri != roots.end(); ++ri)
212     {
213     for(std::vector<std::string>::const_iterator ui = unrootedPaths.begin();
214         ui != unrootedPaths.end(); ++ui)
215       {
216       // Place the unrooted path under the current root if it is not
217       // already inside.  Skip the unrooted path if it is relative to
218       // a user home directory or is empty.
219       std::string rootedDir;
220       if(cmSystemTools::IsSubDirectory(ui->c_str(), ri->c_str()))
221         {
222         rootedDir = *ui;
223         }
224       else if(!ui->empty() && (*ui)[0] != '~')
225         {
226         // Start with the new root.
227         rootedDir = *ri;
228         rootedDir += "/";
229
230         // Append the original path with its old root removed.
231         rootedDir += cmSystemTools::SplitPathRootComponent(ui->c_str());
232         }
233
234       // Store the new path.
235       paths.push_back(rootedDir);
236       }
237     }
238
239   // If searching both rooted and unrooted paths add the original
240   // paths again.
241   if(this->FindRootPathMode == RootPathModeBoth)
242     {
243     paths.insert(paths.end(), unrootedPaths.begin(), unrootedPaths.end());
244     }
245 }
246
247 //----------------------------------------------------------------------------
248 void cmFindCommon::FilterPaths(std::vector<std::string>& paths,
249                                const std::set<std::string>& ignore)
250 {
251   // Now filter out anything that's in the ignore set.
252   std::vector<std::string> unfiltered;
253   unfiltered.swap(paths);
254
255   for(std::vector<std::string>::iterator pi = unfiltered.begin();
256       pi != unfiltered.end(); ++pi)
257     {
258     if (ignore.count(*pi) == 0)
259       {
260       paths.push_back(*pi);
261       }
262     }
263 }
264
265
266 //----------------------------------------------------------------------------
267 void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore)
268 {
269   // null-terminated list of paths.
270   static const char *paths[] =
271     { "CMAKE_SYSTEM_IGNORE_PATH", "CMAKE_IGNORE_PATH", 0 };
272
273   // Construct the list of path roots with no trailing slashes.
274   for(const char **pathName = paths; *pathName; ++pathName)
275     {
276     // Get the list of paths to ignore from the variable.
277     const char* ignorePath = this->Makefile->GetDefinition(*pathName);
278     if((ignorePath == 0) || (strlen(ignorePath) == 0))
279       {
280       continue;
281       }
282
283     cmSystemTools::ExpandListArgument(ignorePath, ignore);
284     }
285
286   for(std::vector<std::string>::iterator i = ignore.begin();
287       i != ignore.end(); ++i)
288     {
289     cmSystemTools::ConvertToUnixSlashes(*i);
290     }
291 }
292
293
294 //----------------------------------------------------------------------------
295 void cmFindCommon::GetIgnoredPaths(std::set<std::string>& ignore)
296 {
297   std::vector<std::string> ignoreVec;
298   GetIgnoredPaths(ignoreVec);
299   ignore.insert(ignoreVec.begin(), ignoreVec.end());
300 }
301
302
303
304 //----------------------------------------------------------------------------
305 bool cmFindCommon::CheckCommonArgument(std::string const& arg)
306 {
307   if(arg == "NO_DEFAULT_PATH")
308     {
309     this->NoDefaultPath = true;
310     }
311   else if(arg == "NO_CMAKE_ENVIRONMENT_PATH")
312     {
313     this->NoCMakeEnvironmentPath = true;
314     }
315   else if(arg == "NO_CMAKE_PATH")
316     {
317     this->NoCMakePath = true;
318     }
319   else if(arg == "NO_SYSTEM_ENVIRONMENT_PATH")
320     {
321     this->NoSystemEnvironmentPath = true;
322     }
323   else if(arg == "NO_CMAKE_SYSTEM_PATH")
324     {
325     this->NoCMakeSystemPath = true;
326     }
327   else if(arg == "NO_CMAKE_FIND_ROOT_PATH")
328     {
329     this->FindRootPathMode = RootPathModeNoRootPath;
330     }
331   else if(arg == "ONLY_CMAKE_FIND_ROOT_PATH")
332     {
333     this->FindRootPathMode = RootPathModeOnlyRootPath;
334     }
335   else if(arg == "CMAKE_FIND_ROOT_PATH_BOTH")
336     {
337     this->FindRootPathMode = RootPathModeBoth;
338     }
339   else
340     {
341     // The argument is not one of the above.
342     return false;
343     }
344
345   // The argument is one of the above.
346   return true;
347 }
348
349 //----------------------------------------------------------------------------
350 void cmFindCommon::AddPathSuffix(std::string const& arg)
351 {
352   std::string suffix = arg;
353
354   // Strip leading and trailing slashes.
355   if(suffix.empty())
356     {
357     return;
358     }
359   if(suffix[0] == '/')
360     {
361     suffix = suffix.substr(1, suffix.npos);
362     }
363   if(suffix.empty())
364     {
365     return;
366     }
367   if(suffix[suffix.size()-1] == '/')
368     {
369     suffix = suffix.substr(0, suffix.size()-1);
370     }
371   if(suffix.empty())
372     {
373     return;
374     }
375
376   // Store the suffix.
377   this->SearchPathSuffixes.push_back(suffix);
378 }
379
380 //----------------------------------------------------------------------------
381 void cmFindCommon::AddUserPath(std::string const& p,
382                                std::vector<std::string>& paths)
383 {
384   // We should view the registry as the target application would view
385   // it.
386   cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32;
387   cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64;
388   if(this->Makefile->PlatformIs64Bit())
389     {
390     view = cmSystemTools::KeyWOW64_64;
391     other_view = cmSystemTools::KeyWOW64_32;
392     }
393
394   // Expand using the view of the target application.
395   std::string expanded = p;
396   cmSystemTools::ExpandRegistryValues(expanded, view);
397   cmSystemTools::GlobDirs(expanded.c_str(), paths);
398
399   // Executables can be either 32-bit or 64-bit, so expand using the
400   // alternative view.
401   if(expanded != p && this->CMakePathName == "PROGRAM")
402     {
403     expanded = p;
404     cmSystemTools::ExpandRegistryValues(expanded, other_view);
405     cmSystemTools::GlobDirs(expanded.c_str(), paths);
406     }
407 }
408
409 //----------------------------------------------------------------------------
410 void cmFindCommon::AddCMakePath(const char* variable)
411 {
412   // Get a path from a CMake variable.
413   if(const char* varPath = this->Makefile->GetDefinition(variable))
414     {
415     std::vector<std::string> tmp;
416     cmSystemTools::ExpandListArgument(varPath, tmp);
417
418     // Relative paths are interpreted with respect to the current
419     // source directory.
420     this->AddPathsInternal(tmp, CMakePath);
421     }
422 }
423
424 //----------------------------------------------------------------------------
425 void cmFindCommon::AddEnvPath(const char* variable)
426 {
427   // Get a path from the environment.
428   std::vector<std::string> tmp;
429   cmSystemTools::GetPath(tmp, variable);
430   // Relative paths are interpreted with respect to the current
431   // working directory.
432   this->AddPathsInternal(tmp, EnvPath);
433 }
434
435 //----------------------------------------------------------------------------
436 void cmFindCommon::AddPathsInternal(std::vector<std::string> const& in_paths,
437                                     PathType pathType)
438 {
439   for(std::vector<std::string>::const_iterator i = in_paths.begin();
440       i != in_paths.end(); ++i)
441     {
442     this->AddPathInternal(*i, pathType);
443     }
444 }
445
446 //----------------------------------------------------------------------------
447 void cmFindCommon::AddPathInternal(std::string const& in_path,
448                                    PathType pathType)
449 {
450   if(in_path.empty())
451     {
452     return;
453     }
454
455   // Select the base path with which to interpret relative paths.
456   const char* relbase = 0;
457   if(pathType == CMakePath)
458     {
459     relbase = this->Makefile->GetCurrentDirectory();
460     }
461
462   // Convert to clean full path.
463   std::string fullPath =
464     cmSystemTools::CollapseFullPath(in_path.c_str(), relbase);
465
466   // Insert the path if has not already been emitted.
467   if(this->SearchPathsEmitted.insert(fullPath).second)
468     {
469     this->SearchPaths.push_back(fullPath.c_str());
470     }
471 }
472
473 //----------------------------------------------------------------------------
474 void cmFindCommon::ComputeFinalPaths()
475 {
476   std::vector<std::string>& paths = this->SearchPaths;
477
478   // Expand list of paths inside all search roots.
479   this->RerootPaths(paths);
480
481   // Add a trailing slash to all paths to aid the search process.
482   for(std::vector<std::string>::iterator i = paths.begin();
483       i != paths.end(); ++i)
484     {
485     std::string& p = *i;
486     if(!p.empty() && p[p.size()-1] != '/')
487       {
488       p += "/";
489       }
490     }
491 }
492
493 //----------------------------------------------------------------------------
494 void cmFindCommon::SetMakefile(cmMakefile* makefile)
495 {
496   cmCommand::SetMakefile(makefile);
497
498   // If we are building for Apple (OSX or also iphone), make sure
499   // that frameworks and bundles are searched first.
500   if(this->Makefile->IsOn("APPLE"))
501     {
502     this->SearchFrameworkFirst = true;
503     this->SearchAppBundleFirst = true;
504     }
505 }