cmLinkLineComputer.cxx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
  12. cmStateDirectory stateDir)
  13. : StateDir(stateDir)
  14. , OutputConverter(outputConverter)
  15. , ForResponse(false)
  16. , UseWatcomQuote(false)
  17. , Relink(false)
  18. {
  19. }
  20. cmLinkLineComputer::~cmLinkLineComputer()
  21. {
  22. }
  23. void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
  24. {
  25. this->UseWatcomQuote = useWatcomQuote;
  26. }
  27. void cmLinkLineComputer::SetForResponse(bool forResponse)
  28. {
  29. this->ForResponse = forResponse;
  30. }
  31. void cmLinkLineComputer::SetRelink(bool relink)
  32. {
  33. this->Relink = relink;
  34. }
  35. std::string cmLinkLineComputer::ConvertToLinkReference(
  36. std::string const& lib) const
  37. {
  38. std::string relLib = lib;
  39. if (cmOutputConverter::ContainedInDirectory(
  40. this->StateDir.GetCurrentBinary(), lib, this->StateDir)) {
  41. relLib = cmOutputConverter::ForceToRelativePath(
  42. this->StateDir.GetCurrentBinary(), lib);
  43. }
  44. return relLib;
  45. }
  46. std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
  47. {
  48. std::string linkLibs;
  49. typedef cmComputeLinkInformation::ItemVector ItemVector;
  50. ItemVector const& items = cli.GetItems();
  51. for (ItemVector::const_iterator li = items.begin(); li != items.end();
  52. ++li) {
  53. if (li->Target &&
  54. li->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
  55. continue;
  56. }
  57. if (li->IsPath) {
  58. linkLibs +=
  59. this->ConvertToOutputFormat(this->ConvertToLinkReference(li->Value));
  60. } else {
  61. linkLibs += li->Value;
  62. }
  63. linkLibs += " ";
  64. }
  65. return linkLibs;
  66. }
  67. std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
  68. {
  69. cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
  70. ? cmOutputConverter::RESPONSE
  71. : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
  72. : cmOutputConverter::SHELL);
  73. return this->OutputConverter->ConvertToOutputFormat(input, shellFormat);
  74. }
  75. std::string cmLinkLineComputer::ConvertToOutputForExisting(
  76. std::string const& input)
  77. {
  78. cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
  79. ? cmOutputConverter::RESPONSE
  80. : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
  81. : cmOutputConverter::SHELL);
  82. return this->OutputConverter->ConvertToOutputForExisting(input, shellFormat);
  83. }
  84. std::string cmLinkLineComputer::ComputeLinkPath(
  85. cmComputeLinkInformation& cli, std::string const& libPathFlag,
  86. std::string const& libPathTerminator)
  87. {
  88. std::string linkPath;
  89. std::vector<std::string> const& libDirs = cli.GetDirectories();
  90. for (std::vector<std::string>::const_iterator libDir = libDirs.begin();
  91. libDir != libDirs.end(); ++libDir) {
  92. std::string libpath = this->ConvertToOutputForExisting(*libDir);
  93. linkPath += " " + libPathFlag;
  94. linkPath += libpath;
  95. linkPath += libPathTerminator;
  96. linkPath += " ";
  97. }
  98. return linkPath;
  99. }
  100. std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
  101. {
  102. std::string rpath;
  103. // Check what kind of rpath flags to use.
  104. if (cli.GetRuntimeSep().empty()) {
  105. // Each rpath entry gets its own option ("-R a -R b -R c")
  106. std::vector<std::string> runtimeDirs;
  107. cli.GetRPath(runtimeDirs, this->Relink);
  108. for (std::vector<std::string>::iterator ri = runtimeDirs.begin();
  109. ri != runtimeDirs.end(); ++ri) {
  110. rpath += cli.GetRuntimeFlag();
  111. rpath += this->ConvertToOutputFormat(*ri);
  112. rpath += " ";
  113. }
  114. } else {
  115. // All rpath entries are combined ("-Wl,-rpath,a:b:c").
  116. std::string rpathString = cli.GetRPathString(this->Relink);
  117. // Store the rpath option in the stream.
  118. if (!rpathString.empty()) {
  119. rpath += cli.GetRuntimeFlag();
  120. rpath +=
  121. this->OutputConverter->EscapeForShell(rpathString, !this->ForResponse);
  122. rpath += " ";
  123. }
  124. }
  125. return rpath;
  126. }
  127. std::string cmLinkLineComputer::ComputeFrameworkPath(
  128. cmComputeLinkInformation& cli, std::string const& fwSearchFlag)
  129. {
  130. std::string frameworkPath;
  131. if (!fwSearchFlag.empty()) {
  132. std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
  133. for (std::vector<std::string>::const_iterator fdi = fwDirs.begin();
  134. fdi != fwDirs.end(); ++fdi) {
  135. frameworkPath += fwSearchFlag;
  136. frameworkPath += this->ConvertToOutputFormat(*fdi);
  137. frameworkPath += " ";
  138. }
  139. }
  140. return frameworkPath;
  141. }
  142. std::string cmLinkLineComputer::ComputeLinkLibraries(
  143. cmComputeLinkInformation& cli, std::string const& stdLibString)
  144. {
  145. std::ostringstream fout;
  146. fout << this->ComputeRPath(cli);
  147. // Write the library flags to the build rule.
  148. fout << this->ComputeLinkLibs(cli);
  149. // Add the linker runtime search path if any.
  150. std::string rpath_link = cli.GetRPathLinkString();
  151. if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
  152. fout << cli.GetRPathLinkFlag();
  153. fout << this->OutputConverter->EscapeForShell(rpath_link,
  154. !this->ForResponse);
  155. fout << " ";
  156. }
  157. if (!stdLibString.empty()) {
  158. fout << stdLibString << " ";
  159. }
  160. return fout.str();
  161. }