1 /*=========================================================================
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: cmMakeDepend.cxx,v $
6 Date: $Date: 2002-06-27 19:57:09 $
7 Version: $Revision: 1.30 $
9 Copyright (c) 2002 Insight Consortium. All rights reserved.
10 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 "cmMakeDepend.h"
18 #include "cmStandardIncludes.h"
19 #include "cmSystemTools.h"
22 void cmDependInformation::AddDependencies(cmDependInformation
* info
)
26 m_DependencySet
.insert(info
);
27 for (cmDependInformation::DependencySet::const_iterator
28 d
= info
->m_DependencySet
.begin();
29 d
!= info
->m_DependencySet
.end(); ++d
)
31 m_DependencySet
.insert(*d
);
36 cmMakeDepend::cmMakeDepend()
39 m_IncludeFileRegularExpression
.compile("^.*$");
40 m_ComplainFileRegularExpression
.compile("^$");
44 cmMakeDepend::~cmMakeDepend()
46 for(DependInformationMap::iterator i
= m_DependInformationMap
.begin();
47 i
!= m_DependInformationMap
.end(); ++i
)
54 // Set the makefile that depends will be made from.
55 // The pointer is kept so the cmSourceFile array can
56 // be updated with the depend information in the cmMakefile.
58 void cmMakeDepend::SetMakefile(const cmMakefile
* makefile
)
60 m_Makefile
= makefile
;
62 // Now extract the include file regular expression from the makefile.
63 m_IncludeFileRegularExpression
.compile(
64 m_Makefile
->m_IncludeFileRegularExpression
.c_str());
65 m_ComplainFileRegularExpression
.compile(
66 m_Makefile
->m_ComplainFileRegularExpression
.c_str());
68 // Now extract any include paths from the makefile flags
69 const std::vector
<std::string
>& includes
=
70 m_Makefile
->GetIncludeDirectories();
71 for(std::vector
<std::string
>::const_iterator j
= includes
.begin();
72 j
!= includes
.end(); ++j
)
74 std::string path
= *j
;
75 m_Makefile
->ExpandVariablesInString(path
);
76 this->AddSearchPath(path
.c_str());
81 const cmDependInformation
* cmMakeDepend::FindDependencies(const char* file
)
83 cmDependInformation
* info
= this->GetDependInformation(file
,NULL
);
84 this->GenerateDependInformation(info
);
88 void cmMakeDepend::GenerateDependInformation(cmDependInformation
* info
)
90 // If dependencies are already done, stop now.
91 if(info
->m_DependDone
)
97 // Make sure we don't visit the same file more than once.
98 info
->m_DependDone
= true;
100 const char* path
= info
->m_FullPath
.c_str();
103 cmSystemTools::Error("Attempt to find dependencies for file without path!");
109 // If the file exists, use it to find dependency information.
110 if(cmSystemTools::FileExists(path
))
112 // Use the real file to find its dependencies.
113 this->DependWalk(info
);
118 // See if the cmSourceFile for it has any files specified as
120 if(info
->m_cmSourceFile
!= 0)
123 // Get the cmSourceFile corresponding to this.
124 const cmSourceFile
& cFile
= *(info
->m_cmSourceFile
);
125 // See if there are any hints for finding dependencies for the missing
127 if(!cFile
.GetDepends().empty())
129 // Dependency hints have been given. Use them to begin the
131 for(std::vector
<std::string
>::const_iterator file
=
132 cFile
.GetDepends().begin(); file
!= cFile
.GetDepends().end();
135 this->AddDependency(info
, file
->c_str());
138 // Found dependency information. We are done.
145 // Try to find the file amongst the sources
146 cmSourceFile
*srcFile
=
147 m_Makefile
->GetSource(cmSystemTools::GetFilenameWithoutExtension(path
).c_str());
150 if (srcFile
->GetFullPath() == path
)
156 //try to guess which include path to use
157 for(std::vector
<std::string
>::iterator t
=
158 m_IncludeDirectories
.begin();
159 t
!= m_IncludeDirectories
.end(); ++t
)
161 std::string incpath
= *t
;
162 incpath
= incpath
+ "/";
163 incpath
= incpath
+ path
;
164 if (srcFile
->GetFullPath() == incpath
)
166 // set the path to the guessed path
167 info
->m_FullPath
= incpath
;
177 // Couldn't find any dependency information.
178 if(m_ComplainFileRegularExpression
.find(info
->m_IncludeName
.c_str()))
180 cmSystemTools::Error("error cannot find dependencies for ", path
);
184 // Destroy the name of the file so that it won't be output as a
186 info
->m_FullPath
= "";
191 // This function actually reads the file specified and scans it for
192 // #include directives
193 void cmMakeDepend::DependWalk(cmDependInformation
* info
)
195 cmRegularExpression
includeLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]");
196 std::ifstream
fin(info
->m_FullPath
.c_str());
199 cmSystemTools::Error("Cannot open ", info
->m_FullPath
.c_str());
203 // TODO: Write real read loop (see cmSystemTools::CopyFile).
205 for(fin
.getline(line
, 255); fin
; fin
.getline(line
, 255))
207 if(includeLine
.find(line
))
209 // extract the file being included
210 std::string includeFile
= includeLine
.match(1);
211 // see if the include matches the regular expression
212 if(!m_IncludeFileRegularExpression
.find(includeFile
))
216 std::string message
= "Skipping ";
217 message
+= includeFile
;
218 message
+= " for file ";
219 message
+= info
->m_FullPath
.c_str();
220 cmSystemTools::Error(message
.c_str(), 0);
225 // Add this file and all its dependencies.
226 this->AddDependency(info
, includeFile
.c_str());
232 void cmMakeDepend::AddDependency(cmDependInformation
* info
, const char* file
)
234 cmDependInformation
* dependInfo
=
235 this->GetDependInformation(file
,
236 cmSystemTools::GetFilenamePath(
237 cmSystemTools::CollapseFullPath(
238 info
->m_FullPath
.c_str())).c_str());
239 this->GenerateDependInformation(dependInfo
);
240 info
->AddDependencies(dependInfo
);
243 cmDependInformation
* cmMakeDepend::GetDependInformation(const char* file
,
244 const char *extraPath
)
246 // Get the full path for the file so that lookup is unambiguous.
247 std::string fullPath
= this->FullPath(file
, extraPath
);
249 // Try to find the file's instance of cmDependInformation.
250 DependInformationMap::const_iterator result
=
251 m_DependInformationMap
.find(fullPath
);
252 if(result
!= m_DependInformationMap
.end())
254 // Found an instance, return it.
255 return result
->second
;
259 // Didn't find an instance. Create a new one and save it.
260 cmDependInformation
* info
= new cmDependInformation
;
261 info
->m_FullPath
= fullPath
;
262 info
->m_IncludeName
= file
;
263 m_DependInformationMap
[fullPath
] = info
;
269 void cmMakeDepend::GenerateMakefileDependencies()
271 // Now create cmDependInformation objects for files in the directory
272 const cmTargets
&tgts
= m_Makefile
->GetTargets();
273 for(cmTargets::const_iterator l
= tgts
.begin();
274 l
!= tgts
.end(); l
++)
276 const std::vector
<cmSourceFile
*> &classes
= l
->second
.GetSourceFiles();
277 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
278 i
!= classes
.end(); ++i
)
280 if(!(*i
)->GetIsAHeaderFileOnly())
282 cmDependInformation
* info
=
283 this->GetDependInformation((*i
)->GetFullPath().c_str(),NULL
);
284 this->AddFileToSearchPath(info
->m_FullPath
.c_str());
285 info
->m_cmSourceFile
= *i
;
286 this->GenerateDependInformation(info
);
293 // find the full path to fname by searching the m_IncludeDirectories array
294 std::string
cmMakeDepend::FullPath(const char* fname
, const char *extraPath
)
296 if(cmSystemTools::FileExists(fname
))
298 return std::string(cmSystemTools::CollapseFullPath(fname
));
301 for(std::vector
<std::string
>::iterator i
= m_IncludeDirectories
.begin();
302 i
!= m_IncludeDirectories
.end(); ++i
)
304 std::string path
= *i
;
307 if(cmSystemTools::FileExists(path
.c_str()))
309 return cmSystemTools::CollapseFullPath(path
.c_str());
315 std::string path
= extraPath
;
318 if(cmSystemTools::FileExists(path
.c_str()))
320 return cmSystemTools::CollapseFullPath(path
.c_str());
324 // Couldn't find the file.
325 return std::string(fname
);
328 // Add a directory to the search path
329 void cmMakeDepend::AddSearchPath(const char* path
)
331 m_IncludeDirectories
.push_back(path
);
334 // Add a directory to the search path
335 void cmMakeDepend::AddFileToSearchPath(const char* file
)
337 std::string filepath
= file
;
338 std::string::size_type pos
= filepath
.rfind('/');
339 if(pos
!= std::string::npos
)
341 std::string path
= filepath
.substr(0, pos
);
342 if(std::find(m_IncludeDirectories
.begin(),
343 m_IncludeDirectories
.end(), path
)
344 == m_IncludeDirectories
.end())
346 m_IncludeDirectories
.push_back(path
);
352 const cmDependInformation
*
353 cmMakeDepend::GetDependInformationForSourceFile(const cmSourceFile
&sf
) const
355 for(DependInformationMap::const_iterator i
= m_DependInformationMap
.begin();
356 i
!= m_DependInformationMap
.end(); ++i
)
358 const cmDependInformation
* info
= i
->second
;
359 if(info
->m_cmSourceFile
== &sf
)