cmLinkLineComputer.cxx 5.3 KB

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