cmTargetLinkLibrariesCommand.cxx 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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 "cmTargetLinkLibrariesCommand.h"
  14. const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] =
  15. {
  16. "general",
  17. "debug",
  18. "optimized"
  19. };
  20. // cmTargetLinkLibrariesCommand
  21. bool cmTargetLinkLibrariesCommand
  22. ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
  23. {
  24. // must have one argument
  25. if(args.size() < 1)
  26. {
  27. this->SetError("called with incorrect number of arguments");
  28. return false;
  29. }
  30. // but we might not have any libs after variable expansion
  31. if(args.size() < 2)
  32. {
  33. return true;
  34. }
  35. // Lookup the target for which libraries are specified.
  36. this->Target =
  37. this->Makefile->GetCMakeInstance()
  38. ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
  39. if(!this->Target)
  40. {
  41. cmOStringStream e;
  42. e << "Cannot specify link libraries for target \"" << args[0] << "\" "
  43. << "which is not built by this project.";
  44. this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
  45. cmSystemTools::SetFatalErrorOccured();
  46. return true;
  47. }
  48. // Keep track of link configuration specifiers.
  49. cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
  50. bool haveLLT = false;
  51. // Start with primary linking and switch to link interface
  52. // specification when the keyword is encountered.
  53. this->DoingInterface = false;
  54. // add libraries, nothe that there is an optional prefix
  55. // of debug and optimized than can be used
  56. for(unsigned int i=1; i < args.size(); ++i)
  57. {
  58. if(args[i] == "LINK_INTERFACE_LIBRARIES")
  59. {
  60. this->DoingInterface = true;
  61. if(i != 1)
  62. {
  63. this->Makefile->IssueMessage(
  64. cmake::FATAL_ERROR,
  65. "The LINK_INTERFACE_LIBRARIES option must appear as the second "
  66. "argument, just after the target name."
  67. );
  68. return true;
  69. }
  70. }
  71. else if(args[i] == "debug")
  72. {
  73. if(haveLLT)
  74. {
  75. this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::DEBUG);
  76. }
  77. llt = cmTarget::DEBUG;
  78. haveLLT = true;
  79. }
  80. else if(args[i] == "optimized")
  81. {
  82. if(haveLLT)
  83. {
  84. this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::OPTIMIZED);
  85. }
  86. llt = cmTarget::OPTIMIZED;
  87. haveLLT = true;
  88. }
  89. else if(args[i] == "general")
  90. {
  91. if(haveLLT)
  92. {
  93. this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::GENERAL);
  94. }
  95. llt = cmTarget::GENERAL;
  96. haveLLT = true;
  97. }
  98. else if(haveLLT)
  99. {
  100. // The link type was specified by the previous argument.
  101. haveLLT = false;
  102. this->HandleLibrary(args[i].c_str(), llt);
  103. }
  104. else
  105. {
  106. // Lookup old-style cache entry if type is unspecified. So if you
  107. // do a target_link_libraries(foo optimized bar) it will stay optimized
  108. // and not use the lookup. As there maybe the case where someone has
  109. // specifed that a library is both debug and optimized. (this check is
  110. // only there for backwards compatibility when mixing projects built
  111. // with old versions of CMake and new)
  112. llt = cmTarget::GENERAL;
  113. std::string linkType = args[0];
  114. linkType += "_LINK_TYPE";
  115. const char* linkTypeString =
  116. this->Makefile->GetDefinition( linkType.c_str() );
  117. if(linkTypeString)
  118. {
  119. if(strcmp(linkTypeString, "debug") == 0)
  120. {
  121. llt = cmTarget::DEBUG;
  122. }
  123. if(strcmp(linkTypeString, "optimized") == 0)
  124. {
  125. llt = cmTarget::OPTIMIZED;
  126. }
  127. }
  128. this->HandleLibrary(args[i].c_str(), llt);
  129. }
  130. }
  131. // Make sure the last argument was not a library type specifier.
  132. if(haveLLT)
  133. {
  134. cmOStringStream e;
  135. e << "The \"" << this->LinkLibraryTypeNames[llt]
  136. << "\" argument must be followed by a library.";
  137. this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
  138. cmSystemTools::SetFatalErrorOccured();
  139. }
  140. // If the INTERFACE option was given, make sure the
  141. // LINK_INTERFACE_LIBRARIES property exists. This allows the
  142. // command to be used to specify an empty link interface.
  143. if(this->DoingInterface &&
  144. !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES"))
  145. {
  146. this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
  147. }
  148. return true;
  149. }
  150. //----------------------------------------------------------------------------
  151. void
  152. cmTargetLinkLibrariesCommand
  153. ::LinkLibraryTypeSpecifierWarning(int left, int right)
  154. {
  155. cmOStringStream w;
  156. w << "Link library type specifier \""
  157. << this->LinkLibraryTypeNames[left] << "\" is followed by specifier \""
  158. << this->LinkLibraryTypeNames[right] << "\" instead of a library name. "
  159. << "The first specifier will be ignored.";
  160. this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
  161. }
  162. //----------------------------------------------------------------------------
  163. void
  164. cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
  165. cmTarget::LinkLibraryType llt)
  166. {
  167. // Handle normal case first.
  168. if(!this->DoingInterface)
  169. {
  170. this->Makefile
  171. ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
  172. return;
  173. }
  174. // Get the list of configurations considered to be DEBUG.
  175. std::vector<std::string> const& debugConfigs =
  176. this->Makefile->GetCMakeInstance()->GetDebugConfigs();
  177. std::string prop;
  178. // Include this library in the link interface for the target.
  179. if(llt == cmTarget::DEBUG || llt == cmTarget::GENERAL)
  180. {
  181. // Put in the DEBUG configuration interfaces.
  182. for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
  183. i != debugConfigs.end(); ++i)
  184. {
  185. prop = "LINK_INTERFACE_LIBRARIES_";
  186. prop += *i;
  187. this->Target->AppendProperty(prop.c_str(), lib);
  188. }
  189. }
  190. if(llt == cmTarget::OPTIMIZED || llt == cmTarget::GENERAL)
  191. {
  192. // Put in the non-DEBUG configuration interfaces.
  193. this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);
  194. // Make sure the DEBUG configuration interfaces exist so that the
  195. // general one will not be used as a fall-back.
  196. for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
  197. i != debugConfigs.end(); ++i)
  198. {
  199. prop = "LINK_INTERFACE_LIBRARIES_";
  200. prop += *i;
  201. if(!this->Target->GetProperty(prop.c_str()))
  202. {
  203. this->Target->SetProperty(prop.c_str(), "");
  204. }
  205. }
  206. }
  207. }