Introduce "generator expressions" to add_test()
[cmake.git] / Source / cmOutputRequiredFilesCommand.cxx
blobf07789c2249e452adb20b1a2b9290beb61f87eb3
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmOutputRequiredFilesCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2008-10-10 14:48:10 $
7 Version: $Revision: 1.17 $
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 "cmOutputRequiredFilesCommand.h"
18 #include "cmMakeDepend.h"
20 class cmLBDepend : public cmMakeDepend
22 /**
23 * Compute the depend information for this class.
25 virtual void DependWalk(cmDependInformation* info);
28 void cmLBDepend::DependWalk(cmDependInformation* info)
30 std::ifstream fin(info->FullPath.c_str());
31 if(!fin)
33 cmSystemTools::Error("error can not open ", info->FullPath.c_str());
34 return;
37 std::string line;
38 while(cmSystemTools::GetLineFromStream(fin, line))
40 if(!strncmp(line.c_str(), "#include", 8))
42 // if it is an include line then create a string class
43 std::string currentline = line;
44 size_t qstart = currentline.find('\"', 8);
45 size_t qend;
46 // if a quote is not found look for a <
47 if(qstart == std::string::npos)
49 qstart = currentline.find('<', 8);
50 // if a < is not found then move on
51 if(qstart == std::string::npos)
53 cmSystemTools::Error("unknown include directive ",
54 currentline.c_str() );
55 continue;
57 else
59 qend = currentline.find('>', qstart+1);
62 else
64 qend = currentline.find('\"', qstart+1);
66 // extract the file being included
67 std::string includeFile = currentline.substr(qstart+1, qend - qstart-1);
68 // see if the include matches the regular expression
69 if(!this->IncludeFileRegularExpression.find(includeFile))
71 if(this->Verbose)
73 std::string message = "Skipping ";
74 message += includeFile;
75 message += " for file ";
76 message += info->FullPath.c_str();
77 cmSystemTools::Error(message.c_str(), 0);
79 continue;
82 // Add this file and all its dependencies.
83 this->AddDependency(info, includeFile.c_str());
84 /// add the cxx file if it exists
85 std::string cxxFile = includeFile;
86 std::string::size_type pos = cxxFile.rfind('.');
87 if(pos != std::string::npos)
89 std::string root = cxxFile.substr(0, pos);
90 cxxFile = root + ".cxx";
91 bool found = false;
92 // try jumping to .cxx .cpp and .c in order
93 if(cmSystemTools::FileExists(cxxFile.c_str()))
95 found = true;
97 for(std::vector<std::string>::iterator i =
98 this->IncludeDirectories.begin();
99 i != this->IncludeDirectories.end(); ++i)
101 std::string path = *i;
102 path = path + "/";
103 path = path + cxxFile;
104 if(cmSystemTools::FileExists(path.c_str()))
106 found = true;
109 if (!found)
111 cxxFile = root + ".cpp";
112 if(cmSystemTools::FileExists(cxxFile.c_str()))
114 found = true;
116 for(std::vector<std::string>::iterator i =
117 this->IncludeDirectories.begin();
118 i != this->IncludeDirectories.end(); ++i)
120 std::string path = *i;
121 path = path + "/";
122 path = path + cxxFile;
123 if(cmSystemTools::FileExists(path.c_str()))
125 found = true;
129 if (!found)
131 cxxFile = root + ".c";
132 if(cmSystemTools::FileExists(cxxFile.c_str()))
134 found = true;
136 for(std::vector<std::string>::iterator i =
137 this->IncludeDirectories.begin();
138 i != this->IncludeDirectories.end(); ++i)
140 std::string path = *i;
141 path = path + "/";
142 path = path + cxxFile;
143 if(cmSystemTools::FileExists(path.c_str()))
145 found = true;
149 if (!found)
151 cxxFile = root + ".txx";
152 if(cmSystemTools::FileExists(cxxFile.c_str()))
154 found = true;
156 for(std::vector<std::string>::iterator i =
157 this->IncludeDirectories.begin();
158 i != this->IncludeDirectories.end(); ++i)
160 std::string path = *i;
161 path = path + "/";
162 path = path + cxxFile;
163 if(cmSystemTools::FileExists(path.c_str()))
165 found = true;
169 if (found)
171 this->AddDependency(info, cxxFile.c_str());
178 // cmOutputRequiredFilesCommand
179 bool cmOutputRequiredFilesCommand
180 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
182 if(args.size() != 2 )
184 this->SetError("called with incorrect number of arguments");
185 return false;
188 // store the arg for final pass
189 this->File = args[0];
190 this->OutputFile = args[1];
192 // compute the list of files
193 cmLBDepend md;
194 md.SetMakefile(this->Makefile);
195 md.AddSearchPath(this->Makefile->GetStartDirectory());
196 // find the depends for a file
197 const cmDependInformation *info = md.FindDependencies(this->File.c_str());
198 if (info)
200 // write them out
201 FILE *fout = fopen(this->OutputFile.c_str(),"w");
202 if(!fout)
204 std::string err = "Can not open output file: ";
205 err += this->OutputFile;
206 this->SetError(err.c_str());
207 return false;
209 std::set<cmDependInformation const*> visited;
210 this->ListDependencies(info,fout, &visited);
211 fclose(fout);
214 return true;
217 void cmOutputRequiredFilesCommand::
218 ListDependencies(cmDependInformation const *info,
219 FILE *fout,
220 std::set<cmDependInformation const*> *visited)
222 // add info to the visited set
223 visited->insert(info);
224 // now recurse with info's dependencies
225 for(cmDependInformation::DependencySetType::const_iterator d =
226 info->DependencySet.begin();
227 d != info->DependencySet.end(); ++d)
229 if (visited->find(*d) == visited->end())
231 if(info->FullPath != "")
233 std::string tmp = (*d)->FullPath;
234 std::string::size_type pos = tmp.rfind('.');
235 if(pos != std::string::npos && (tmp.substr(pos) != ".h"))
237 tmp = tmp.substr(0, pos);
238 fprintf(fout,"%s\n",(*d)->FullPath.c_str());
241 this->ListDependencies(*d,fout,visited);