Imported Upstream version 2.8.12.2
[platform/upstream/cmake.git] / Source / cmOutputRequiredFilesCommand.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 "cmOutputRequiredFilesCommand.h"
13 #include "cmMakeDepend.h"
14
15 class cmLBDepend : public cmMakeDepend
16 {
17   /**
18    * Compute the depend information for this class.
19    */
20   virtual void DependWalk(cmDependInformation* info);
21 };
22
23 void cmLBDepend::DependWalk(cmDependInformation* info)
24 {
25   std::ifstream fin(info->FullPath.c_str());
26   if(!fin)
27     {
28     cmSystemTools::Error("error can not open ", info->FullPath.c_str());
29     return;
30     }
31
32   std::string line;
33   while(cmSystemTools::GetLineFromStream(fin, line))
34     {
35     if(!strncmp(line.c_str(), "#include", 8))
36       {
37       // if it is an include line then create a string class
38       std::string currentline = line;
39       size_t qstart = currentline.find('\"', 8);
40       size_t qend;
41       // if a quote is not found look for a <
42       if(qstart == std::string::npos)
43         {
44         qstart = currentline.find('<', 8);
45         // if a < is not found then move on
46         if(qstart == std::string::npos)
47           {
48           cmSystemTools::Error("unknown include directive ",
49                                currentline.c_str() );
50           continue;
51           }
52         else
53           {
54           qend = currentline.find('>', qstart+1);
55           }
56         }
57       else
58         {
59         qend = currentline.find('\"', qstart+1);
60         }
61       // extract the file being included
62       std::string includeFile = currentline.substr(qstart+1, qend - qstart-1);
63       // see if the include matches the regular expression
64       if(!this->IncludeFileRegularExpression.find(includeFile))
65         {
66         if(this->Verbose)
67           {
68           std::string message = "Skipping ";
69           message += includeFile;
70           message += " for file ";
71           message += info->FullPath.c_str();
72           cmSystemTools::Error(message.c_str(), 0);
73           }
74         continue;
75         }
76
77       // Add this file and all its dependencies.
78       this->AddDependency(info, includeFile.c_str());
79       /// add the cxx file if it exists
80       std::string cxxFile = includeFile;
81       std::string::size_type pos = cxxFile.rfind('.');
82       if(pos != std::string::npos)
83         {
84         std::string root = cxxFile.substr(0, pos);
85         cxxFile = root + ".cxx";
86         bool found = false;
87         // try jumping to .cxx .cpp and .c in order
88         if(cmSystemTools::FileExists(cxxFile.c_str()))
89           {
90           found = true;
91           }
92         for(std::vector<std::string>::iterator i =
93               this->IncludeDirectories.begin();
94             i != this->IncludeDirectories.end(); ++i)
95           {
96           std::string path = *i;
97           path = path + "/";
98           path = path + cxxFile;
99           if(cmSystemTools::FileExists(path.c_str()))
100             {
101             found = true;
102             }
103           }
104         if (!found)
105           {
106           cxxFile = root + ".cpp";
107           if(cmSystemTools::FileExists(cxxFile.c_str()))
108             {
109             found = true;
110             }
111           for(std::vector<std::string>::iterator i =
112                 this->IncludeDirectories.begin();
113               i != this->IncludeDirectories.end(); ++i)
114             {
115             std::string path = *i;
116             path = path + "/";
117             path = path + cxxFile;
118             if(cmSystemTools::FileExists(path.c_str()))
119               {
120               found = true;
121               }
122             }
123           }
124         if (!found)
125           {
126           cxxFile = root + ".c";
127           if(cmSystemTools::FileExists(cxxFile.c_str()))
128             {
129             found = true;
130             }
131           for(std::vector<std::string>::iterator i =
132                 this->IncludeDirectories.begin();
133               i != this->IncludeDirectories.end(); ++i)
134             {
135             std::string path = *i;
136             path = path + "/";
137             path = path + cxxFile;
138             if(cmSystemTools::FileExists(path.c_str()))
139               {
140               found = true;
141               }
142             }
143           }
144         if (!found)
145           {
146           cxxFile = root + ".txx";
147           if(cmSystemTools::FileExists(cxxFile.c_str()))
148             {
149             found = true;
150             }
151           for(std::vector<std::string>::iterator i =
152                 this->IncludeDirectories.begin();
153               i != this->IncludeDirectories.end(); ++i)
154             {
155             std::string path = *i;
156             path = path + "/";
157             path = path + cxxFile;
158             if(cmSystemTools::FileExists(path.c_str()))
159               {
160               found = true;
161               }
162             }
163           }
164         if (found)
165           {
166           this->AddDependency(info, cxxFile.c_str());
167           }
168         }
169       }
170     }
171 }
172
173 // cmOutputRequiredFilesCommand
174 bool cmOutputRequiredFilesCommand
175 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
176 {
177   if(args.size() != 2 )
178     {
179     this->SetError("called with incorrect number of arguments");
180     return false;
181     }
182
183   // store the arg for final pass
184   this->File = args[0];
185   this->OutputFile = args[1];
186
187   // compute the list of files
188   cmLBDepend md;
189   md.SetMakefile(this->Makefile);
190   md.AddSearchPath(this->Makefile->GetStartDirectory());
191   // find the depends for a file
192   const cmDependInformation *info = md.FindDependencies(this->File.c_str());
193   if (info)
194     {
195     // write them out
196     FILE *fout = fopen(this->OutputFile.c_str(),"w");
197     if(!fout)
198       {
199       std::string err = "Can not open output file: ";
200       err += this->OutputFile;
201       this->SetError(err.c_str());
202       return false;
203       }
204     std::set<cmDependInformation const*> visited;
205     this->ListDependencies(info,fout, &visited);
206     fclose(fout);
207     }
208
209   return true;
210 }
211
212 void cmOutputRequiredFilesCommand::
213 ListDependencies(cmDependInformation const *info,
214                  FILE *fout,
215                  std::set<cmDependInformation const*> *visited)
216 {
217   // add info to the visited set
218   visited->insert(info);
219   // now recurse with info's dependencies
220   for(cmDependInformation::DependencySetType::const_iterator d =
221         info->DependencySet.begin();
222       d != info->DependencySet.end(); ++d)
223     {
224     if (visited->find(*d) == visited->end())
225       {
226       if(info->FullPath != "")
227         {
228         std::string tmp = (*d)->FullPath;
229         std::string::size_type pos = tmp.rfind('.');
230         if(pos != std::string::npos && (tmp.substr(pos) != ".h"))
231           {
232           tmp = tmp.substr(0, pos);
233           fprintf(fout,"%s\n",(*d)->FullPath.c_str());
234           }
235         }
236       this->ListDependencies(*d,fout,visited);
237       }
238     }
239 }
240