Imported Upstream version 2.8.11.2
[platform/upstream/cmake.git] / Source / cmFindBase.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 "cmFindBase.h"
13
14 cmFindBase::cmFindBase()
15 {
16   this->AlreadyInCache = false;
17   this->AlreadyInCacheWithoutMetaInfo = false;
18   this->NamesPerDir = false;
19   this->NamesPerDirAllowed = false;
20 }
21
22 //----------------------------------------------------------------------------
23 void cmFindBase::GenerateDocumentation()
24 {
25   this->cmFindCommon::GenerateDocumentation();
26   cmSystemTools::ReplaceString(this->GenericDocumentationPathsOrder,
27                                "FIND_ARGS_XXX", "<VAR> NAMES name");
28   this->GenericDocumentation =
29     "   FIND_XXX(<VAR> name1 [path1 path2 ...])\n"
30     "This is the short-hand signature for the command that "
31     "is sufficient in many cases.  It is the same "
32     "as FIND_XXX(<VAR> name1 [PATHS path1 path2 ...])\n"
33     "   FIND_XXX(\n"
34     "             <VAR>\n"
35     "             name | NAMES name1 [name2 ...]\n"
36     "             [HINTS path1 [path2 ... ENV var]]\n"
37     "             [PATHS path1 [path2 ... ENV var]]\n"
38     "             [PATH_SUFFIXES suffix1 [suffix2 ...]]\n"
39     "             [DOC \"cache documentation string\"]\n"
40     "             [NO_DEFAULT_PATH]\n"
41     "             [NO_CMAKE_ENVIRONMENT_PATH]\n"
42     "             [NO_CMAKE_PATH]\n"
43     "             [NO_SYSTEM_ENVIRONMENT_PATH]\n"
44     "             [NO_CMAKE_SYSTEM_PATH]\n"
45     "             [CMAKE_FIND_ROOT_PATH_BOTH |\n"
46     "              ONLY_CMAKE_FIND_ROOT_PATH |\n"
47     "              NO_CMAKE_FIND_ROOT_PATH]\n"
48     "            )\n"
49     ""
50     "This command is used to find a SEARCH_XXX_DESC. "
51     "A cache entry named by <VAR> is created to store the result "
52     "of this command.  "
53     "If the SEARCH_XXX is found the result is stored in the variable "
54     "and the search will not be repeated unless the variable is cleared.  "
55     "If nothing is found, the result will be "
56     "<VAR>-NOTFOUND, and the search will be attempted again the "
57     "next time FIND_XXX is invoked with the same variable.  "
58     "The name of the SEARCH_XXX that "
59     "is searched for is specified by the names listed "
60     "after the NAMES argument.   Additional search locations "
61     "can be specified after the PATHS argument.  If ENV var is "
62     "found in the HINTS or PATHS section the environment variable var "
63     "will be read and converted from a system environment variable to "
64     "a cmake style list of paths.  For example ENV PATH would be a way "
65     "to list the system path variable. The argument "
66     "after DOC will be used for the documentation string in "
67     "the cache.  "
68     "PATH_SUFFIXES specifies additional subdirectories to check below "
69     "each search path."
70     "\n"
71     "If NO_DEFAULT_PATH is specified, then no additional paths are "
72     "added to the search. "
73     "If NO_DEFAULT_PATH is not specified, the search process is as follows:\n"
74     "1. Search paths specified in cmake-specific cache variables.  "
75     "These are intended to be used on the command line with a -DVAR=value.  "
76     "This can be skipped if NO_CMAKE_PATH is passed.\n"
77     "XXX_EXTRA_PREFIX_ENTRY"
78     "   <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n"
79     "   CMAKE_XXX_PATH\n"
80     "   CMAKE_XXX_MAC_PATH\n"
81     "2. Search paths specified in cmake-specific environment variables.  "
82     "These are intended to be set in the user's shell configuration.  "
83     "This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed.\n"
84     "XXX_EXTRA_PREFIX_ENTRY"
85     "   <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n"
86     "   CMAKE_XXX_PATH\n"
87     "   CMAKE_XXX_MAC_PATH\n"
88     "3. Search the paths specified by the HINTS option.  "
89     "These should be paths computed by system introspection, such as a "
90     "hint provided by the location of another item already found.  "
91     "Hard-coded guesses should be specified with the PATHS option.\n"
92     "4. Search the standard system environment variables. "
93     "This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is an argument.\n"
94     "   PATH\n"
95     "   XXX_SYSTEM\n"  // replace with "", LIB, or INCLUDE
96     "5. Search cmake variables defined in the Platform files "
97     "for the current system.  This can be skipped if NO_CMAKE_SYSTEM_PATH "
98     "is passed.\n"
99     "XXX_EXTRA_PREFIX_ENTRY"
100     "   <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_SYSTEM_PREFIX_PATH\n"
101     "   CMAKE_SYSTEM_XXX_PATH\n"
102     "   CMAKE_SYSTEM_XXX_MAC_PATH\n"
103     "6. Search the paths specified by the PATHS option "
104     "or in the short-hand version of the command.  "
105     "These are typically hard-coded guesses.\n"
106     ;
107   this->GenericDocumentation += this->GenericDocumentationMacPolicy;
108   this->GenericDocumentation += this->GenericDocumentationRootPath;
109   this->GenericDocumentation += this->GenericDocumentationPathsOrder;
110 }
111
112 //----------------------------------------------------------------------------
113 const char* cmFindBase::GetFullDocumentation() const
114 {
115   if(this->GenericDocumentation.empty())
116     {
117     const_cast<cmFindBase *>(this)->GenerateDocumentation();
118     }
119   return this->GenericDocumentation.c_str();
120 }
121
122 //----------------------------------------------------------------------------
123 bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
124 {
125   if(argsIn.size() < 2 )
126     {
127     this->SetError("called with incorrect number of arguments");
128     return false;
129     }
130
131   // CMake versions below 2.3 did not search all these extra
132   // locations.  Preserve compatibility unless a modern argument is
133   // passed.
134   bool compatibility = this->Makefile->NeedBackwardsCompatibility(2,3);
135
136   // copy argsIn into args so it can be modified,
137   // in the process extract the DOC "documentation"
138   size_t size = argsIn.size();
139   std::vector<std::string> args;
140   bool foundDoc = false;
141   for(unsigned int j = 0; j < size; ++j)
142     {
143     if(foundDoc  || argsIn[j] != "DOC" )
144       {
145       if(argsIn[j] == "ENV")
146         {
147         if(j+1 < size)
148           {
149           j++;
150           cmSystemTools::GetPath(args, argsIn[j].c_str());
151           }
152         }
153       else
154         {
155         args.push_back(argsIn[j]);
156         }
157       }
158     else
159       {
160       if(j+1 < size)
161         {
162         foundDoc = true;
163         this->VariableDocumentation = argsIn[j+1];
164         j++;
165         if(j >= size)
166           {
167           break;
168           }
169         }
170       }
171     }
172   if(args.size() < 2 )
173     {
174     this->SetError("called with incorrect number of arguments");
175     return false;
176     }
177   this->VariableName = args[0];
178   if(this->CheckForVariableInCache())
179     {
180     this->AlreadyInCache = true;
181     return true;
182     }
183   this->AlreadyInCache = false;
184
185   // Find the current root path mode.
186   this->SelectDefaultRootPathMode();
187
188   // Find the current bundle/framework search policy.
189   this->SelectDefaultMacMode();
190
191   bool newStyle = false;
192   enum Doing { DoingNone, DoingNames, DoingPaths, DoingPathSuffixes,
193                DoingHints };
194   Doing doing = DoingNames; // assume it starts with a name
195   for (unsigned int j = 1; j < args.size(); ++j)
196     {
197     if(args[j] == "NAMES")
198       {
199       doing = DoingNames;
200       newStyle = true;
201       }
202     else if (args[j] == "PATHS")
203       {
204       doing = DoingPaths;
205       newStyle = true;
206       }
207     else if (args[j] == "HINTS")
208       {
209       doing = DoingHints;
210       newStyle = true;
211       }
212     else if (args[j] == "PATH_SUFFIXES")
213       {
214       doing = DoingPathSuffixes;
215       compatibility = false;
216       newStyle = true;
217       }
218     else if (args[j] == "NAMES_PER_DIR")
219       {
220       doing = DoingNone;
221       if(this->NamesPerDirAllowed)
222         {
223         this->NamesPerDir = true;
224         }
225       else
226         {
227         this->SetError("does not support NAMES_PER_DIR");
228         return false;
229         }
230       }
231     else if (args[j] == "NO_SYSTEM_PATH")
232       {
233       doing = DoingNone;
234       this->NoDefaultPath = true;
235       }
236     else if (this->CheckCommonArgument(args[j]))
237       {
238       doing = DoingNone;
239       compatibility = false;
240       // Some common arguments were accidentally supported by CMake
241       // 2.4 and 2.6.0 in the short-hand form of the command, so we
242       // must support it even though it is not documented.
243       }
244     else if(doing == DoingNames)
245       {
246       this->Names.push_back(args[j]);
247       }
248     else if(doing == DoingPaths)
249       {
250       this->AddUserPath(args[j], this->UserPaths);
251       }
252     else if(doing == DoingHints)
253       {
254       this->AddUserPath(args[j], this->UserHints);
255       }
256     else if(doing == DoingPathSuffixes)
257       {
258       this->AddPathSuffix(args[j]);
259       }
260     }
261
262   // Now that arguments have been parsed check the compatibility
263   // setting.  If we need to be compatible with CMake 2.2 and earlier
264   // do not add the CMake system paths.  It is safe to add the CMake
265   // environment paths and system environment paths because that
266   // existed in 2.2.  It is safe to add the CMake user variable paths
267   // because the user or project has explicitly set them.
268   if(compatibility)
269     {
270     this->NoCMakeSystemPath = true;
271     }
272
273   if(this->VariableDocumentation.size() == 0)
274     {
275     this->VariableDocumentation = "Where can ";
276     if(this->Names.size() == 0)
277       {
278       this->VariableDocumentation += "the (unknown) library be found";
279       }
280     else if(this->Names.size() == 1)
281       {
282       this->VariableDocumentation += "the "
283         + this->Names[0] + " library be found";
284       }
285     else
286       {
287       this->VariableDocumentation += "one of the " + this->Names[0];
288       for (unsigned int j = 1; j < this->Names.size() - 1; ++j)
289         {
290         this->VariableDocumentation += ", " + this->Names[j];
291         }
292       this->VariableDocumentation += " or "
293         + this->Names[this->Names.size() - 1] + " libraries be found";
294       }
295     }
296
297   // look for old style
298   // FIND_*(VAR name path1 path2 ...)
299   if(!newStyle)
300     {
301     // All the short-hand arguments have been recorded as names.
302     std::vector<std::string> shortArgs = this->Names;
303     this->Names.clear(); // clear out any values in Names
304     this->Names.push_back(shortArgs[0]);
305     for(unsigned int j = 1; j < shortArgs.size(); ++j)
306       {
307       this->AddUserPath(shortArgs[j], this->UserPaths);
308       }
309     }
310   this->ExpandPaths();
311
312   // Filter out ignored paths from the prefix list
313   std::set<std::string> ignored;
314   this->GetIgnoredPaths(ignored);
315   this->FilterPaths(this->SearchPaths, ignored);
316
317   this->ComputeFinalPaths();
318
319   return true;
320 }
321
322 void cmFindBase::ExpandPaths()
323 {
324   this->AddCMakeVariablePath();
325   this->AddCMakeEnvironmentPath();
326   this->AddUserHintsPath();
327   this->AddSystemEnvironmentPath();
328   this->AddCMakeSystemVariablePath();
329   this->AddUserGuessPath();
330
331   // Add suffixes and clean up paths.
332   this->AddPathSuffixes();
333 }
334
335 //----------------------------------------------------------------------------
336 void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths,
337                                 PathType pathType)
338 {
339   // default for programs
340   std::string subdir = "bin";
341
342   if (this->CMakePathName == "INCLUDE")
343     {
344     subdir = "include";
345     }
346   else if (this->CMakePathName == "LIBRARY")
347     {
348     subdir = "lib";
349     }
350   else if (this->CMakePathName == "FRAMEWORK")
351     {
352     subdir = "";  // ? what to do for frameworks ?
353     }
354
355   for(std::vector<std::string>::const_iterator it = in_paths.begin();
356       it != in_paths.end(); ++it)
357     {
358     std::string dir = it->c_str();
359     if(!subdir.empty() && !dir.empty() && dir[dir.size()-1] != '/')
360       {
361       dir += "/";
362       }
363     if(subdir == "include" || subdir == "lib")
364       {
365       const char* arch =
366         this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE");
367       if(arch && *arch)
368         {
369         this->AddPathInternal(dir+subdir+"/"+arch, pathType);
370         }
371       }
372     std::string add = dir + subdir;
373     if(add != "/")
374       {
375       this->AddPathInternal(add, pathType);
376       }
377     if (subdir == "bin")
378       {
379       this->AddPathInternal(dir+"sbin", pathType);
380       }
381     if(!subdir.empty() && *it != "/")
382       {
383       this->AddPathInternal(*it, pathType);
384       }
385     }
386 }
387
388 //----------------------------------------------------------------------------
389 void cmFindBase::AddCMakePrefixPath(const char* variable)
390 {
391   // Get a path from a CMake variable.
392   if(const char* varPath = this->Makefile->GetDefinition(variable))
393     {
394     std::vector<std::string> tmp;
395     cmSystemTools::ExpandListArgument(varPath, tmp);
396     this->AddPrefixPaths(tmp, CMakePath);
397     }
398 }
399
400 //----------------------------------------------------------------------------
401 void cmFindBase::AddEnvPrefixPath(const char* variable)
402 {
403   // Get a path from the environment.
404   std::vector<std::string> tmp;
405   cmSystemTools::GetPath(tmp, variable);
406   this->AddPrefixPaths(tmp, EnvPath);
407 }
408
409 //----------------------------------------------------------------------------
410 void cmFindBase::AddCMakeEnvironmentPath()
411 {
412   if(!this->NoCMakeEnvironmentPath && !this->NoDefaultPath)
413     {
414     // Add CMAKE_*_PATH environment variables
415     std::string var = "CMAKE_";
416     var += this->CMakePathName;
417     var += "_PATH";
418     this->AddEnvPrefixPath("CMAKE_PREFIX_PATH");
419     this->AddEnvPath(var.c_str());
420
421     if(this->CMakePathName == "PROGRAM")
422       {
423       this->AddEnvPath("CMAKE_APPBUNDLE_PATH");
424       }
425     else
426       {
427       this->AddEnvPath("CMAKE_FRAMEWORK_PATH");
428       }
429     }
430 }
431
432 //----------------------------------------------------------------------------
433 void cmFindBase::AddCMakeVariablePath()
434 {
435   if(!this->NoCMakePath && !this->NoDefaultPath)
436     {
437     // Add CMake varibles of the same name as the previous environment
438     // varibles CMAKE_*_PATH to be used most of the time with -D
439     // command line options
440     std::string var = "CMAKE_";
441     var += this->CMakePathName;
442     var += "_PATH";
443     this->AddCMakePrefixPath("CMAKE_PREFIX_PATH");
444     this->AddCMakePath(var.c_str());
445
446     if(this->CMakePathName == "PROGRAM")
447       {
448       this->AddCMakePath("CMAKE_APPBUNDLE_PATH");
449       }
450     else
451       {
452       this->AddCMakePath("CMAKE_FRAMEWORK_PATH");
453       }
454     }
455 }
456
457 //----------------------------------------------------------------------------
458 void cmFindBase::AddSystemEnvironmentPath()
459 {
460   if(!this->NoSystemEnvironmentPath && !this->NoDefaultPath)
461     {
462     // Add LIB or INCLUDE
463     if(!this->EnvironmentPath.empty())
464       {
465       this->AddEnvPath(this->EnvironmentPath.c_str());
466       }
467     // Add PATH
468     this->AddEnvPath(0);
469     }
470 }
471
472 //----------------------------------------------------------------------------
473 void cmFindBase::AddCMakeSystemVariablePath()
474 {
475   if(!this->NoCMakeSystemPath && !this->NoDefaultPath)
476     {
477     std::string var = "CMAKE_SYSTEM_";
478     var += this->CMakePathName;
479     var += "_PATH";
480     this->AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
481     this->AddCMakePath(var.c_str());
482
483     if(this->CMakePathName == "PROGRAM")
484       {
485       this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");
486       }
487     else
488       {
489       this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
490       }
491     }
492 }
493
494 //----------------------------------------------------------------------------
495 void cmFindBase::AddUserHintsPath()
496 {
497   this->AddPathsInternal(this->UserHints, CMakePath);
498 }
499
500 //----------------------------------------------------------------------------
501 void cmFindBase::AddUserGuessPath()
502 {
503   this->AddPathsInternal(this->UserPaths, CMakePath);
504 }
505
506 //----------------------------------------------------------------------------
507 void cmFindBase::AddPathSuffixes()
508 {
509   std::vector<std::string>& paths = this->SearchPaths;
510   std::vector<std::string> finalPath = paths;
511   std::vector<std::string>::iterator i;
512   // clear the path
513   paths.clear();
514   // convert all paths to unix slashes and add search path suffixes
515   // if there are any
516   for(i = finalPath.begin();
517       i != finalPath.end(); ++i)
518     {
519     cmSystemTools::ConvertToUnixSlashes(*i);
520     // copy each finalPath combined with SearchPathSuffixes
521     // to the SearchPaths ivar
522     for(std::vector<std::string>::iterator j =
523           this->SearchPathSuffixes.begin();
524         j != this->SearchPathSuffixes.end(); ++j)
525       {
526       // if *i is only / then do not add a //
527       // this will get incorrectly considered a network
528       // path on windows and cause huge delays.
529       std::string p = *i;
530       if(p.size() && p[p.size()-1] != '/')
531         {
532         p += std::string("/");
533         }
534       p +=  *j;
535       // add to all paths because the search path may be modified
536       // later with lib being replaced for lib64 which may exist
537       paths.push_back(p);
538       }
539     // now put the path without the path suffixes in the SearchPaths
540     paths.push_back(*i);
541     }
542 }
543
544 void cmFindBase::PrintFindStuff()
545 {
546   std::cerr << "SearchFrameworkLast: " << this->SearchFrameworkLast << "\n";
547   std::cerr << "SearchFrameworkOnly: " << this->SearchFrameworkOnly << "\n";
548   std::cerr << "SearchFrameworkFirst: " << this->SearchFrameworkFirst << "\n";
549   std::cerr << "SearchAppBundleLast: " << this->SearchAppBundleLast << "\n";
550   std::cerr << "SearchAppBundleOnly: " << this->SearchAppBundleOnly << "\n";
551   std::cerr << "SearchAppBundleFirst: " << this->SearchAppBundleFirst << "\n";
552   std::cerr << "VariableName " << this->VariableName << "\n";
553   std::cerr << "VariableDocumentation "
554             << this->VariableDocumentation << "\n";
555   std::cerr << "NoDefaultPath " << this->NoDefaultPath << "\n";
556   std::cerr << "NoCMakeEnvironmentPath "
557             << this->NoCMakeEnvironmentPath << "\n";
558   std::cerr << "NoCMakePath " << this->NoCMakePath << "\n";
559   std::cerr << "NoSystemEnvironmentPath "
560             << this->NoSystemEnvironmentPath << "\n";
561   std::cerr << "NoCMakeSystemPath " << this->NoCMakeSystemPath << "\n";
562   std::cerr << "EnvironmentPath " << this->EnvironmentPath << "\n";
563   std::cerr << "CMakePathName " << this->CMakePathName << "\n";
564   std::cerr << "Names  ";
565   for(unsigned int i =0; i < this->Names.size(); ++i)
566     {
567     std::cerr << this->Names[i] << " ";
568     }
569   std::cerr << "\n";
570   std::cerr << "\n";
571   std::cerr << "SearchPathSuffixes  ";
572   for(unsigned int i =0; i < this->SearchPathSuffixes.size(); ++i)
573     {
574     std::cerr << this->SearchPathSuffixes[i] << "\n";
575     }
576   std::cerr << "\n";
577   std::cerr << "SearchPaths\n";
578   for(unsigned int i =0; i < this->SearchPaths.size(); ++i)
579     {
580     std::cerr << "[" << this->SearchPaths[i] << "]\n";
581     }
582 }
583
584 bool cmFindBase::CheckForVariableInCache()
585 {
586   if(const char* cacheValue =
587      this->Makefile->GetDefinition(this->VariableName.c_str()))
588     {
589     cmCacheManager::CacheIterator it =
590       this->Makefile->GetCacheManager()->
591       GetCacheIterator(this->VariableName.c_str());
592     bool found = !cmSystemTools::IsNOTFOUND(cacheValue);
593     bool cached = !it.IsAtEnd();
594     if(found)
595       {
596       // If the user specifies the entry on the command line without a
597       // type we should add the type and docstring but keep the
598       // original value.  Tell the subclass implementations to do
599       // this.
600       if(cached && it.GetType() == cmCacheManager::UNINITIALIZED)
601         {
602         this->AlreadyInCacheWithoutMetaInfo = true;
603         }
604       return true;
605       }
606     else if(cached)
607       {
608       const char* hs = it.GetProperty("HELPSTRING");
609       this->VariableDocumentation = hs?hs:"(none)";
610       }
611     }
612   return false;
613 }