cmExportLibraryDependenciesCommand.cxx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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 "cmExportLibraryDependenciesCommand.h"
  11. #include "cmGeneratedFileStream.h"
  12. #include "cmGlobalGenerator.h"
  13. #include "cmVersion.h"
  14. #include "cmake.h"
  15. #include <cm_auto_ptr.hxx>
  16. bool cmExportLibraryDependenciesCommand::InitialPass(
  17. std::vector<std::string> const& args, cmExecutionStatus&)
  18. {
  19. if (this->Disallowed(
  20. cmPolicies::CMP0033,
  21. "The export_library_dependencies command should not be called; "
  22. "see CMP0033.")) {
  23. return true;
  24. }
  25. if (args.size() < 1) {
  26. this->SetError("called with incorrect number of arguments");
  27. return false;
  28. }
  29. // store the arguments for the final pass
  30. this->Filename = args[0];
  31. this->Append = false;
  32. if (args.size() > 1) {
  33. if (args[1] == "APPEND") {
  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. CM_AUTO_PTR<cmsys::ofstream> foutPtr;
  49. if (this->Append) {
  50. CM_AUTO_PTR<cmsys::ofstream> ap(
  51. new cmsys::ofstream(this->Filename.c_str(), std::ios::app));
  52. foutPtr = ap;
  53. } else {
  54. CM_AUTO_PTR<cmGeneratedFileStream> ap(
  55. new cmGeneratedFileStream(this->Filename.c_str(), true));
  56. ap->SetCopyIfDifferent(true);
  57. foutPtr = ap;
  58. }
  59. std::ostream& fout = *foutPtr.get();
  60. if (!fout) {
  61. cmSystemTools::Error("Error Writing ", this->Filename.c_str());
  62. cmSystemTools::ReportLastSystemError("");
  63. return;
  64. }
  65. // Collect dependency information about all library targets built in
  66. // the project.
  67. cmake* cm = this->Makefile->GetCMakeInstance();
  68. cmGlobalGenerator* global = cm->GetGlobalGenerator();
  69. const std::vector<cmMakefile*>& locals = global->GetMakefiles();
  70. std::map<std::string, std::string> libDepsOld;
  71. std::map<std::string, std::string> libDepsNew;
  72. std::map<std::string, std::string> libTypes;
  73. for (std::vector<cmMakefile*>::const_iterator i = locals.begin();
  74. i != locals.end(); ++i) {
  75. const cmTargets& tgts = (*i)->GetTargets();
  76. for (cmTargets::const_iterator l = tgts.begin(); l != tgts.end(); ++l) {
  77. // Get the current target.
  78. cmTarget const& target = l->second;
  79. // Skip non-library targets.
  80. if (target.GetType() < cmState::STATIC_LIBRARY ||
  81. target.GetType() > cmState::MODULE_LIBRARY) {
  82. continue;
  83. }
  84. // Construct the dependency variable name.
  85. std::string targetEntry = target.GetName();
  86. targetEntry += "_LIB_DEPENDS";
  87. // Construct the dependency variable value with the direct link
  88. // dependencies.
  89. std::string valueOld;
  90. std::string valueNew;
  91. cmTarget::LinkLibraryVectorType const& libs =
  92. target.GetOriginalLinkLibraries();
  93. for (cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
  94. li != libs.end(); ++li) {
  95. std::string ltVar = li->first;
  96. ltVar += "_LINK_TYPE";
  97. std::string ltValue;
  98. switch (li->second) {
  99. case GENERAL_LibraryType:
  100. valueNew += "general;";
  101. ltValue = "general";
  102. break;
  103. case DEBUG_LibraryType:
  104. valueNew += "debug;";
  105. ltValue = "debug";
  106. break;
  107. case OPTIMIZED_LibraryType:
  108. valueNew += "optimized;";
  109. ltValue = "optimized";
  110. break;
  111. }
  112. std::string lib = li->first;
  113. if (cmTarget* libtgt = global->FindTarget(lib)) {
  114. // Handle simple output name changes. This command is
  115. // deprecated so we do not support full target name
  116. // translation (which requires per-configuration info).
  117. if (const char* outname = libtgt->GetProperty("OUTPUT_NAME")) {
  118. lib = outname;
  119. }
  120. }
  121. valueOld += lib;
  122. valueOld += ";";
  123. valueNew += lib;
  124. valueNew += ";";
  125. std::string& ltEntry = libTypes[ltVar];
  126. if (ltEntry.empty()) {
  127. ltEntry = ltValue;
  128. } else if (ltEntry != ltValue) {
  129. ltEntry = "general";
  130. }
  131. }
  132. libDepsNew[targetEntry] = valueNew;
  133. libDepsOld[targetEntry] = valueOld;
  134. }
  135. }
  136. // Generate dependency information for both old and new style CMake
  137. // versions.
  138. const char* vertest =
  139. "\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" GREATER 2.4";
  140. fout << "# Generated by CMake\n\n";
  141. fout << "if(" << vertest << ")\n";
  142. fout << " # Information for CMake 2.6 and above.\n";
  143. for (std::map<std::string, std::string>::const_iterator i =
  144. libDepsNew.begin();
  145. i != libDepsNew.end(); ++i) {
  146. if (!i->second.empty()) {
  147. fout << " set(\"" << i->first << "\" \"" << i->second << "\")\n";
  148. }
  149. }
  150. fout << "else()\n";
  151. fout << " # Information for CMake 2.4 and lower.\n";
  152. for (std::map<std::string, std::string>::const_iterator i =
  153. libDepsOld.begin();
  154. i != libDepsOld.end(); ++i) {
  155. if (!i->second.empty()) {
  156. fout << " set(\"" << i->first << "\" \"" << i->second << "\")\n";
  157. }
  158. }
  159. for (std::map<std::string, std::string>::const_iterator i = libTypes.begin();
  160. i != libTypes.end(); ++i) {
  161. if (i->second != "general") {
  162. fout << " set(\"" << i->first << "\" \"" << i->second << "\")\n";
  163. }
  164. }
  165. fout << "endif()\n";
  166. return;
  167. }