cmGlobalVisualStudioGenerator.cxx 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 "cmGlobalVisualStudioGenerator.h"
  14. #include "cmLocalGenerator.h"
  15. #include "cmMakefile.h"
  16. #include "cmTarget.h"
  17. //----------------------------------------------------------------------------
  18. cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
  19. {
  20. }
  21. //----------------------------------------------------------------------------
  22. cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator()
  23. {
  24. }
  25. //----------------------------------------------------------------------------
  26. void cmGlobalVisualStudioGenerator::FixUtilityDepends()
  27. {
  28. // For VS versions before 8:
  29. //
  30. // When a target that links contains a project-level dependency on a
  31. // library target that library is automatically linked. In order to
  32. // allow utility-style project-level dependencies that do not
  33. // actually link we need to automatically insert an intermediate
  34. // custom target.
  35. //
  36. // Here we edit the utility dependencies of a target to add the
  37. // intermediate custom target when necessary.
  38. for(unsigned i = 0; i < this->LocalGenerators.size(); ++i)
  39. {
  40. cmTargets* targets =
  41. &(this->LocalGenerators[i]->GetMakefile()->GetTargets());
  42. for(cmTargets::iterator tarIt = targets->begin();
  43. tarIt != targets->end(); ++tarIt)
  44. {
  45. this->FixUtilityDependsForTarget(tarIt->second);
  46. }
  47. }
  48. }
  49. //----------------------------------------------------------------------------
  50. void
  51. cmGlobalVisualStudioGenerator::FixUtilityDependsForTarget(cmTarget& target)
  52. {
  53. // Only targets that link need to be fixed.
  54. if(target.GetType() != cmTarget::STATIC_LIBRARY &&
  55. target.GetType() != cmTarget::SHARED_LIBRARY &&
  56. target.GetType() != cmTarget::MODULE_LIBRARY &&
  57. target.GetType() != cmTarget::EXECUTABLE)
  58. {
  59. return;
  60. }
  61. // Look at each utility dependency.
  62. for(std::set<cmStdString>::const_iterator ui =
  63. target.GetUtilities().begin();
  64. ui != target.GetUtilities().end(); ++ui)
  65. {
  66. if(cmTarget* depTarget = this->FindTarget(0, ui->c_str()))
  67. {
  68. if(depTarget->GetType() == cmTarget::STATIC_LIBRARY ||
  69. depTarget->GetType() == cmTarget::SHARED_LIBRARY ||
  70. depTarget->GetType() == cmTarget::MODULE_LIBRARY)
  71. {
  72. // This utility dependency will cause an attempt to link. If
  73. // the depender does not already link the dependee we need an
  74. // intermediate target.
  75. if(!this->CheckTargetLinks(target, ui->c_str()))
  76. {
  77. this->CreateUtilityDependTarget(*depTarget);
  78. }
  79. }
  80. }
  81. }
  82. }
  83. //----------------------------------------------------------------------------
  84. void
  85. cmGlobalVisualStudioGenerator::CreateUtilityDependTarget(cmTarget& target)
  86. {
  87. // This target is a library on which a utility dependency exists.
  88. // We need to create an intermediate custom target to hook up the
  89. // dependency without causing a link.
  90. const char* altName = target.GetProperty("ALTERNATIVE_DEPENDENCY_NAME");
  91. if(!altName)
  92. {
  93. // Create the intermediate utility target.
  94. std::string altNameStr = target.GetName();
  95. altNameStr += "_UTILITY";
  96. const std::vector<std::string> no_depends;
  97. cmCustomCommandLines no_commands;
  98. const char* no_working_dir = 0;
  99. const char* no_comment = 0;
  100. target.GetMakefile()->AddUtilityCommand(altNameStr.c_str(), true,
  101. no_working_dir, no_depends,
  102. no_commands, false, no_comment);
  103. target.SetProperty("ALTERNATIVE_DEPENDENCY_NAME", altNameStr.c_str());
  104. // Most targets have a GUID created in ConfigureFinalPass. Since
  105. // that has already been called, create one for this target now.
  106. this->CreateGUID(altNameStr.c_str());
  107. // The intermediate target should depend on the original target.
  108. if(cmTarget* alt = this->FindTarget(0, altNameStr.c_str()))
  109. {
  110. alt->AddUtility(target.GetName());
  111. }
  112. }
  113. }
  114. //----------------------------------------------------------------------------
  115. bool cmGlobalVisualStudioGenerator::CheckTargetLinks(cmTarget& target,
  116. const char* name)
  117. {
  118. // Return whether the given target links to a target with the given name.
  119. if(target.GetType() == cmTarget::STATIC_LIBRARY)
  120. {
  121. // Static libraries never link to anything.
  122. return false;
  123. }
  124. cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries();
  125. for(cmTarget::LinkLibraryVectorType::const_iterator i = libs.begin();
  126. i != libs.end(); ++i)
  127. {
  128. if(i->first == name)
  129. {
  130. return true;
  131. }
  132. }
  133. return false;
  134. }
  135. //----------------------------------------------------------------------------
  136. const char*
  137. cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target,
  138. const char* name)
  139. {
  140. // Handle the external MS project special case.
  141. if(strncmp(name, "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
  142. {
  143. // Note from Ken:
  144. // kind of weird removing the first 27 letters. my
  145. // recommendatsions: use cmCustomCommand::GetCommand() to get the
  146. // project name or get rid of the target name starting with
  147. // "INCLUDE_EXTERNAL_MSPROJECT_" and use another indicator/flag
  148. // somewhere. These external project names shouldn't conflict
  149. // with cmake target names anyways.
  150. return name+27;
  151. }
  152. // Possibly depend on an intermediate utility target to avoid
  153. // linking.
  154. if(target.GetType() == cmTarget::STATIC_LIBRARY ||
  155. target.GetType() == cmTarget::SHARED_LIBRARY ||
  156. target.GetType() == cmTarget::MODULE_LIBRARY ||
  157. target.GetType() == cmTarget::EXECUTABLE)
  158. {
  159. // The depender is a target that links. Lookup the dependee to
  160. // see if it provides an alternative dependency name.
  161. if(cmTarget* depTarget = this->FindTarget(0, name))
  162. {
  163. // Check for an alternative name created by FixUtilityDepends.
  164. if(const char* altName =
  165. depTarget->GetProperty("ALTERNATIVE_DEPENDENCY_NAME"))
  166. {
  167. // The alternative name is needed only if the depender does
  168. // not really link to the dependee.
  169. if(!this->CheckTargetLinks(target, name))
  170. {
  171. return altName;
  172. }
  173. }
  174. }
  175. }
  176. // No special case. Just use the original dependency name.
  177. return name;
  178. }