Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmDepends.cxx
bloba3178f2943277450665f4e171674706fdf2e6475
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmDepends.cxx,v $
5 Language: C++
6 <<<<<<< cmDepends.cxx
7 Date: $Date: 2007/12/28 16:49:59 $
8 Version: $Revision: 1.17 $
9 =======
10 Date: $Date: 2008-05-08 14:09:14 $
11 Version: $Revision: 1.18 $
12 >>>>>>> 1.18
14 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
15 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
17 This software is distributed WITHOUT ANY WARRANTY; without even
18 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 PURPOSE. See the above copyright notices for more information.
21 =========================================================================*/
22 #include "cmDepends.h"
24 #include "cmLocalGenerator.h"
25 #include "cmMakefile.h"
26 #include "cmGeneratedFileStream.h"
27 #include "cmSystemTools.h"
28 #include "cmFileTimeComparison.h"
29 #include <string.h>
31 //----------------------------------------------------------------------------
32 cmDepends::cmDepends(cmLocalGenerator* lg, const char* targetDir):
33 CompileDirectory(),
34 LocalGenerator(lg),
35 Verbose(false),
36 FileComparison(0),
37 TargetDirectory(targetDir),
38 MaxPath(cmSystemTools::GetMaximumFilePathLength()),
39 Dependee(new char[MaxPath]),
40 Depender(new char[MaxPath])
44 //----------------------------------------------------------------------------
45 cmDepends::~cmDepends()
47 delete [] this->Dependee;
48 delete [] this->Depender;
51 //----------------------------------------------------------------------------
52 bool cmDepends::Write(std::ostream &makeDepends,
53 std::ostream &internalDepends)
55 // Lookup the set of sources to scan.
56 std::string srcLang = "CMAKE_DEPENDS_CHECK_";
57 srcLang += this->Language;
58 cmMakefile* mf = this->LocalGenerator->GetMakefile();
59 const char* srcStr = mf->GetSafeDefinition(srcLang.c_str());
60 std::vector<std::string> pairs;
61 cmSystemTools::ExpandListArgument(srcStr, pairs);
63 for(std::vector<std::string>::iterator si = pairs.begin();
64 si != pairs.end();)
66 // Get the source and object file.
67 std::string const& src = *si++;
68 if(si == pairs.end()) { break; }
69 std::string obj = *si++;
71 // Make sure the object file is relative to the top of the build tree.
72 obj = this->LocalGenerator->Convert(obj.c_str(),
73 cmLocalGenerator::HOME_OUTPUT,
74 cmLocalGenerator::MAKEFILE);
76 // Write the dependencies for this pair.
77 if(!this->WriteDependencies(src.c_str(), obj.c_str(),
78 makeDepends, internalDepends))
80 return false;
84 return this->Finalize(makeDepends, internalDepends);
87 //----------------------------------------------------------------------------
88 bool cmDepends::Finalize(std::ostream&,
89 std::ostream&)
91 return true;
94 //----------------------------------------------------------------------------
95 bool cmDepends::Check(const char *makeFile, const char *internalFile)
97 // Dependency checks must be done in proper working directory.
98 std::string oldcwd = ".";
99 if(this->CompileDirectory != ".")
101 // Get the CWD but do not call CollapseFullPath because
102 // we only need it to cd back, and the form does not matter
103 oldcwd = cmSystemTools::GetCurrentWorkingDirectory(false);
104 cmSystemTools::ChangeDirectory(this->CompileDirectory.c_str());
107 // Check whether dependencies must be regenerated.
108 bool okay = true;
109 std::ifstream fin(internalFile);
110 if(!(fin && this->CheckDependencies(fin)))
112 // Clear all dependencies so they will be regenerated.
113 this->Clear(makeFile);
114 cmSystemTools::RemoveFile(internalFile);
115 okay = false;
118 // Restore working directory.
119 if(oldcwd != ".")
121 cmSystemTools::ChangeDirectory(oldcwd.c_str());
124 return okay;
127 //----------------------------------------------------------------------------
128 void cmDepends::Clear(const char *file)
130 // Print verbose output.
131 if(this->Verbose)
133 cmOStringStream msg;
134 msg << "Clearing dependencies in \"" << file << "\"." << std::endl;
135 cmSystemTools::Stdout(msg.str().c_str());
138 // Write an empty dependency file.
139 cmGeneratedFileStream depFileStream(file);
140 depFileStream
141 << "# Empty dependencies file\n"
142 << "# This may be replaced when dependencies are built." << std::endl;
145 //----------------------------------------------------------------------------
146 bool cmDepends::WriteDependencies(const char*, const char*,
147 std::ostream&, std::ostream&)
149 // This should be implemented by the subclass.
150 return false;
153 //----------------------------------------------------------------------------
154 bool cmDepends::CheckDependencies(std::istream& internalDepends)
156 // Parse dependencies from the stream. If any dependee is missing
157 // or newer than the depender then dependencies should be
158 // regenerated.
159 bool okay = true;
160 while(internalDepends.getline(this->Dependee, this->MaxPath))
162 if ( this->Dependee[0] == 0 || this->Dependee[0] == '#' ||
163 this->Dependee[0] == '\r' )
165 continue;
167 size_t len = internalDepends.gcount()-1;
168 if ( this->Dependee[len-1] == '\r' )
170 len --;
171 this->Dependee[len] = 0;
173 if ( this->Dependee[0] != ' ' )
175 memcpy(this->Depender, this->Dependee, len+1);
176 continue;
179 // Parse the dependency line.
180 if(!this->ParseDependency(line.c_str()))
182 continue;
186 // Dependencies must be regenerated if the dependee does not exist
187 // or if the depender exists and is older than the dependee.
188 bool regenerate = false;
189 const char* dependee = this->Dependee+1;
190 const char* depender = this->Depender;
191 if(!cmSystemTools::FileExists(dependee))
193 // The dependee does not exist.
194 regenerate = true;
196 // Print verbose output.
197 if(this->Verbose)
199 cmOStringStream msg;
200 msg << "Dependee \"" << dependee
201 << "\" does not exist for depender \""
202 << depender << "\"." << std::endl;
203 cmSystemTools::Stdout(msg.str().c_str());
206 else if(cmSystemTools::FileExists(depender))
208 // The dependee and depender both exist. Compare file times.
209 int result = 0;
210 if((!this->FileComparison->FileTimeCompare(depender, dependee,
211 &result) || result < 0))
213 // The depender is older than the dependee.
214 regenerate = true;
216 // Print verbose output.
217 if(this->Verbose)
219 cmOStringStream msg;
220 msg << "Dependee \"" << dependee
221 << "\" is newer than depender \""
222 << depender << "\"." << std::endl;
223 cmSystemTools::Stdout(msg.str().c_str());
227 if(regenerate)
229 // Dependencies must be regenerated.
230 okay = false;
232 // Remove the depender to be sure it is rebuilt.
233 cmSystemTools::RemoveFile(depender);
237 return okay;
240 //----------------------------------------------------------------------------
241 void cmDepends::SetIncludePathFromLanguage(const char* lang)
243 std::string includePathVar = "CMAKE_";
244 includePathVar += lang;
245 includePathVar += "_INCLUDE_PATH";
246 cmMakefile* mf = this->LocalGenerator->GetMakefile();
247 if(const char* includePath = mf->GetDefinition(includePathVar.c_str()))
249 cmSystemTools::ExpandListArgument(includePath, this->IncludePath);