cmake/Source/cmLinkLineComputer.cxx

266 lines
7.9 KiB
C++
Raw Normal View History

2017-04-14 19:02:05 +02:00
/* 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>
2020-02-01 23:06:01 +01:00
#include <utility>
2017-04-14 19:02:05 +02:00
#include <vector>
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
2020-02-01 23:06:01 +01:00
#include "cmListFileCache.h"
2017-04-14 19:02:05 +02:00
#include "cmOutputConverter.h"
#include "cmStateTypes.h"
2020-02-01 23:06:01 +01:00
#include "cmStringAlgorithms.h"
2017-04-14 19:02:05 +02:00
cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
2017-07-20 19:35:53 +02:00
cmStateDirectory const& stateDir)
2017-04-14 19:02:05 +02:00
: StateDir(stateDir)
, OutputConverter(outputConverter)
{
}
2019-11-11 23:01:05 +01:00
cmLinkLineComputer::~cmLinkLineComputer() = default;
2017-04-14 19:02:05 +02:00
void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
{
this->UseWatcomQuote = useWatcomQuote;
}
2020-08-30 11:54:41 +02:00
void cmLinkLineComputer::SetUseNinjaMulti(bool useNinjaMulti)
{
this->UseNinjaMulti = useNinjaMulti;
}
2017-04-14 19:02:05 +02:00
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
{
2021-09-14 00:13:48 +02:00
return this->OutputConverter->MaybeRelativeToCurBinDir(lib);
2017-04-14 19:02:05 +02:00
}
std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
{
std::string linkLibs;
2020-02-01 23:06:01 +01:00
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;
2017-04-14 19:02:05 +02:00
ItemVector const& items = cli.GetItems();
2018-01-26 17:06:56 +01:00
for (auto const& item : items) {
if (item.Target &&
item.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
2017-04-14 19:02:05 +02:00
continue;
}
2020-02-01 23:06:01 +01:00
BT<std::string> linkLib;
2021-09-14 00:13:48 +02:00
if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
2022-08-04 22:12:04 +02:00
linkLib = item.GetFormattedItem(this->ConvertToOutputFormat(
this->ConvertToLinkReference(item.Value.Value)));
2017-04-14 19:02:05 +02:00
} else {
2020-08-30 11:54:41 +02:00
linkLib = item.Value;
2017-04-14 19:02:05 +02:00
}
2020-02-01 23:06:01 +01:00
linkLib.Value += " ";
linkLibraries.emplace_back(linkLib);
2017-04-14 19:02:05 +02:00
}
}
std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
{
2020-08-30 11:54:41 +02:00
cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL;
if (this->ForResponse) {
shellFormat = cmOutputConverter::RESPONSE;
} else if (this->UseNinjaMulti) {
shellFormat = cmOutputConverter::NINJAMULTI;
}
2017-04-14 19:02:05 +02:00
2023-05-23 16:38:00 +02:00
return this->OutputConverter->ConvertToOutputFormat(input, shellFormat,
this->UseWatcomQuote);
2017-04-14 19:02:05 +02:00
}
std::string cmLinkLineComputer::ConvertToOutputForExisting(
std::string const& input)
{
2020-08-30 11:54:41 +02:00
cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL;
if (this->ForResponse) {
shellFormat = cmOutputConverter::RESPONSE;
} else if (this->UseNinjaMulti) {
shellFormat = cmOutputConverter::NINJAMULTI;
}
2017-04-14 19:02:05 +02:00
2023-05-23 16:38:00 +02:00
return this->OutputConverter->ConvertToOutputForExisting(
input, shellFormat, this->UseWatcomQuote);
2017-04-14 19:02:05 +02:00
}
std::string cmLinkLineComputer::ComputeLinkPath(
cmComputeLinkInformation& cli, std::string const& libPathFlag,
std::string const& libPathTerminator)
{
std::string linkPath;
2020-02-01 23:06:01 +01:00
std::vector<BT<std::string>> linkPathList;
this->ComputeLinkPath(cli, libPathFlag, libPathTerminator, linkPathList);
cli.AppendValues(linkPath, linkPathList);
return linkPath;
}
2019-11-11 23:01:05 +01:00
2020-02-01 23:06:01 +01:00
void cmLinkLineComputer::ComputeLinkPath(
cmComputeLinkInformation& cli, std::string const& libPathFlag,
std::string const& libPathTerminator, std::vector<BT<std::string>>& linkPath)
{
2019-11-11 23:01:05 +01:00
if (cli.GetLinkLanguage() == "Swift") {
2020-02-01 23:06:01 +01:00
std::string linkPathNoBT;
2019-11-11 23:01:05 +01:00
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;
2020-02-01 23:06:01 +01:00
if (target->HasImportLibrary(cli.GetConfig())) {
2019-11-11 23:01:05 +01:00
type = cmStateEnums::ImportLibraryArtifact;
}
2020-08-30 11:54:41 +02:00
linkPathNoBT +=
cmStrCat(" ", libPathFlag,
this->ConvertToOutputForExisting(
item.Target->GetDirectory(cli.GetConfig(), type)),
libPathTerminator, " ");
2019-11-11 23:01:05 +01:00
}
}
2020-02-01 23:06:01 +01:00
if (!linkPathNoBT.empty()) {
linkPath.emplace_back(std::move(linkPathNoBT));
}
2019-11-11 23:01:05 +01:00
}
2020-02-01 23:06:01 +01:00
for (BT<std::string> libDir : cli.GetDirectoriesWithBacktraces()) {
libDir.Value = cmStrCat(" ", libPathFlag,
this->ConvertToOutputForExisting(libDir.Value),
libPathTerminator, " ");
linkPath.emplace_back(libDir);
}
2017-04-14 19:02:05 +02:00
}
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);
2018-01-26 17:06:56 +01:00
for (std::string const& rd : runtimeDirs) {
2017-04-14 19:02:05 +02:00
rpath += cli.GetRuntimeFlag();
2018-01-26 17:06:56 +01:00
rpath += this->ConvertToOutputFormat(rd);
2017-04-14 19:02:05 +02:00
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(
2023-07-02 19:51:09 +02:00
cmComputeLinkInformation& cli, cmValue fwSearchFlag, cmValue sysFwSearchFlag)
2017-04-14 19:02:05 +02:00
{
2023-07-02 19:51:09 +02:00
if (!fwSearchFlag && !sysFwSearchFlag) {
return std::string{};
}
2017-04-14 19:02:05 +02:00
std::string frameworkPath;
2023-07-02 19:51:09 +02:00
auto const& fwDirs = cli.GetFrameworkPaths();
for (auto const& fd : fwDirs) {
if (sysFwSearchFlag &&
cli.GetTarget()->IsSystemIncludeDirectory(fd, cli.GetConfig(),
cli.GetLinkLanguage())) {
frameworkPath += sysFwSearchFlag;
} else {
2017-04-14 19:02:05 +02:00
frameworkPath += fwSearchFlag;
}
2023-07-02 19:51:09 +02:00
frameworkPath += this->ConvertToOutputFormat(fd);
frameworkPath += " ";
2017-04-14 19:02:05 +02:00
}
return frameworkPath;
}
std::string cmLinkLineComputer::ComputeLinkLibraries(
cmComputeLinkInformation& cli, std::string const& stdLibString)
{
2020-02-01 23:06:01 +01:00
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));
}
2017-04-14 19:02:05 +02:00
// Write the library flags to the build rule.
2020-02-01 23:06:01 +01:00
this->ComputeLinkLibs(cli, linkLibraries);
2017-04-14 19:02:05 +02:00
// Add the linker runtime search path if any.
2020-02-01 23:06:01 +01:00
std::ostringstream fout;
2017-04-14 19:02:05 +02:00
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 << " ";
}
2020-02-01 23:06:01 +01:00
std::string remainingLibs = fout.str();
if (!remainingLibs.empty()) {
linkLibraries.emplace_back(remainingLibs);
}
2017-04-14 19:02:05 +02:00
}
std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target,
std::string const& config)
{
return target->GetLinkerLanguage(config);
}