cmExportLibraryDependencies.cxx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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 "cmExportLibraryDependencies.h"
  14. #include "cmGlobalGenerator.h"
  15. #include "cmLocalGenerator.h"
  16. #include "cmGeneratedFileStream.h"
  17. #include "cmake.h"
  18. #include <cmsys/auto_ptr.hxx>
  19. bool cmExportLibraryDependenciesCommand
  20. ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
  21. {
  22. if(args.size() < 1 )
  23. {
  24. this->SetError("called with incorrect number of arguments");
  25. return false;
  26. }
  27. // store the arguments for the final pass
  28. this->Filename = args[0];
  29. this->Append = false;
  30. if(args.size() > 1)
  31. {
  32. if(args[1] == "APPEND")
  33. {
  34. this->Append = true;
  35. }
  36. }
  37. return true;
  38. }
  39. void cmExportLibraryDependenciesCommand::FinalPass()
  40. {
  41. // export_library_dependencies() shouldn't modify anything
  42. // ensure this by calling a const method
  43. this->ConstFinalPass();
  44. }
  45. void cmExportLibraryDependenciesCommand::ConstFinalPass() const
  46. {
  47. // Use copy-if-different if not appending.
  48. cmsys::auto_ptr<std::ofstream> foutPtr;
  49. if(this->Append)
  50. {
  51. cmsys::auto_ptr<std::ofstream> ap(
  52. new std::ofstream(this->Filename.c_str(), std::ios::app));
  53. foutPtr = ap;
  54. }
  55. else
  56. {
  57. cmsys::auto_ptr<cmGeneratedFileStream> ap(
  58. new cmGeneratedFileStream(this->Filename.c_str(), true));
  59. ap->SetCopyIfDifferent(true);
  60. foutPtr = ap;
  61. }
  62. std::ostream& fout = *foutPtr.get();
  63. if (!fout)
  64. {
  65. cmSystemTools::Error("Error Writing ", this->Filename.c_str());
  66. cmSystemTools::ReportLastSystemError("");
  67. return;
  68. }
  69. // Collect dependency information about all library targets built in
  70. // the project.
  71. const cmake* cm = this->Makefile->GetCMakeInstance();
  72. const cmGlobalGenerator* global = cm->GetGlobalGenerator();
  73. const std::vector<cmLocalGenerator *>& locals = global->GetLocalGenerators();
  74. std::map<cmStdString, cmStdString> libDepsOld;
  75. std::map<cmStdString, cmStdString> libDepsNew;
  76. std::map<cmStdString, cmStdString> libTypes;
  77. for(std::vector<cmLocalGenerator *>::const_iterator i = locals.begin();
  78. i != locals.end(); ++i)
  79. {
  80. const cmLocalGenerator* gen = *i;
  81. const cmTargets &tgts = gen->GetMakefile()->GetTargets();
  82. for(cmTargets::const_iterator l = tgts.begin();
  83. l != tgts.end(); ++l)
  84. {
  85. // Get the current target.
  86. cmTarget const& target = l->second;
  87. // Skip non-library targets.
  88. if(target.GetType() < cmTarget::STATIC_LIBRARY
  89. || target.GetType() > cmTarget::MODULE_LIBRARY)
  90. {
  91. continue;
  92. }
  93. // Construct the dependency variable name.
  94. std::string targetEntry = target.GetName();
  95. targetEntry += "_LIB_DEPENDS";
  96. // Construct the dependency variable value. It is safe to use
  97. // the target GetLinkLibraries method here because this code is
  98. // called at the end of configure but before generate so library
  99. // dependencies have yet to be analyzed. Therefore the value
  100. // will be the direct link dependencies.
  101. std::string valueOld;
  102. std::string valueNew;
  103. cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries();
  104. for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
  105. li != libs.end(); ++li)
  106. {
  107. std::string ltVar = li->first;
  108. ltVar += "_LINK_TYPE";
  109. std::string ltValue;
  110. switch(li->second)
  111. {
  112. case cmTarget::GENERAL:
  113. valueNew += "general;";
  114. ltValue = "general";
  115. break;
  116. case cmTarget::DEBUG:
  117. valueNew += "debug;";
  118. ltValue = "debug";
  119. break;
  120. case cmTarget::OPTIMIZED:
  121. valueNew += "optimized;";
  122. ltValue = "optimized";
  123. break;
  124. }
  125. valueOld += li->first;
  126. valueOld += ";";
  127. valueNew += li->first;
  128. valueNew += ";";
  129. std::string& ltEntry = libTypes[ltVar];
  130. if(ltEntry.empty())
  131. {
  132. ltEntry = ltValue;
  133. }
  134. else if(ltEntry != ltValue)
  135. {
  136. ltEntry = "general";
  137. }
  138. }
  139. libDepsNew[targetEntry] = valueNew;
  140. libDepsOld[targetEntry] = valueOld;
  141. }
  142. }
  143. // Generate dependency information for both old and new style CMake
  144. // versions.
  145. const char* vertest =
  146. "\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" GREATER 2.4";
  147. fout << "IF(" << vertest << ")\n";
  148. fout << " # Information for CMake 2.6 and above.\n";
  149. for(std::map<cmStdString, cmStdString>::const_iterator i = libDepsNew.begin();
  150. i != libDepsNew.end(); ++i)
  151. {
  152. if(!i->second.empty())
  153. {
  154. fout << " SET(\"" << i->first << "\" \"" << i->second << "\")\n";
  155. }
  156. }
  157. fout << "ELSE(" << vertest << ")\n";
  158. fout << " # Information for CMake 2.4 and lower.\n";
  159. for(std::map<cmStdString, cmStdString>::const_iterator i = libDepsOld.begin();
  160. i != libDepsOld.end(); ++i)
  161. {
  162. if(!i->second.empty())
  163. {
  164. fout << " SET(\"" << i->first << "\" \"" << i->second << "\")\n";
  165. }
  166. }
  167. for(std::map<cmStdString, cmStdString>::const_iterator i = libTypes.begin();
  168. i != libTypes.end(); ++i)
  169. {
  170. if(i->second != "general")
  171. {
  172. fout << " SET(\"" << i->first << "\" \"" << i->second << "\")\n";
  173. }
  174. }
  175. fout << "ENDIF(" << vertest << ")\n";
  176. return;
  177. }