cmOutputRequiredFilesCommand.cxx 7.2 KB

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