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