cmOutputRequiredFilesCommand.cxx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmOutputRequiredFilesCommand.h"
  14. #include "cmMakeDepend.h"
  15. class cmLBDepend : public cmMakeDepend
  16. {
  17. /**
  18. * Compute the depend information for this class.
  19. */
  20. virtual void DependWalk(cmDependInformation* info);
  21. };
  22. void cmLBDepend::DependWalk(cmDependInformation* info)
  23. {
  24. std::ifstream fin(info->m_FullPath.c_str());
  25. if(!fin)
  26. {
  27. cmSystemTools::Error("error can not open ", info->m_FullPath.c_str());
  28. return;
  29. }
  30. std::string line;
  31. while(cmSystemTools::GetLineFromStream(fin, line))
  32. {
  33. if(!strncmp(line.c_str(), "#include", 8))
  34. {
  35. // if it is an include line then create a string class
  36. std::string currentline = line;
  37. size_t qstart = currentline.find('\"', 8);
  38. size_t qend;
  39. // if a quote is not found look for a <
  40. if(qstart == std::string::npos)
  41. {
  42. qstart = currentline.find('<', 8);
  43. // if a < is not found then move on
  44. if(qstart == std::string::npos)
  45. {
  46. cmSystemTools::Error("unknown include directive ",
  47. currentline.c_str() );
  48. continue;
  49. }
  50. else
  51. {
  52. qend = currentline.find('>', qstart+1);
  53. }
  54. }
  55. else
  56. {
  57. qend = currentline.find('\"', qstart+1);
  58. }
  59. // extract the file being included
  60. std::string includeFile = currentline.substr(qstart+1, qend - qstart-1);
  61. // see if the include matches the regular expression
  62. if(!m_IncludeFileRegularExpression.find(includeFile))
  63. {
  64. if(m_Verbose)
  65. {
  66. std::string message = "Skipping ";
  67. message += includeFile;
  68. message += " for file ";
  69. message += info->m_FullPath.c_str();
  70. cmSystemTools::Error(message.c_str(), 0);
  71. }
  72. continue;
  73. }
  74. // Add this file and all its dependencies.
  75. this->AddDependency(info, includeFile.c_str());
  76. /// add the cxx file if it exists
  77. std::string cxxFile = includeFile;
  78. std::string::size_type pos = cxxFile.rfind('.');
  79. if(pos != std::string::npos)
  80. {
  81. std::string root = cxxFile.substr(0, pos);
  82. cxxFile = root + ".cxx";
  83. bool found = false;
  84. // try jumping to .cxx .cpp and .c in order
  85. if(cmSystemTools::FileExists(cxxFile.c_str()))
  86. {
  87. found = true;
  88. }
  89. for(std::vector<std::string>::iterator i =
  90. m_IncludeDirectories.begin();
  91. i != m_IncludeDirectories.end(); ++i)
  92. {
  93. std::string path = *i;
  94. path = path + "/";
  95. path = path + cxxFile;
  96. if(cmSystemTools::FileExists(path.c_str()))
  97. {
  98. found = true;
  99. }
  100. }
  101. if (!found)
  102. {
  103. cxxFile = root + ".cpp";
  104. if(cmSystemTools::FileExists(cxxFile.c_str()))
  105. {
  106. found = true;
  107. }
  108. for(std::vector<std::string>::iterator i =
  109. m_IncludeDirectories.begin();
  110. i != m_IncludeDirectories.end(); ++i)
  111. {
  112. std::string path = *i;
  113. path = path + "/";
  114. path = path + cxxFile;
  115. if(cmSystemTools::FileExists(path.c_str()))
  116. {
  117. found = true;
  118. }
  119. }
  120. }
  121. if (!found)
  122. {
  123. cxxFile = root + ".c";
  124. if(cmSystemTools::FileExists(cxxFile.c_str()))
  125. {
  126. found = true;
  127. }
  128. for(std::vector<std::string>::iterator i =
  129. m_IncludeDirectories.begin();
  130. i != m_IncludeDirectories.end(); ++i)
  131. {
  132. std::string path = *i;
  133. path = path + "/";
  134. path = path + cxxFile;
  135. if(cmSystemTools::FileExists(path.c_str()))
  136. {
  137. found = true;
  138. }
  139. }
  140. }
  141. if (found)
  142. {
  143. this->AddDependency(info, cxxFile.c_str());
  144. }
  145. }
  146. }
  147. }
  148. }
  149. // cmOutputRequiredFilesCommand
  150. bool cmOutputRequiredFilesCommand::InitialPass(std::vector<std::string> const& args)
  151. {
  152. if(args.size() != 2 )
  153. {
  154. this->SetError("called with incorrect number of arguments");
  155. return false;
  156. }
  157. // store the arg for final pass
  158. m_File = args[0];
  159. m_OutputFile = args[1];
  160. return true;
  161. }
  162. void cmOutputRequiredFilesCommand::
  163. ListDependencies(cmDependInformation const *info,
  164. FILE *fout,
  165. std::set<cmDependInformation const*> *visited)
  166. {
  167. // add info to the visited set
  168. visited->insert(info);
  169. // now recurse with info's dependencies
  170. for(cmDependInformation::DependencySet::const_iterator d =
  171. info->m_DependencySet.begin();
  172. d != info->m_DependencySet.end(); ++d)
  173. {
  174. if (visited->find(*d) == visited->end())
  175. {
  176. if(info->m_FullPath != "")
  177. {
  178. std::string tmp = (*d)->m_FullPath;
  179. std::string::size_type pos = tmp.rfind('.');
  180. if(pos != std::string::npos && tmp.substr(pos) == ".cxx")
  181. {
  182. tmp = tmp.substr(0, pos);
  183. fprintf(fout,"%s\n",(*d)->m_FullPath.c_str());
  184. }
  185. }
  186. this->ListDependencies(*d,fout,visited);
  187. }
  188. }
  189. }
  190. void cmOutputRequiredFilesCommand::FinalPass()
  191. {
  192. cmTargets &tgts = m_Makefile->GetTargets();
  193. for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
  194. {
  195. l->second.GenerateSourceFilesFromSourceLists(*m_Makefile);
  196. }
  197. // compute the list of files
  198. cmLBDepend md;
  199. md.SetMakefile(m_Makefile);
  200. // find the depends for a file
  201. const cmDependInformation *info = md.FindDependencies(m_File.c_str());
  202. if (info)
  203. {
  204. // write them out
  205. FILE *fout = fopen(m_OutputFile.c_str(),"w");
  206. std::set<cmDependInformation const*> visited;
  207. this->ListDependencies(info,fout, &visited);
  208. fclose(fout);
  209. }
  210. }