CMake Nightly Date Stamp
[kiteware-cmake.git] / Source / cmLinkLineComputer.cxx
blobe823337e80903f8d0ad26e67bfeae67ac32201da
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 "cmList.h"
13 #include "cmListFileCache.h"
14 #include "cmOutputConverter.h"
15 #include "cmStateTypes.h"
16 #include "cmStringAlgorithms.h"
18 cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
19 cmStateDirectory const& stateDir)
20 : StateDir(stateDir)
21 , OutputConverter(outputConverter)
25 cmLinkLineComputer::~cmLinkLineComputer() = default;
27 void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
29 this->UseWatcomQuote = useWatcomQuote;
32 void cmLinkLineComputer::SetUseNinjaMulti(bool useNinjaMulti)
34 this->UseNinjaMulti = useNinjaMulti;
37 void cmLinkLineComputer::SetForResponse(bool forResponse)
39 this->ForResponse = forResponse;
42 void cmLinkLineComputer::SetRelink(bool relink)
44 this->Relink = relink;
47 std::string cmLinkLineComputer::ConvertToLinkReference(
48 std::string const& lib) const
50 return this->OutputConverter->MaybeRelativeToCurBinDir(lib);
53 std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
55 std::string linkLibs;
56 std::vector<BT<std::string>> linkLibsList;
57 this->ComputeLinkLibs(cli, linkLibsList);
58 cli.AppendValues(linkLibs, linkLibsList);
59 return linkLibs;
62 void cmLinkLineComputer::ComputeLinkLibs(
63 cmComputeLinkInformation& cli, std::vector<BT<std::string>>& linkLibraries)
65 using ItemVector = cmComputeLinkInformation::ItemVector;
66 ItemVector const& items = cli.GetItems();
67 for (auto const& item : items) {
68 if (item.Target &&
69 (item.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
70 item.Target->GetType() == cmStateEnums::OBJECT_LIBRARY)) {
71 continue;
74 BT<std::string> linkLib;
75 if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
76 linkLib = item.GetFormattedItem(this->ConvertToOutputFormat(
77 this->ConvertToLinkReference(item.Value.Value)));
78 } else {
79 linkLib = item.Value;
81 linkLib.Value += " ";
83 linkLibraries.emplace_back(linkLib);
87 std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
89 cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL;
90 if (this->ForResponse) {
91 shellFormat = cmOutputConverter::RESPONSE;
92 } else if (this->UseNinjaMulti) {
93 shellFormat = cmOutputConverter::NINJAMULTI;
96 return this->OutputConverter->ConvertToOutputFormat(input, shellFormat,
97 this->UseWatcomQuote);
100 std::string cmLinkLineComputer::ConvertToOutputForExisting(
101 std::string const& input)
103 cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL;
104 if (this->ForResponse) {
105 shellFormat = cmOutputConverter::RESPONSE;
106 } else if (this->UseNinjaMulti) {
107 shellFormat = cmOutputConverter::NINJAMULTI;
110 return this->OutputConverter->ConvertToOutputForExisting(
111 input, shellFormat, this->UseWatcomQuote);
114 std::string cmLinkLineComputer::ComputeLinkPath(
115 cmComputeLinkInformation& cli, std::string const& libPathFlag,
116 std::string const& libPathTerminator, std::string const& stdLinkDirString)
118 std::string linkPath;
119 std::vector<BT<std::string>> linkPathList;
120 this->ComputeLinkPath(cli, libPathFlag, libPathTerminator, stdLinkDirString,
121 linkPathList);
122 cli.AppendValues(linkPath, linkPathList);
123 return linkPath;
126 void cmLinkLineComputer::ComputeLinkPath(
127 cmComputeLinkInformation& cli, std::string const& libPathFlag,
128 std::string const& libPathTerminator, std::string const& stdLinkDirString,
129 std::vector<BT<std::string>>& linkPath)
131 if (cli.GetLinkLanguage() == "Swift") {
132 std::string linkPathNoBT;
134 for (const cmComputeLinkInformation::Item& item : cli.GetItems()) {
135 const cmGeneratorTarget* target = item.Target;
136 if (!target) {
137 continue;
140 if (target->GetType() == cmStateEnums::STATIC_LIBRARY ||
141 target->GetType() == cmStateEnums::SHARED_LIBRARY) {
142 cmStateEnums::ArtifactType type = cmStateEnums::RuntimeBinaryArtifact;
143 if (target->HasImportLibrary(cli.GetConfig())) {
144 type = cmStateEnums::ImportLibraryArtifact;
147 linkPathNoBT +=
148 cmStrCat(" ", libPathFlag,
149 this->ConvertToOutputForExisting(
150 item.Target->GetDirectory(cli.GetConfig(), type)),
151 libPathTerminator, " ");
155 if (!linkPathNoBT.empty()) {
156 linkPath.emplace_back(std::move(linkPathNoBT));
160 for (BT<std::string> libDir : cli.GetDirectoriesWithBacktraces()) {
161 libDir.Value = cmStrCat(" ", libPathFlag,
162 this->ConvertToOutputForExisting(libDir.Value),
163 libPathTerminator, " ");
164 linkPath.emplace_back(libDir);
167 for (auto& linkDir : cmList(stdLinkDirString)) {
168 linkPath.emplace_back(cmStrCat(' ', libPathFlag,
169 this->ConvertToOutputForExisting(linkDir),
170 libPathTerminator, ' '));
174 std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
176 std::string rpath;
177 // Check what kind of rpath flags to use.
178 if (cli.GetRuntimeSep().empty()) {
179 // Each rpath entry gets its own option ("-R a -R b -R c")
180 std::vector<std::string> runtimeDirs;
181 cli.GetRPath(runtimeDirs, this->Relink);
183 for (std::string const& rd : runtimeDirs) {
184 rpath += cli.GetRuntimeFlag();
185 rpath += this->ConvertToOutputFormat(rd);
186 rpath += " ";
188 } else {
189 // All rpath entries are combined ("-Wl,-rpath,a:b:c").
190 std::string rpathString = cli.GetRPathString(this->Relink);
192 // Store the rpath option in the stream.
193 if (!rpathString.empty()) {
194 rpath += cli.GetRuntimeFlag();
195 rpath +=
196 this->OutputConverter->EscapeForShell(rpathString, !this->ForResponse);
197 rpath += " ";
200 return rpath;
203 std::string cmLinkLineComputer::ComputeFrameworkPath(
204 cmComputeLinkInformation& cli, cmValue fwSearchFlag)
206 if (!fwSearchFlag) {
207 return std::string{};
210 std::string frameworkPath;
211 for (auto const& fd : cli.GetFrameworkPaths()) {
212 frameworkPath +=
213 cmStrCat(fwSearchFlag, this->ConvertToOutputFormat(fd), ' ');
215 return frameworkPath;
218 std::string cmLinkLineComputer::ComputeLinkLibraries(
219 cmComputeLinkInformation& cli, std::string const& stdLibString)
221 std::string linkLibraries;
222 std::vector<BT<std::string>> linkLibrariesList;
223 this->ComputeLinkLibraries(cli, stdLibString, linkLibrariesList);
224 cli.AppendValues(linkLibraries, linkLibrariesList);
225 return linkLibraries;
228 void cmLinkLineComputer::ComputeLinkLibraries(
229 cmComputeLinkInformation& cli, std::string const& stdLibString,
230 std::vector<BT<std::string>>& linkLibraries)
232 std::ostringstream rpathOut;
233 rpathOut << this->ComputeRPath(cli);
235 std::string rpath = rpathOut.str();
236 if (!rpath.empty()) {
237 linkLibraries.emplace_back(std::move(rpath));
240 // Write the library flags to the build rule.
241 this->ComputeLinkLibs(cli, linkLibraries);
243 // Add the linker runtime search path if any.
244 std::ostringstream fout;
245 std::string rpath_link = cli.GetRPathLinkString();
246 if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
247 fout << cli.GetRPathLinkFlag();
248 fout << this->OutputConverter->EscapeForShell(rpath_link,
249 !this->ForResponse);
250 fout << " ";
253 if (!stdLibString.empty()) {
254 fout << stdLibString << " ";
257 std::string remainingLibs = fout.str();
258 if (!remainingLibs.empty()) {
259 linkLibraries.emplace_back(remainingLibs);
263 std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target,
264 std::string const& config)
266 return target->GetLinkerLanguage(config);