cmOutputRequiredFilesCommand.cxx 7.2 KB

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