| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 | /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying   file Copyright.txt or https://cmake.org/licensing for details.  */#include "cmLinkLineComputer.h"#include <sstream>#include <utility>#include <vector>#include "cmComputeLinkInformation.h"#include "cmGeneratorTarget.h"#include "cmList.h"#include "cmListFileCache.h"#include "cmOutputConverter.h"#include "cmStateTypes.h"#include "cmStringAlgorithms.h"cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,                                       cmStateDirectory const& stateDir)  : StateDir(stateDir)  , OutputConverter(outputConverter){}cmLinkLineComputer::~cmLinkLineComputer() = default;void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote){  this->UseWatcomQuote = useWatcomQuote;}void cmLinkLineComputer::SetUseNinjaMulti(bool useNinjaMulti){  this->UseNinjaMulti = useNinjaMulti;}void cmLinkLineComputer::SetForResponse(bool forResponse){  this->ForResponse = forResponse;}void cmLinkLineComputer::SetRelink(bool relink){  this->Relink = relink;}std::string cmLinkLineComputer::ConvertToLinkReference(  std::string const& lib) const{  return this->OutputConverter->MaybeRelativeToCurBinDir(lib);}std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli){  std::string linkLibs;  std::vector<BT<std::string>> linkLibsList;  this->ComputeLinkLibs(cli, linkLibsList);  cli.AppendValues(linkLibs, linkLibsList);  return linkLibs;}void cmLinkLineComputer::ComputeLinkLibs(  cmComputeLinkInformation& cli, std::vector<BT<std::string>>& linkLibraries){  using ItemVector = cmComputeLinkInformation::ItemVector;  ItemVector const& items = cli.GetItems();  for (auto const& item : items) {    if (item.Target &&        (item.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||         item.Target->GetType() == cmStateEnums::OBJECT_LIBRARY)) {      continue;    }    BT<std::string> linkLib;    if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {      linkLib = item.GetFormattedItem(this->ConvertToOutputFormat(        this->ConvertToLinkReference(item.Value.Value)));    } else {      linkLib = item.Value;    }    linkLib.Value += " ";    linkLibraries.emplace_back(linkLib);  }}std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input){  cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL;  if (this->ForResponse) {    shellFormat = cmOutputConverter::RESPONSE;  } else if (this->UseNinjaMulti) {    shellFormat = cmOutputConverter::NINJAMULTI;  }  return this->OutputConverter->ConvertToOutputFormat(input, shellFormat,                                                      this->UseWatcomQuote);}std::string cmLinkLineComputer::ConvertToOutputForExisting(  std::string const& input){  cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL;  if (this->ForResponse) {    shellFormat = cmOutputConverter::RESPONSE;  } else if (this->UseNinjaMulti) {    shellFormat = cmOutputConverter::NINJAMULTI;  }  return this->OutputConverter->ConvertToOutputForExisting(    input, shellFormat, this->UseWatcomQuote);}std::string cmLinkLineComputer::ComputeLinkPath(  cmComputeLinkInformation& cli, std::string const& libPathFlag,  std::string const& libPathTerminator, std::string const& stdLinkDirString){  std::string linkPath;  std::vector<BT<std::string>> linkPathList;  this->ComputeLinkPath(cli, libPathFlag, libPathTerminator, stdLinkDirString,                        linkPathList);  cli.AppendValues(linkPath, linkPathList);  return linkPath;}void cmLinkLineComputer::ComputeLinkPath(  cmComputeLinkInformation& cli, std::string const& libPathFlag,  std::string const& libPathTerminator, std::string const& stdLinkDirString,  std::vector<BT<std::string>>& linkPath){  if (cli.GetLinkLanguage() == "Swift") {    std::string linkPathNoBT;    for (const cmComputeLinkInformation::Item& item : cli.GetItems()) {      const cmGeneratorTarget* target = item.Target;      if (!target) {        continue;      }      if (target->GetType() == cmStateEnums::STATIC_LIBRARY ||          target->GetType() == cmStateEnums::SHARED_LIBRARY) {        cmStateEnums::ArtifactType type = cmStateEnums::RuntimeBinaryArtifact;        if (target->HasImportLibrary(cli.GetConfig())) {          type = cmStateEnums::ImportLibraryArtifact;        }        linkPathNoBT +=          cmStrCat(" ", libPathFlag,                   this->ConvertToOutputForExisting(                     item.Target->GetDirectory(cli.GetConfig(), type)),                   libPathTerminator, " ");      }    }    if (!linkPathNoBT.empty()) {      linkPath.emplace_back(std::move(linkPathNoBT));    }  }  for (BT<std::string> libDir : cli.GetDirectoriesWithBacktraces()) {    libDir.Value = cmStrCat(" ", libPathFlag,                            this->ConvertToOutputForExisting(libDir.Value),                            libPathTerminator, " ");    linkPath.emplace_back(libDir);  }  for (auto& linkDir : cmList(stdLinkDirString)) {    linkPath.emplace_back(cmStrCat(' ', libPathFlag,                                   this->ConvertToOutputForExisting(linkDir),                                   libPathTerminator, ' '));  }}std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli){  std::string rpath;  // Check what kind of rpath flags to use.  if (cli.GetRuntimeSep().empty()) {    // Each rpath entry gets its own option ("-R a -R b -R c")    std::vector<std::string> runtimeDirs;    cli.GetRPath(runtimeDirs, this->Relink);    for (std::string const& rd : runtimeDirs) {      rpath += cli.GetRuntimeFlag();      rpath += this->ConvertToOutputFormat(rd);      rpath += " ";    }  } else {    // All rpath entries are combined ("-Wl,-rpath,a:b:c").    std::string rpathString = cli.GetRPathString(this->Relink);    // Store the rpath option in the stream.    if (!rpathString.empty()) {      rpath += cli.GetRuntimeFlag();      rpath +=        this->OutputConverter->EscapeForShell(rpathString, !this->ForResponse);      rpath += " ";    }  }  return rpath;}std::string cmLinkLineComputer::ComputeFrameworkPath(  cmComputeLinkInformation& cli, cmValue fwSearchFlag){  if (!fwSearchFlag) {    return std::string{};  }  std::string frameworkPath;  for (auto const& fd : cli.GetFrameworkPaths()) {    frameworkPath +=      cmStrCat(fwSearchFlag, this->ConvertToOutputFormat(fd), ' ');  }  return frameworkPath;}std::string cmLinkLineComputer::ComputeLinkLibraries(  cmComputeLinkInformation& cli, std::string const& stdLibString){  std::string linkLibraries;  std::vector<BT<std::string>> linkLibrariesList;  this->ComputeLinkLibraries(cli, stdLibString, linkLibrariesList);  cli.AppendValues(linkLibraries, linkLibrariesList);  return linkLibraries;}void cmLinkLineComputer::ComputeLinkLibraries(  cmComputeLinkInformation& cli, std::string const& stdLibString,  std::vector<BT<std::string>>& linkLibraries){  std::ostringstream rpathOut;  rpathOut << this->ComputeRPath(cli);  std::string rpath = rpathOut.str();  if (!rpath.empty()) {    linkLibraries.emplace_back(std::move(rpath));  }  // Write the library flags to the build rule.  this->ComputeLinkLibs(cli, linkLibraries);  // Add the linker runtime search path if any.  std::ostringstream fout;  std::string rpath_link = cli.GetRPathLinkString();  if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {    fout << cli.GetRPathLinkFlag();    fout << this->OutputConverter->EscapeForShell(rpath_link,                                                  !this->ForResponse);    fout << " ";  }  if (!stdLibString.empty()) {    fout << stdLibString << " ";  }  std::string remainingLibs = fout.str();  if (!remainingLibs.empty()) {    linkLibraries.emplace_back(remainingLibs);  }}std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target,                                                  std::string const& config){  return target->GetLinkerLanguage(config);}
 |