Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmFindPathCommand.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 "cmFindPathCommand.h"
13 #include "cmCacheManager.h"
14
15 #include <cmsys/Glob.hxx>
16
17 cmFindPathCommand::cmFindPathCommand()
18 {
19   this->EnvironmentPath = "INCLUDE";
20   this->IncludeFileInPath = false;
21 }
22
23 void cmFindPathCommand::GenerateDocumentation()
24 {
25   this->cmFindBase::GenerateDocumentation();
26   cmSystemTools::ReplaceString(this->GenericDocumentation,
27                                "FIND_XXX", "find_path");
28   cmSystemTools::ReplaceString(this->GenericDocumentation,
29                                "CMAKE_XXX_PATH", "CMAKE_INCLUDE_PATH");
30   cmSystemTools::ReplaceString(this->GenericDocumentation,
31                                "CMAKE_XXX_MAC_PATH",
32                                "CMAKE_FRAMEWORK_PATH");
33   cmSystemTools::ReplaceString(this->GenericDocumentation,
34                                "CMAKE_SYSTEM_XXX_MAC_PATH",
35                                "CMAKE_SYSTEM_FRAMEWORK_PATH");
36   cmSystemTools::ReplaceString(this->GenericDocumentation,
37                                "XXX_SYSTEM", "INCLUDE");
38   cmSystemTools::ReplaceString(this->GenericDocumentation,
39                                "CMAKE_SYSTEM_XXX_PATH",
40                                "CMAKE_SYSTEM_INCLUDE_PATH");
41   cmSystemTools::ReplaceString(this->GenericDocumentation,
42                                "SEARCH_XXX_DESC",
43                                "directory containing the named file");
44   cmSystemTools::ReplaceString(this->GenericDocumentation,
45                                "SEARCH_XXX", "file in a directory");
46   cmSystemTools::ReplaceString(this->GenericDocumentation,
47                                "XXX_SUBDIR", "include");
48   cmSystemTools::ReplaceString(this->GenericDocumentation,
49                                "XXX_EXTRA_PREFIX_ENTRY", "");
50   cmSystemTools::ReplaceString(this->GenericDocumentation,
51                                "CMAKE_FIND_ROOT_PATH_MODE_XXX",
52                                "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE");
53   if(!this->IncludeFileInPath)
54     {
55     this->GenericDocumentation +=
56       "\n"
57       "When searching for frameworks, if the file is specified as "
58       "A/b.h, then the framework search will look for "
59       "A.framework/Headers/b.h. "
60       "If that is found the path will be set to the path to the framework. "
61       "CMake will convert this to the correct -F option to include the "
62       "file. ";
63     }
64 }
65
66 // cmFindPathCommand
67 bool cmFindPathCommand
68 ::InitialPass(std::vector<std::string> const& argsIn, cmExecutionStatus &)
69 {
70   this->VariableDocumentation = "Path to a file.";
71   this->CMakePathName = "INCLUDE";
72   if(!this->ParseArguments(argsIn))
73     {
74     return false;
75     }
76   if(this->AlreadyInCache)
77     {
78     // If the user specifies the entry on the command line without a
79     // type we should add the type and docstring but keep the original
80     // value.
81     if(this->AlreadyInCacheWithoutMetaInfo)
82       {
83       this->Makefile->AddCacheDefinition(
84         this->VariableName.c_str(), "",
85         this->VariableDocumentation.c_str(),
86         (this->IncludeFileInPath ?
87          cmCacheManager::FILEPATH :cmCacheManager::PATH)
88         );
89       }
90     return true;
91     }
92
93   std::string result = this->FindHeader();
94   if(result.size() != 0)
95     {
96     this->Makefile->AddCacheDefinition
97       (this->VariableName.c_str(), result.c_str(),
98        this->VariableDocumentation.c_str(),
99        (this->IncludeFileInPath) ?
100        cmCacheManager::FILEPATH :cmCacheManager::PATH);
101     return true;
102     }
103   this->Makefile->AddCacheDefinition
104     (this->VariableName.c_str(),
105      (this->VariableName + "-NOTFOUND").c_str(),
106      this->VariableDocumentation.c_str(),
107      (this->IncludeFileInPath) ? 
108      cmCacheManager::FILEPATH :cmCacheManager::PATH);
109   return true;
110 }
111
112 //----------------------------------------------------------------------------
113 std::string cmFindPathCommand::FindHeader()
114 {
115   std::string header;
116   if(this->SearchFrameworkFirst || this->SearchFrameworkOnly)
117     {
118     header = this->FindFrameworkHeader();
119     }
120   if(header.empty() && !this->SearchFrameworkOnly)
121     {
122     header = this->FindNormalHeader();
123     }
124   if(header.empty() && this->SearchFrameworkLast)
125     {
126     header = this->FindFrameworkHeader();
127     }
128   return header;
129 }
130
131 std::string
132 cmFindPathCommand::FindHeaderInFramework(std::string const& file,
133                                          std::string const& dir)
134 {
135   cmStdString fileName = file;
136   cmStdString frameWorkName;
137   cmStdString::size_type pos = fileName.find("/");
138   // if there is a / in the name try to find the header as a framework
139   // For example bar/foo.h would look for:
140   // bar.framework/Headers/foo.h
141   if(pos != fileName.npos)
142     {
143     // remove the name from the slash;
144     fileName = fileName.substr(pos+1);
145     frameWorkName = file;
146     frameWorkName = 
147       frameWorkName.substr(0, frameWorkName.size()-fileName.size()-1);
148     // if the framework has a path in it then just use the filename
149     if(frameWorkName.find("/") != frameWorkName.npos)
150       {
151       fileName = file;
152       frameWorkName = "";
153       } 
154     if(frameWorkName.size())
155       {
156       std::string fpath = dir;
157       fpath += frameWorkName;
158       fpath += ".framework";
159       std::string intPath = fpath;
160       intPath += "/Headers/";
161       intPath += fileName;
162       if(cmSystemTools::FileExists(intPath.c_str()))
163         { 
164         if(this->IncludeFileInPath)
165           {
166           return intPath;
167           }
168         return fpath;
169         }
170       }
171     }
172   // if it is not found yet or not a framework header, then do a glob search
173   // for all frameworks in the directory: dir/*.framework/Headers/<file>
174   cmStdString glob = dir;
175   glob += "*.framework/Headers/";
176   glob += file;
177   cmsys::Glob globIt;
178   globIt.FindFiles(glob);
179   std::vector<std::string> files = globIt.GetFiles();
180   if(files.size())
181     {
182     cmStdString fheader = cmSystemTools::CollapseFullPath(files[0].c_str());
183     if(this->IncludeFileInPath)
184       {
185       return fheader;
186       }
187     fheader = cmSystemTools::GetFilenamePath(fheader);
188     return fheader;
189     }
190   return "";
191 }
192
193 //----------------------------------------------------------------------------
194 std::string cmFindPathCommand::FindNormalHeader()
195 {
196   std::string tryPath;
197   for(std::vector<std::string>::const_iterator ni = this->Names.begin();
198       ni != this->Names.end() ; ++ni)
199     {
200     for(std::vector<std::string>::const_iterator
201           p = this->SearchPaths.begin();
202         p != this->SearchPaths.end(); ++p)
203       {
204       tryPath = *p;
205       tryPath += *ni;
206       if(cmSystemTools::FileExists(tryPath.c_str()))
207         {
208         if(this->IncludeFileInPath)
209           {
210           return tryPath;
211           }
212         else
213           {
214           return *p;
215           }
216         }
217       }
218     }
219   return "";
220 }
221
222 //----------------------------------------------------------------------------
223 std::string cmFindPathCommand::FindFrameworkHeader()
224 {
225   for(std::vector<std::string>::const_iterator ni = this->Names.begin();
226       ni != this->Names.end() ; ++ni)
227     {
228     for(std::vector<std::string>::const_iterator
229           p = this->SearchPaths.begin();
230         p != this->SearchPaths.end(); ++p)
231       {
232       std::string fwPath = this->FindHeaderInFramework(*ni, *p);
233       if(!fwPath.empty())
234         {
235         return fwPath;
236         }
237       }
238     }
239   return "";
240 }