CMake Nightly Date Stamp
[kiteware-cmake.git] / Source / cmLinkLineComputer.cxx
bloba29e33f801f898c19fd04c52655e24f3336a95ec
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
4 #include "cmLinkLineComputer.h"
6 #include <sstream>
7 #include <utility>
8 #include <vector>
10 #include "cmComputeLinkInformation.h"
11 #include "cmGeneratorTarget.h"
12 #include "cmListFileCache.h"
13 #include "cmOutputConverter.h"
14 #include "cmStateTypes.h"
15 #include "cmStringAlgorithms.h"
17 cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
18 cmStateDirectory const& stateDir)
19 : StateDir(stateDir)
20 , OutputConverter(outputConverter)
24 cmLinkLineComputer::~cmLinkLineComputer() = default;
26 void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
28 this->UseWatcomQuote = useWatcomQuote;
31 void cmLinkLineComputer::SetUseNinjaMulti(bool useNinjaMulti)
33 this->UseNinjaMulti = useNinjaMulti;
36 void cmLinkLineComputer::SetForResponse(bool forResponse)
38 this->ForResponse = forResponse;
41 void cmLinkLineComputer::SetRelink(bool relink)
43 this->Relink = relink;
46 std::string cmLinkLineComputer::ConvertToLinkReference(
47 std::string const& lib) const
49 return this->OutputConverter->MaybeRelativeToCurBinDir(lib);
52 std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
54 std::string linkLibs;
55 std::vector<BT<std::string>> linkLibsList;
56 this->ComputeLinkLibs(cli, linkLibsList);
57 cli.AppendValues(linkLibs, linkLibsList);
58 return linkLibs;
61 void cmLinkLineComputer::ComputeLinkLibs(
62 cmComputeLinkInformation& cli, std::vector<BT<std::string>>& linkLibraries)
64 using ItemVector = cmComputeLinkInformation::ItemVector;
65 ItemVector const& items = cli.GetItems();
66 for (auto const& item : items) {
67 if (item.Target &&
68 (item.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
69 item.Target->GetType() == cmStateEnums::OBJECT_LIBRARY)) {
70 continue;
73 BT<std::string> linkLib;
74 if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
75 linkLib = item.GetFormattedItem(this->ConvertToOutputFormat(
76 this->ConvertToLinkReference(item.Value.Value)));
77 } else {
78 linkLib = item.Value;
80 linkLib.Value += " ";
82 linkLibraries.emplace_back(linkLib);
86 std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
88 cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL;
89 if (this->ForResponse) {
90 shellFormat = cmOutputConverter::RESPONSE;
91 } else if (this->UseNinjaMulti) {
92 shellFormat = cmOutputConverter::NINJAMULTI;
95 return this->OutputConverter->ConvertToOutputFormat(input, shellFormat,
96 this->UseWatcomQuote);
99 std::string cmLinkLineComputer::ConvertToOutputForExisting(
100 std::string const& input)
102 cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL;
103 if (this->ForResponse) {
104 shellFormat = cmOutputConverter::RESPONSE;
105 } else if (this->UseNinjaMulti) {
106 shellFormat = cmOutputConverter::NINJAMULTI;
109 return this->OutputConverter->ConvertToOutputForExisting(
110 input, shellFormat, this->UseWatcomQuote);
113 std::string cmLinkLineComputer::ComputeLinkPath(
114 cmComputeLinkInformation& cli, std::string const& libPathFlag,
115 std::string const& libPathTerminator)
117 std::string linkPath;
118 std::vector<BT<std::string>> linkPathList;
119 this->ComputeLinkPath(cli, libPathFlag, libPathTerminator, linkPathList);
120 cli.AppendValues(linkPath, linkPathList);
121 return linkPath;
124 void cmLinkLineComputer::ComputeLinkPath(
125 cmComputeLinkInformation& cli, std::string const& libPathFlag,
126 std::string const& libPathTerminator, std::vector<BT<std::string>>& linkPath)
128 if (cli.GetLinkLanguage() == "Swift") {
129 std::string linkPathNoBT;
131 for (const cmComputeLinkInformation::Item& item : cli.GetItems()) {
132 const cmGeneratorTarget* target = item.Target;
133 if (!target) {
134 continue;
137 if (target->GetType() == cmStateEnums::STATIC_LIBRARY ||
138 target->GetType() == cmStateEnums::SHARED_LIBRARY) {
139 cmStateEnums::ArtifactType type = cmStateEnums::RuntimeBinaryArtifact;
140 if (target->HasImportLibrary(cli.GetConfig())) {
141 type = cmStateEnums::ImportLibraryArtifact;
144 linkPathNoBT +=
145 cmStrCat(" ", libPathFlag,
146 this->ConvertToOutputForExisting(
147 item.Target->GetDirectory(cli.GetConfig(), type)),
148 libPathTerminator, " ");
152 if (!linkPathNoBT.empty()) {
153 linkPath.emplace_back(std::move(linkPathNoBT));
157 for (BT<std::string> libDir : cli.GetDirectoriesWithBacktraces()) {
158 libDir.Value = cmStrCat(" ", libPathFlag,
159 this->ConvertToOutputForExisting(libDir.Value),
160 libPathTerminator, " ");
161 linkPath.emplace_back(libDir);
165 std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
167 std::string rpath;
168 // Check what kind of rpath flags to use.
169 if (cli.GetRuntimeSep().empty()) {
170 // Each rpath entry gets its own option ("-R a -R b -R c")
171 std::vector<std::string> runtimeDirs;
172 cli.GetRPath(runtimeDirs, this->Relink);
174 for (std::string const& rd : runtimeDirs) {
175 rpath += cli.GetRuntimeFlag();
176 rpath += this->ConvertToOutputFormat(rd);
177 rpath += " ";
179 } else {
180 // All rpath entries are combined ("-Wl,-rpath,a:b:c").
181 std::string rpathString = cli.GetRPathString(this->Relink);
183 // Store the rpath option in the stream.
184 if (!rpathString.empty()) {
185 rpath += cli.GetRuntimeFlag();
186 rpath +=
187 this->OutputConverter->EscapeForShell(rpathString, !this->ForResponse);
188 rpath += " ";
191 return rpath;
194 std::string cmLinkLineComputer::ComputeFrameworkPath(
195 cmComputeLinkInformation& cli, cmValue fwSearchFlag)
197 if (!fwSearchFlag) {
198 return std::string{};
201 std::string frameworkPath;
202 for (auto const& fd : cli.GetFrameworkPaths()) {
203 frameworkPath +=
204 cmStrCat(fwSearchFlag, this->ConvertToOutputFormat(fd), ' ');
206 return frameworkPath;
209 std::string cmLinkLineComputer::ComputeLinkLibraries(
210 cmComputeLinkInformation& cli, std::string const& stdLibString)
212 std::string linkLibraries;
213 std::vector<BT<std::string>> linkLibrariesList;
214 this->ComputeLinkLibraries(cli, stdLibString, linkLibrariesList);
215 cli.AppendValues(linkLibraries, linkLibrariesList);
216 return linkLibraries;
219 void cmLinkLineComputer::ComputeLinkLibraries(
220 cmComputeLinkInformation& cli, std::string const& stdLibString,
221 std::vector<BT<std::string>>& linkLibraries)
223 std::ostringstream rpathOut;
224 rpathOut << this->ComputeRPath(cli);
226 std::string rpath = rpathOut.str();
227 if (!rpath.empty()) {
228 linkLibraries.emplace_back(std::move(rpath));
231 // Write the library flags to the build rule.
232 this->ComputeLinkLibs(cli, linkLibraries);
234 // Add the linker runtime search path if any.
235 std::ostringstream fout;
236 std::string rpath_link = cli.GetRPathLinkString();
237 if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
238 fout << cli.GetRPathLinkFlag();
239 fout << this->OutputConverter->EscapeForShell(rpath_link,
240 !this->ForResponse);
241 fout << " ";
244 if (!stdLibString.empty()) {
245 fout << stdLibString << " ";
248 std::string remainingLibs = fout.str();
249 if (!remainingLibs.empty()) {
250 linkLibraries.emplace_back(remainingLibs);
254 std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target,
255 std::string const& config)
257 return target->GetLinkerLanguage(config);