cmLinkLineComputer.cxx 5.3 KB

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