cmOutputRequiredFilesCommand.cxx 7.1 KB

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