blob: 2a8bee6e5a7b64384e8cfc55e547ad12adc17774 [file] [log] [blame]
/* 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 <vector>
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmOutputConverter.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
cmStateDirectory const& stateDir)
: StateDir(stateDir)
, OutputConverter(outputConverter)
, ForResponse(false)
, UseWatcomQuote(false)
, Relink(false)
{
}
cmLinkLineComputer::~cmLinkLineComputer() = default;
void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
{
this->UseWatcomQuote = useWatcomQuote;
}
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
{
std::string relLib = lib;
if (this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), lib)) {
relLib = cmSystemTools::ForceToRelativePath(
this->StateDir.GetCurrentBinary(), lib);
}
return relLib;
}
std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
{
std::string linkLibs;
typedef cmComputeLinkInformation::ItemVector ItemVector;
ItemVector const& items = cli.GetItems();
for (auto const& item : items) {
if (item.Target &&
item.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
if (item.IsPath) {
linkLibs +=
this->ConvertToOutputFormat(this->ConvertToLinkReference(item.Value));
} else {
linkLibs += item.Value;
}
linkLibs += " ";
}
return linkLibs;
}
std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
{
cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
? cmOutputConverter::RESPONSE
: ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
: cmOutputConverter::SHELL);
return this->OutputConverter->ConvertToOutputFormat(input, shellFormat);
}
std::string cmLinkLineComputer::ConvertToOutputForExisting(
std::string const& input)
{
cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
? cmOutputConverter::RESPONSE
: ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
: cmOutputConverter::SHELL);
return this->OutputConverter->ConvertToOutputForExisting(input, shellFormat);
}
std::string cmLinkLineComputer::ComputeLinkPath(
cmComputeLinkInformation& cli, std::string const& libPathFlag,
std::string const& libPathTerminator)
{
std::string linkPath;
std::vector<std::string> const& libDirs = cli.GetDirectories();
for (std::string const& libDir : libDirs) {
std::string libpath = this->ConvertToOutputForExisting(libDir);
linkPath += " " + libPathFlag;
linkPath += libpath;
linkPath += libPathTerminator;
linkPath += " ";
}
return linkPath;
}
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, std::string const& fwSearchFlag)
{
std::string frameworkPath;
if (!fwSearchFlag.empty()) {
std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
for (std::string const& fd : fwDirs) {
frameworkPath += fwSearchFlag;
frameworkPath += this->ConvertToOutputFormat(fd);
frameworkPath += " ";
}
}
return frameworkPath;
}
std::string cmLinkLineComputer::ComputeLinkLibraries(
cmComputeLinkInformation& cli, std::string const& stdLibString)
{
std::ostringstream fout;
fout << this->ComputeRPath(cli);
// Write the library flags to the build rule.
fout << this->ComputeLinkLibs(cli);
// Add the linker runtime search path if any.
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 << " ";
}
return fout.str();
}
std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target,
std::string const& config)
{
return target->GetLinkerLanguage(config);
}