1
0

cmLinkLineComputer.cxx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmLinkLineComputer.h"
  4. #include <sstream>
  5. #include <vector>
  6. #include "cmComputeLinkInformation.h"
  7. #include "cmGeneratorTarget.h"
  8. #include "cmOutputConverter.h"
  9. #include "cmStateDirectory.h"
  10. #include "cmStateTypes.h"
  11. #include "cmSystemTools.h"
  12. cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
  13. cmStateDirectory const& stateDir)
  14. : StateDir(stateDir)
  15. , OutputConverter(outputConverter)
  16. , ForResponse(false)
  17. , UseWatcomQuote(false)
  18. , Relink(false)
  19. {
  20. }
  21. cmLinkLineComputer::~cmLinkLineComputer() = default;
  22. void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
  23. {
  24. this->UseWatcomQuote = useWatcomQuote;
  25. }
  26. void cmLinkLineComputer::SetForResponse(bool forResponse)
  27. {
  28. this->ForResponse = forResponse;
  29. }
  30. void cmLinkLineComputer::SetRelink(bool relink)
  31. {
  32. this->Relink = relink;
  33. }
  34. std::string cmLinkLineComputer::ConvertToLinkReference(
  35. std::string const& lib) const
  36. {
  37. std::string relLib = lib;
  38. if (this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), lib)) {
  39. relLib = cmSystemTools::ForceToRelativePath(
  40. this->StateDir.GetCurrentBinary(), lib);
  41. }
  42. return relLib;
  43. }
  44. std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
  45. {
  46. std::string linkLibs;
  47. typedef cmComputeLinkInformation::ItemVector ItemVector;
  48. ItemVector const& items = cli.GetItems();
  49. for (auto const& item : items) {
  50. if (item.Target &&
  51. item.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
  52. continue;
  53. }
  54. if (item.IsPath) {
  55. linkLibs +=
  56. this->ConvertToOutputFormat(this->ConvertToLinkReference(item.Value));
  57. } else {
  58. linkLibs += item.Value;
  59. }
  60. linkLibs += " ";
  61. }
  62. return linkLibs;
  63. }
  64. std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
  65. {
  66. cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
  67. ? cmOutputConverter::RESPONSE
  68. : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
  69. : cmOutputConverter::SHELL);
  70. return this->OutputConverter->ConvertToOutputFormat(input, shellFormat);
  71. }
  72. std::string cmLinkLineComputer::ConvertToOutputForExisting(
  73. std::string const& input)
  74. {
  75. cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
  76. ? cmOutputConverter::RESPONSE
  77. : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
  78. : cmOutputConverter::SHELL);
  79. return this->OutputConverter->ConvertToOutputForExisting(input, shellFormat);
  80. }
  81. std::string cmLinkLineComputer::ComputeLinkPath(
  82. cmComputeLinkInformation& cli, std::string const& libPathFlag,
  83. std::string const& libPathTerminator)
  84. {
  85. std::string linkPath;
  86. if (cli.GetLinkLanguage() == "Swift") {
  87. for (const cmComputeLinkInformation::Item& item : cli.GetItems()) {
  88. const cmGeneratorTarget* target = item.Target;
  89. if (!target) {
  90. continue;
  91. }
  92. if (target->GetType() == cmStateEnums::STATIC_LIBRARY ||
  93. target->GetType() == cmStateEnums::SHARED_LIBRARY) {
  94. cmStateEnums::ArtifactType type = cmStateEnums::RuntimeBinaryArtifact;
  95. if (target->GetType() == cmStateEnums::SHARED_LIBRARY &&
  96. target->IsDLLPlatform()) {
  97. type = cmStateEnums::ImportLibraryArtifact;
  98. }
  99. linkPath += " " + libPathFlag +
  100. item.Target->GetDirectory(cli.GetConfig(), type) +
  101. libPathTerminator + " ";
  102. }
  103. }
  104. }
  105. for (std::string const& libDir : cli.GetDirectories()) {
  106. linkPath += " " + libPathFlag + this->ConvertToOutputForExisting(libDir) +
  107. libPathTerminator + " ";
  108. }
  109. return linkPath;
  110. }
  111. std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
  112. {
  113. std::string rpath;
  114. // Check what kind of rpath flags to use.
  115. if (cli.GetRuntimeSep().empty()) {
  116. // Each rpath entry gets its own option ("-R a -R b -R c")
  117. std::vector<std::string> runtimeDirs;
  118. cli.GetRPath(runtimeDirs, this->Relink);
  119. for (std::string const& rd : runtimeDirs) {
  120. rpath += cli.GetRuntimeFlag();
  121. rpath += this->ConvertToOutputFormat(rd);
  122. rpath += " ";
  123. }
  124. } else {
  125. // All rpath entries are combined ("-Wl,-rpath,a:b:c").
  126. std::string rpathString = cli.GetRPathString(this->Relink);
  127. // Store the rpath option in the stream.
  128. if (!rpathString.empty()) {
  129. rpath += cli.GetRuntimeFlag();
  130. rpath +=
  131. this->OutputConverter->EscapeForShell(rpathString, !this->ForResponse);
  132. rpath += " ";
  133. }
  134. }
  135. return rpath;
  136. }
  137. std::string cmLinkLineComputer::ComputeFrameworkPath(
  138. cmComputeLinkInformation& cli, std::string const& fwSearchFlag)
  139. {
  140. std::string frameworkPath;
  141. if (!fwSearchFlag.empty()) {
  142. std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
  143. for (std::string const& fd : fwDirs) {
  144. frameworkPath += fwSearchFlag;
  145. frameworkPath += this->ConvertToOutputFormat(fd);
  146. frameworkPath += " ";
  147. }
  148. }
  149. return frameworkPath;
  150. }
  151. std::string cmLinkLineComputer::ComputeLinkLibraries(
  152. cmComputeLinkInformation& cli, std::string const& stdLibString)
  153. {
  154. std::ostringstream fout;
  155. fout << this->ComputeRPath(cli);
  156. // Write the library flags to the build rule.
  157. fout << this->ComputeLinkLibs(cli);
  158. // Add the linker runtime search path if any.
  159. std::string rpath_link = cli.GetRPathLinkString();
  160. if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
  161. fout << cli.GetRPathLinkFlag();
  162. fout << this->OutputConverter->EscapeForShell(rpath_link,
  163. !this->ForResponse);
  164. fout << " ";
  165. }
  166. if (!stdLibString.empty()) {
  167. fout << stdLibString << " ";
  168. }
  169. return fout.str();
  170. }
  171. std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target,
  172. std::string const& config)
  173. {
  174. return target->GetLinkerLanguage(config);
  175. }