1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmFindPathCommand.cxx,v $
6 Date: $Date: 2008-01-23 15:27:59 $
7 Version: $Revision: 1.41 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmFindPathCommand.h"
18 #include "cmCacheManager.h"
20 #include <cmsys/Glob.hxx>
22 cmFindPathCommand::cmFindPathCommand()
24 this->EnvironmentPath
= "INCLUDE";
25 this->IncludeFileInPath
= false;
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
,
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
,
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 "CMAKE_FIND_ROOT_PATH_MODE_XXX",
50 "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE");
52 this->ExtraDocAdded
= false;
55 const char* cmFindPathCommand::GetFullDocumentation()
57 if(!this->ExtraDocAdded
&& !this->IncludeFileInPath
)
59 this->GenericDocumentation
+=
61 "When searching for frameworks, if the file is specified as "
62 "A/b.h, then the framework search will look for "
63 "A.framework/Headers/b.h. "
64 "If that is found the path will be set to the path to the framework. "
65 "CMake will convert this to the correct -F option to include the "
67 this->ExtraDocAdded
= true;
69 return this->GenericDocumentation
.c_str();
73 bool cmFindPathCommand
74 ::InitialPass(std::vector
<std::string
> const& argsIn
, cmExecutionStatus
&)
76 this->VariableDocumentation
= "Path to a file.";
77 this->CMakePathName
= "INCLUDE";
78 if(!this->ParseArguments(argsIn
))
82 if(this->AlreadyInCache
)
84 // If the user specifies the entry on the command line without a
85 // type we should add the type and docstring but keep the original
87 if(this->AlreadyInCacheWithoutMetaInfo
)
89 this->Makefile
->AddCacheDefinition(
90 this->VariableName
.c_str(), "",
91 this->VariableDocumentation
.c_str(),
92 (this->IncludeFileInPath
?
93 cmCacheManager::FILEPATH
:cmCacheManager::PATH
)
98 std::string ff
= this->Makefile
->GetSafeDefinition("CMAKE_FIND_FRAMEWORK");
99 bool supportFrameworks
= true;
100 if( ff
.size() == 0 || ff
== "NEVER" )
102 supportFrameworks
= false;
104 std::string framework
;
105 // Add a trailing slash to all paths to aid the search process.
106 for(std::vector
<std::string
>::iterator i
= this->SearchPaths
.begin();
107 i
!= this->SearchPaths
.end(); ++i
)
110 if(p
.empty() || p
[p
.size()-1] != '/')
115 // Use the search path to find the file.
118 for(k
=0; k
< this->SearchPaths
.size(); k
++)
120 for(unsigned int j
=0; j
< this->Names
.size(); ++j
)
122 // if frameworks are supported try to find the header in a framework
124 if(supportFrameworks
)
126 tryPath
= this->FindHeaderInFramework(this->Names
[j
],
127 this->SearchPaths
[k
]);
133 if(result
.size() == 0)
135 tryPath
= this->SearchPaths
[k
];
136 tryPath
+= this->Names
[j
];
137 if(cmSystemTools::FileExists(tryPath
.c_str()))
139 if(this->IncludeFileInPath
)
145 result
= this->SearchPaths
[k
];
149 if(result
.size() != 0)
151 this->Makefile
->AddCacheDefinition
152 (this->VariableName
.c_str(), result
.c_str(),
153 this->VariableDocumentation
.c_str(),
154 (this->IncludeFileInPath
) ?
155 cmCacheManager::FILEPATH
:cmCacheManager::PATH
);
160 this->Makefile
->AddCacheDefinition
161 (this->VariableName
.c_str(),
162 (this->VariableName
+ "-NOTFOUND").c_str(),
163 this->VariableDocumentation
.c_str(),
164 (this->IncludeFileInPath
) ?
165 cmCacheManager::FILEPATH
:cmCacheManager::PATH
);
169 std::string
cmFindPathCommand::FindHeaderInFramework(std::string
& file
,
172 cmStdString fileName
= file
;
173 cmStdString frameWorkName
;
174 cmStdString::size_type pos
= fileName
.find("/");
175 // if there is a / in the name try to find the header as a framework
176 // For example bar/foo.h would look for:
177 // bar.framework/Headers/foo.h
178 if(pos
!= fileName
.npos
)
180 // remove the name from the slash;
181 fileName
= fileName
.substr(pos
+1);
182 frameWorkName
= file
;
184 frameWorkName
.substr(0, frameWorkName
.size()-fileName
.size()-1);
185 // if the framework has a path in it then just use the filename
186 if(frameWorkName
.find("/") != frameWorkName
.npos
)
191 if(frameWorkName
.size())
193 std::string fpath
= dir
;
194 fpath
+= frameWorkName
;
195 fpath
+= ".framework";
196 std::string intPath
= fpath
;
197 intPath
+= "/Headers/";
199 if(cmSystemTools::FileExists(intPath
.c_str()))
201 if(this->IncludeFileInPath
)
209 // if it is not found yet or not a framework header, then do a glob search
210 // for all files in dir/*/Headers/
211 cmStdString glob
= dir
;
212 glob
+= "*/Headers/";
215 globIt
.FindFiles(glob
);
216 std::vector
<std::string
> files
= globIt
.GetFiles();
219 cmStdString fheader
= cmSystemTools::CollapseFullPath(files
[0].c_str());
220 if(this->IncludeFileInPath
)
224 fheader
= cmSystemTools::GetFilenamePath(fheader
);