Coverage Report

Created: 2026-10-28 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmGeneratorTarget_Link.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
/* clang-format off */
4
#include "cmGeneratorTarget.h"
5
/* clang-format on */
6
7
#include <algorithm>
8
#include <cassert>
9
#include <cstdio>
10
#include <map>
11
#include <set>
12
#include <string>
13
#include <unordered_map>
14
#include <unordered_set>
15
#include <utility>
16
#include <vector>
17
18
#include <cm/memory>
19
#include <cm/optional>
20
#include <cm/string_view>
21
#include <cmext/algorithm>
22
#include <cmext/string_view>
23
24
#include "cmAlgorithms.h"
25
#include "cmComputeLinkInformation.h"
26
#include "cmDiagnostics.h"
27
#include "cmGenExContext.h"
28
#include "cmGeneratorExpression.h"
29
#include "cmGeneratorExpressionDAGChecker.h"
30
#include "cmGlobalGenerator.h"
31
#include "cmLinkItem.h"
32
#include "cmList.h"
33
#include "cmListFileCache.h"
34
#include "cmLocalGenerator.h"
35
#include "cmMakefile.h"
36
#include "cmMessageType.h"
37
#include "cmPolicies.h"
38
#include "cmRange.h"
39
#include "cmSourceFile.h"
40
#include "cmSourceFileLocationKind.h"
41
#include "cmStringAlgorithms.h"
42
#include "cmSystemTools.h"
43
#include "cmTarget.h"
44
#include "cmTargetLinkLibraryType.h"
45
#include "cmTargetTypes.h"
46
#include "cmValue.h"
47
#include "cmake.h"
48
49
namespace {
50
using UseTo = cmGeneratorTarget::UseTo;
51
52
std::string const kINTERFACE_LINK_LIBRARIES = "INTERFACE_LINK_LIBRARIES";
53
std::string const kINTERFACE_LINK_LIBRARIES_DIRECT =
54
  "INTERFACE_LINK_LIBRARIES_DIRECT";
55
std::string const kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE =
56
  "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE";
57
58
unsigned int CheckLinkLibrariesSuppressionRAIICount;
59
void MaybeEnableCheckLinkLibraries(cmOptionalLinkImplementation& impl)
60
15.5k
{
61
15.5k
  if (CheckLinkLibrariesSuppressionRAIICount == 0) {
62
15.5k
    impl.CheckLinkLibraries = true;
63
15.5k
  }
64
15.5k
}
65
void MaybeEnableCheckLinkLibraries(cmOptionalLinkInterface& iface)
66
51.0k
{
67
51.0k
  if (CheckLinkLibrariesSuppressionRAIICount == 0) {
68
51.0k
    iface.CheckLinkLibraries = true;
69
51.0k
  }
70
51.0k
}
71
}
72
73
class cmTargetCollectLinkLanguages
74
{
75
public:
76
  cmTargetCollectLinkLanguages(cmGeneratorTarget const* target,
77
                               std::string config,
78
                               std::unordered_set<std::string>& languages,
79
                               cmGeneratorTarget const* head, bool secondPass)
80
567
    : Config(std::move(config))
81
567
    , Languages(languages)
82
567
    , HeadTarget(head)
83
567
    , SecondPass(secondPass)
84
567
  {
85
567
    this->Visited.insert(target);
86
567
  }
87
88
  void Visit(cmLinkItem const& item)
89
3.65k
  {
90
3.65k
    if (!item.Target) {
91
492
      return;
92
492
    }
93
3.16k
    if (!this->Visited.insert(item.Target).second) {
94
573
      return;
95
573
    }
96
2.59k
    cmLinkInterface const* iface = item.Target->GetLinkInterface(
97
2.59k
      this->Config, this->HeadTarget, this->SecondPass);
98
2.59k
    if (!iface) {
99
0
      return;
100
0
    }
101
2.59k
    if (iface->HadLinkLanguageSensitiveCondition) {
102
0
      this->HadLinkLanguageSensitiveCondition = true;
103
0
    }
104
105
2.59k
    for (std::string const& language : iface->Languages) {
106
637
      this->Languages.insert(language);
107
637
    }
108
109
2.59k
    for (cmLinkItem const& lib : iface->Libraries) {
110
2.40k
      this->Visit(lib);
111
2.40k
    }
112
2.59k
  }
113
114
  bool GetHadLinkLanguageSensitiveCondition() const
115
567
  {
116
567
    return this->HadLinkLanguageSensitiveCondition;
117
567
  }
118
119
private:
120
  std::string Config;
121
  std::unordered_set<std::string>& Languages;
122
  cmGeneratorTarget const* HeadTarget;
123
  std::set<cmGeneratorTarget const*> Visited;
124
  bool SecondPass;
125
  bool HadLinkLanguageSensitiveCondition = false;
126
};
127
128
cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure(
129
  std::string const& config) const
130
567
{
131
  // There is no link implementation for targets that cannot compile sources.
132
567
  if (!this->CanCompileSources()) {
133
0
    static LinkClosure const empty = { {}, {} };
134
0
    return &empty;
135
0
  }
136
137
567
  std::string key(cmSystemTools::UpperCase(config));
138
567
  auto i = this->LinkClosureMap.find(key);
139
567
  if (i == this->LinkClosureMap.end()) {
140
567
    LinkClosure lc;
141
567
    this->ComputeLinkClosure(config, lc);
142
567
    LinkClosureMapType::value_type entry(key, lc);
143
567
    i = this->LinkClosureMap.insert(entry).first;
144
567
  }
145
567
  return &i->second;
146
567
}
147
148
class cmTargetSelectLinker
149
{
150
  int Preference = 0;
151
  cmGeneratorTarget const* Target;
152
  cmGlobalGenerator* GG;
153
  std::set<std::string> Preferred;
154
155
public:
156
  cmTargetSelectLinker(cmGeneratorTarget const* target)
157
442
    : Target(target)
158
442
  {
159
442
    this->GG = this->Target->GetLocalGenerator()->GetGlobalGenerator();
160
442
  }
161
  void Consider(std::string const& lang)
162
576
  {
163
576
    int preference = this->GG->GetLinkerPreference(lang);
164
576
    if (preference > this->Preference) {
165
442
      this->Preference = preference;
166
442
      this->Preferred.clear();
167
442
    }
168
576
    if (preference == this->Preference) {
169
576
      this->Preferred.insert(lang);
170
576
    }
171
576
  }
172
  std::string Choose()
173
442
  {
174
442
    if (this->Preferred.empty()) {
175
0
      return "";
176
0
    }
177
442
    if (this->Preferred.size() > 1) {
178
0
      cmake* cm = this->Target->GetLocalGenerator()->GetCMakeInstance();
179
0
      cm->IssueMessage(
180
0
        MessageType::FATAL_ERROR,
181
0
        cmStrCat(
182
0
          "Target ", this->Target->GetName(),
183
0
          " contains multiple languages with the highest linker preference (",
184
0
          this->Preference, "):\n", cmWrap("  ", this->Preferred, "\n", ""),
185
0
          "Set the LINKER_LANGUAGE property for this target."),
186
0
        this->Target->GetBacktrace());
187
0
    }
188
442
    return *this->Preferred.begin();
189
442
  }
190
};
191
192
bool cmGeneratorTarget::ComputeLinkClosure(std::string const& config,
193
                                           LinkClosure& lc,
194
                                           bool secondPass) const
195
567
{
196
  // Get languages built in this target.
197
567
  std::unordered_set<std::string> languages;
198
567
  cmLinkImplementation const* impl =
199
567
    this->GetLinkImplementation(config, UseTo::Link, secondPass);
200
567
  assert(impl);
201
567
  languages.insert(impl->Languages.cbegin(), impl->Languages.cend());
202
203
  // Add interface languages from linked targets.
204
  // cmTargetCollectLinkLanguages linkLangs(this, config, languages, this,
205
  // secondPass);
206
567
  cmTargetCollectLinkLanguages linkLangs(this, config, languages, this,
207
567
                                         secondPass);
208
1.25k
  for (cmLinkItem const& lib : impl->Libraries) {
209
1.25k
    linkLangs.Visit(lib);
210
1.25k
  }
211
212
  // Store the transitive closure of languages.
213
567
  cm::append(lc.Languages, languages);
214
215
  // Choose the language whose linker should be used.
216
567
  if (secondPass || lc.LinkerLanguage.empty()) {
217
    // Find the language with the highest preference value.
218
442
    cmTargetSelectLinker tsl(this);
219
220
    // First select from the languages compiled directly in this target.
221
442
    for (std::string const& l : impl->Languages) {
222
442
      tsl.Consider(l);
223
442
    }
224
225
    // Now consider languages that propagate from linked targets.
226
543
    for (std::string const& lang : languages) {
227
543
      std::string propagates =
228
543
        cmStrCat("CMAKE_", lang, "_LINKER_PREFERENCE_PROPAGATES");
229
543
      if (this->Makefile->IsOn(propagates)) {
230
134
        tsl.Consider(lang);
231
134
      }
232
543
    }
233
234
442
    lc.LinkerLanguage = tsl.Choose();
235
442
  }
236
237
567
  return impl->HadLinkLanguageSensitiveCondition ||
238
567
    linkLangs.GetHadLinkLanguageSensitiveCondition();
239
567
}
240
241
void cmGeneratorTarget::ComputeLinkClosure(std::string const& config,
242
                                           LinkClosure& lc) const
243
567
{
244
567
  bool secondPass = false;
245
246
567
  {
247
567
    LinkClosure linkClosure;
248
567
    linkClosure.LinkerLanguage = this->LinkerLanguage;
249
250
567
    bool hasHardCodedLinkerLanguage = this->Target->GetProperty("HAS_CXX") ||
251
567
      !this->Target->GetSafeProperty("LINKER_LANGUAGE").empty();
252
253
    // Get languages built in this target.
254
567
    secondPass = this->ComputeLinkClosure(config, linkClosure, false) &&
255
0
      !hasHardCodedLinkerLanguage;
256
567
    this->LinkerLanguage = linkClosure.LinkerLanguage;
257
567
    if (!secondPass) {
258
567
      lc = std::move(linkClosure);
259
567
    }
260
567
  }
261
262
567
  if (secondPass) {
263
0
    LinkClosure linkClosure;
264
265
0
    this->ComputeLinkClosure(config, linkClosure, secondPass);
266
0
    lc = std::move(linkClosure);
267
268
    // linker language must not be changed between the two passes
269
0
    if (this->LinkerLanguage != lc.LinkerLanguage) {
270
0
      cmSystemTools::Error(cmStrCat(
271
0
        "Evaluation of $<LINK_LANGUAGE:...> or $<LINK_LAND_AND_ID:...> "
272
0
        "changes\nthe linker language for target \"",
273
0
        this->GetName(), "\" (from '", this->LinkerLanguage, "' to '",
274
0
        lc.LinkerLanguage, "') which is invalid."));
275
0
    }
276
0
  }
277
567
}
278
279
static void processILibs(std::string const& config,
280
                         cmGeneratorTarget const* headTarget,
281
                         cmLinkItem const& item, cmGlobalGenerator* gg,
282
                         std::vector<cmGeneratorTarget const*>& tgts,
283
                         std::set<cmGeneratorTarget const*>& emitted,
284
                         UseTo usage)
285
166k
{
286
166k
  if (item.Target && emitted.insert(item.Target).second) {
287
10.4k
    tgts.push_back(item.Target);
288
10.4k
    if (cmLinkInterfaceLibraries const* iface =
289
10.4k
          item.Target->GetLinkInterfaceLibraries(config, headTarget, usage)) {
290
26.4k
      for (cmLinkItem const& lib : iface->Libraries) {
291
26.4k
        processILibs(config, headTarget, lib, gg, tgts, emitted, usage);
292
26.4k
      }
293
10.4k
    }
294
10.4k
  }
295
166k
}
296
297
std::vector<cmGeneratorTarget const*>
298
cmGeneratorTarget::GetLinkInterfaceClosure(std::string const& config,
299
                                           cmGeneratorTarget const* headTarget,
300
                                           UseTo usage) const
301
2.61k
{
302
2.61k
  cmGlobalGenerator* gg = this->GetLocalGenerator()->GetGlobalGenerator();
303
2.61k
  std::vector<cmGeneratorTarget const*> tgts;
304
2.61k
  std::set<cmGeneratorTarget const*> emitted;
305
2.61k
  if (cmLinkInterfaceLibraries const* iface =
306
2.61k
        this->GetLinkInterfaceLibraries(config, headTarget, usage)) {
307
32.7k
    for (cmLinkItem const& lib : iface->Libraries) {
308
32.7k
      processILibs(config, headTarget, lib, gg, tgts, emitted, usage);
309
32.7k
    }
310
2.60k
  }
311
2.61k
  return tgts;
312
2.61k
}
313
314
std::vector<cmGeneratorTarget const*> const&
315
cmGeneratorTarget::GetLinkImplementationClosure(std::string const& config,
316
                                                UseTo usage) const
317
11.3k
{
318
  // There is no link implementation for targets that cannot compile sources.
319
11.3k
  if (!this->CanCompileSources()) {
320
818
    static std::vector<cmGeneratorTarget const*> const empty;
321
818
    return empty;
322
818
  }
323
324
10.5k
  LinkImplClosure& tgts =
325
10.5k
    (usage == UseTo::Compile ? this->LinkImplClosureForUsageMap[config]
326
10.5k
                             : this->LinkImplClosureForLinkMap[config]);
327
10.5k
  if (!tgts.Done) {
328
7.08k
    tgts.Done = true;
329
7.08k
    std::set<cmGeneratorTarget const*> emitted;
330
331
7.08k
    cmLinkImplementationLibraries const* impl =
332
7.08k
      this->GetLinkImplementationLibraries(config, usage);
333
7.08k
    assert(impl);
334
335
107k
    for (cmLinkItem const& lib : impl->Libraries) {
336
107k
      processILibs(config, this, lib,
337
107k
                   this->LocalGenerator->GetGlobalGenerator(), tgts, emitted,
338
107k
                   usage);
339
107k
    }
340
7.08k
  }
341
10.5k
  return tgts;
342
11.3k
}
343
344
cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation(
345
  std::string const& config) const
346
0
{
347
  // Lookup any existing information for this configuration.
348
0
  std::string key(cmSystemTools::UpperCase(config));
349
0
  auto i = this->LinkInformation.find(key);
350
0
  if (i == this->LinkInformation.end()) {
351
    // Compute information for this configuration.
352
0
    auto info = cm::make_unique<cmComputeLinkInformation>(this, config);
353
0
    if (info && !info->Compute()) {
354
0
      info.reset();
355
0
    }
356
357
    // Store the information for this configuration.
358
0
    i = this->LinkInformation.emplace(key, std::move(info)).first;
359
360
0
    if (i->second) {
361
0
      this->CheckPropertyCompatibility(*i->second, config);
362
0
    }
363
0
  }
364
0
  return i->second.get();
365
0
}
366
367
void cmGeneratorTarget::CheckLinkLibraries() const
368
0
{
369
0
  bool linkLibrariesOnlyTargets =
370
0
    this->GetPropertyAsBool("LINK_LIBRARIES_ONLY_TARGETS");
371
372
  // Evaluate the link interface of this target if needed for extra checks.
373
0
  if (linkLibrariesOnlyTargets) {
374
0
    std::vector<std::string> const& configs =
375
0
      this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
376
0
    for (std::string const& config : configs) {
377
0
      this->GetLinkInterfaceLibraries(config, this, UseTo::Link);
378
0
    }
379
0
  }
380
381
  // Check link the implementation for each generated configuration.
382
0
  for (auto const& impl : this->LinkImplMap) {
383
0
    for (cmLinkItem const& item : impl.second.Libraries) {
384
0
      if (!this->VerifyLinkItemColons(LinkItemRole::Implementation, item)) {
385
0
        return;
386
0
      }
387
0
      if (linkLibrariesOnlyTargets &&
388
0
          !this->VerifyLinkItemIsTarget(LinkItemRole::Implementation, item)) {
389
0
        return;
390
0
      }
391
0
    }
392
0
  }
393
394
  // Check link the interface for each generated combination of
395
  // configuration and consuming head target.  We should not need to
396
  // consider LinkInterfaceUsageRequirementsOnlyMap because its entries
397
  // should be a subset of LinkInterfaceMap (with LINK_ONLY left out).
398
0
  for (auto const& hmp : this->LinkInterfaceMap) {
399
0
    for (auto const& hmi : hmp.second) {
400
0
      if (!hmi.second.LibrariesDone || !hmi.second.CheckLinkLibraries) {
401
0
        continue;
402
0
      }
403
0
      for (cmLinkItem const& item : hmi.second.Libraries) {
404
0
        if (!this->VerifyLinkItemColons(LinkItemRole::Interface, item)) {
405
0
          return;
406
0
        }
407
0
        if (linkLibrariesOnlyTargets &&
408
0
            !this->VerifyLinkItemIsTarget(LinkItemRole::Interface, item)) {
409
0
          return;
410
0
        }
411
0
      }
412
0
    }
413
0
  }
414
0
}
415
416
cmGeneratorTarget::CheckLinkLibrariesSuppressionRAII::
417
  CheckLinkLibrariesSuppressionRAII()
418
0
{
419
0
  ++CheckLinkLibrariesSuppressionRAIICount;
420
0
}
421
422
cmGeneratorTarget::CheckLinkLibrariesSuppressionRAII::
423
  ~CheckLinkLibrariesSuppressionRAII()
424
0
{
425
0
  --CheckLinkLibrariesSuppressionRAIICount;
426
0
}
427
428
namespace {
429
cm::string_view missingTargetPossibleReasons =
430
  "Possible reasons include:\n"
431
  "  * There is a typo in the target name.\n"
432
  "  * A find_package call is missing for an IMPORTED target.\n"
433
  "  * An ALIAS target is missing.\n"_s;
434
}
435
436
bool cmGeneratorTarget::VerifyLinkItemColons(LinkItemRole role,
437
                                             cmLinkItem const& item) const
438
0
{
439
0
  if (item.Target || cmHasPrefix(item.AsStr(), "<LINK_GROUP:"_s) ||
440
0
      item.AsStr().find("::") == std::string::npos) {
441
0
    return true;
442
0
  }
443
0
  std::string e;
444
0
  if (role == LinkItemRole::Implementation) {
445
0
    e = cmStrCat(std::move(e), "Target \"", this->GetName(), "\" links to");
446
0
  } else {
447
0
    e = cmStrCat(std::move(e), "The link interface of target \"",
448
0
                 this->GetName(), "\" contains");
449
0
  }
450
0
  e = cmStrCat(std::move(e), ":\n  ", item.AsStr(),
451
0
               "\nbut the target was not found.  ",
452
0
               missingTargetPossibleReasons);
453
0
  cmListFileBacktrace backtrace = item.Backtrace;
454
0
  if (backtrace.Empty()) {
455
0
    backtrace = this->GetBacktrace();
456
0
  }
457
0
  this->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
458
0
    MessageType::FATAL_ERROR, e, backtrace);
459
0
  return false;
460
0
}
461
462
bool cmGeneratorTarget::VerifyLinkItemIsTarget(LinkItemRole role,
463
                                               cmLinkItem const& item) const
464
0
{
465
0
  if (item.Target) {
466
0
    return true;
467
0
  }
468
0
  std::string const& str = item.AsStr();
469
0
  if (!str.empty() &&
470
0
      (str[0] == '-' || str[0] == '$' || str[0] == '`' ||
471
0
       str.find_first_of("/\\") != std::string::npos ||
472
0
       cmHasPrefix(str, "<LINK_LIBRARY:"_s) ||
473
0
       cmHasPrefix(str, "<LINK_GROUP:"_s))) {
474
0
    return true;
475
0
  }
476
477
0
  std::string e = cmStrCat("Target \"", this->GetName(),
478
0
                           "\" has LINK_LIBRARIES_ONLY_TARGETS enabled, but ",
479
0
                           role == LinkItemRole::Implementation
480
0
                             ? "it links to"
481
0
                             : "its link interface contains",
482
0
                           ":\n  ", item.AsStr(), "\nwhich is not a target.  ",
483
0
                           missingTargetPossibleReasons);
484
0
  cmListFileBacktrace backtrace = item.Backtrace;
485
0
  if (backtrace.Empty()) {
486
0
    backtrace = this->GetBacktrace();
487
0
  }
488
0
  this->LocalGenerator->GetCMakeInstance()->IssueMessage(
489
0
    MessageType::FATAL_ERROR, e, backtrace);
490
0
  return false;
491
0
}
492
493
bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n,
494
                                          cmLocalGenerator const*& lg) const
495
153k
{
496
153k
  if (cmHasLiteralPrefix(n, CMAKE_DIRECTORY_ID_SEP)) {
497
893
    cmDirectoryId const dirId = n.substr(cmStrLen(CMAKE_DIRECTORY_ID_SEP));
498
893
    if (dirId.String.empty()) {
499
24
      lg = this->LocalGenerator;
500
24
      return true;
501
24
    }
502
869
    if (cmLocalGenerator const* otherLG =
503
869
          this->GlobalGenerator->FindLocalGenerator(dirId)) {
504
0
      lg = otherLG;
505
0
      return true;
506
0
    }
507
869
  }
508
153k
  return false;
509
153k
}
510
511
cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem(
512
  std::string const& n, cmListFileBacktrace const& bt,
513
  std::string const& linkFeature, LookupLinkItemScope* scope,
514
  LookupSelf lookupSelf) const
515
43.2k
{
516
43.2k
  cm::optional<cmLinkItem> maybeItem;
517
43.2k
  if (this->IsLinkLookupScope(n, scope->LG)) {
518
8
    return maybeItem;
519
8
  }
520
521
43.2k
  std::string name = this->CheckCMP0004(n);
522
43.2k
  if (name.empty() ||
523
43.2k
      (lookupSelf == LookupSelf::No && name == this->GetName())) {
524
4
    return maybeItem;
525
4
  }
526
43.2k
  maybeItem =
527
43.2k
    this->ResolveLinkItem(BT<std::string>(name, bt), scope->LG, linkFeature);
528
43.2k
  return maybeItem;
529
43.2k
}
530
531
void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
532
                                        cmBTStringRange entries,
533
                                        std::string const& config,
534
                                        cmGeneratorTarget const* headTarget,
535
                                        UseTo usage, LinkInterfaceField field,
536
                                        cmLinkInterface& iface) const
537
48.1k
{
538
48.1k
  if (entries.empty()) {
539
38.4k
    return;
540
38.4k
  }
541
  // Keep this logic in sync with ComputeLinkImplementationLibraries.
542
9.63k
  cm::GenEx::Context context(this->LocalGenerator, config,
543
9.63k
                             headTarget->LinkerLanguage);
544
9.63k
  cmGeneratorExpressionDAGChecker dagChecker{
545
9.63k
    this,
546
9.63k
    prop,
547
9.63k
    nullptr,
548
9.63k
    nullptr,
549
9.63k
    context,
550
9.63k
    cmListFileBacktrace(),
551
9.63k
    cmGeneratorExpressionDAGChecker::ComputingLinkLibraries::Yes,
552
9.63k
  };
553
  // The $<LINK_ONLY> expression may be in a link interface to specify
554
  // private link dependencies that are otherwise excluded from usage
555
  // requirements.
556
9.63k
  if (usage == UseTo::Compile) {
557
6.03k
    dagChecker.SetTransitivePropertiesOnly();
558
6.03k
    dagChecker.SetTransitivePropertiesOnlyCMP0131();
559
6.03k
  }
560
9.63k
  cmMakefile const* mf = this->LocalGenerator->GetMakefile();
561
9.63k
  LookupLinkItemScope scope{ this->LocalGenerator };
562
20.0k
  for (BT<std::string> const& entry : entries) {
563
20.0k
    cmGeneratorExpression ge(*this->LocalGenerator->GetCMakeInstance(),
564
20.0k
                             entry.Backtrace);
565
20.0k
    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(entry.Value);
566
20.0k
    cge->SetEvaluateForBuildsystem(true);
567
20.0k
    cmList libs{ cge->Evaluate(context, &dagChecker, headTarget, this) };
568
569
20.0k
    auto linkFeature = cmLinkItem::DEFAULT;
570
43.4k
    for (auto const& lib : libs) {
571
43.4k
      if (auto maybeLinkFeature = ParseLinkFeature(lib)) {
572
140
        linkFeature = std::move(*maybeLinkFeature);
573
140
        continue;
574
140
      }
575
576
43.2k
      if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem(
577
43.2k
            lib, cge->GetBacktrace(), linkFeature, &scope,
578
43.2k
            field == LinkInterfaceField::Libraries ? LookupSelf::No
579
43.2k
                                                   : LookupSelf::Yes)) {
580
43.2k
        cmLinkItem item = std::move(*maybeItem);
581
582
43.2k
        if (field == LinkInterfaceField::HeadInclude) {
583
0
          item.InterfaceDirectFrom = this;
584
0
          iface.HeadInclude.emplace_back(std::move(item));
585
0
          continue;
586
0
        }
587
43.2k
        if (field == LinkInterfaceField::HeadExclude) {
588
0
          iface.HeadExclude.emplace_back(std::move(item));
589
0
          continue;
590
0
        }
591
43.2k
        if (!item.Target) {
592
          // Report explicitly linked object files separately.
593
33.2k
          std::string const& maybeObj = item.AsStr();
594
33.2k
          if (cmSystemTools::FileIsFullPath(maybeObj)) {
595
10.9k
            cmSourceFile const* sf =
596
10.9k
              mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
597
10.9k
            if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
598
0
              item.ObjectSource = sf;
599
0
              iface.Objects.emplace_back(std::move(item));
600
0
              continue;
601
0
            }
602
10.9k
          }
603
33.2k
        }
604
605
43.2k
        iface.Libraries.emplace_back(std::move(item));
606
43.2k
      }
607
43.2k
    }
608
20.0k
    if (cge->GetHadHeadSensitiveCondition()) {
609
440
      iface.HadHeadSensitiveCondition = true;
610
440
    }
611
20.0k
    if (cge->GetHadContextSensitiveCondition()) {
612
2.50k
      iface.HadContextSensitiveCondition = true;
613
2.50k
    }
614
20.0k
    if (cge->GetHadLinkLanguageSensitiveCondition()) {
615
0
      iface.HadLinkLanguageSensitiveCondition = true;
616
0
    }
617
20.0k
  }
618
9.63k
}
619
620
cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
621
  std::string const& config, cmGeneratorTarget const* head) const
622
0
{
623
0
  return this->GetLinkInterface(config, head, false);
624
0
}
625
626
cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
627
  std::string const& config, cmGeneratorTarget const* head,
628
  bool secondPass) const
629
2.59k
{
630
  // Imported targets have their own link interface.
631
2.59k
  if (this->IsImported()) {
632
1.01k
    return this->GetImportLinkInterface(config, head, UseTo::Link, secondPass);
633
1.01k
  }
634
635
  // Link interfaces are not supported for executables that do not
636
  // export symbols.
637
1.58k
  if (this->GetType() == cm::TargetType::EXECUTABLE &&
638
0
      !this->IsExecutableWithExports()) {
639
0
    return nullptr;
640
0
  }
641
642
  // Lookup any existing link interface for this configuration.
643
1.58k
  cmHeadToLinkInterfaceMap& hm = this->GetHeadToLinkInterfaceMap(config);
644
645
  // If the link interface does not depend on the head target
646
  // then reuse the one from the head we computed first.
647
1.58k
  if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
648
1.58k
    head = hm.begin()->first;
649
1.58k
  }
650
651
1.58k
  cmOptionalLinkInterface& iface = hm[head];
652
1.58k
  if (secondPass) {
653
0
    iface = cmOptionalLinkInterface();
654
0
  }
655
1.58k
  MaybeEnableCheckLinkLibraries(iface);
656
1.58k
  if (!iface.LibrariesDone) {
657
0
    iface.LibrariesDone = true;
658
0
    this->ComputeLinkInterfaceLibraries(config, iface, head, UseTo::Link);
659
0
  }
660
1.58k
  if (!iface.AllDone) {
661
1.48k
    iface.AllDone = true;
662
1.48k
    if (iface.Exists) {
663
1.48k
      this->ComputeLinkInterface(config, iface, secondPass);
664
1.48k
      this->ComputeLinkInterfaceRuntimeLibraries(config, iface);
665
1.48k
    }
666
1.48k
  }
667
668
1.58k
  return iface.Exists ? &iface : nullptr;
669
1.58k
}
670
671
void cmGeneratorTarget::ComputeLinkInterface(std::string const& config,
672
                                             cmOptionalLinkInterface& iface,
673
                                             bool secondPass) const
674
1.48k
{
675
1.48k
  if (this->GetType() == cm::TargetType::SHARED_LIBRARY ||
676
1.48k
      this->GetType() == cm::TargetType::STATIC_LIBRARY ||
677
1.35k
      this->GetType() == cm::TargetType::INTERFACE_LIBRARY) {
678
    // Shared libraries may have runtime implementation dependencies
679
    // on other shared libraries that are not in the interface.
680
1.01k
    std::set<cmLinkItem> emitted;
681
1.82k
    for (cmLinkItem const& lib : iface.Libraries) {
682
1.82k
      emitted.insert(lib);
683
1.82k
    }
684
1.01k
    if (this->GetType() != cm::TargetType::INTERFACE_LIBRARY) {
685
132
      cmLinkImplementation const* impl =
686
132
        this->GetLinkImplementation(config, UseTo::Link, secondPass);
687
393
      for (cmLinkItem const& lib : impl->Libraries) {
688
393
        if (emitted.insert(lib).second) {
689
0
          if (lib.Target) {
690
            // This is a runtime dependency on another shared library.
691
0
            if (lib.Target->GetType() == cm::TargetType::SHARED_LIBRARY) {
692
0
              iface.SharedDeps.push_back(lib);
693
0
            }
694
0
          } else {
695
            // TODO: Recognize shared library file names.  Perhaps this
696
            // should be moved to cmComputeLinkInformation, but that
697
            // creates a chicken-and-egg problem since this list is needed
698
            // for its construction.
699
0
          }
700
0
        }
701
393
      }
702
132
    }
703
1.01k
  }
704
705
1.48k
  if (this->LinkLanguagePropagatesToDependents()) {
706
    // Targets using this archive need its language runtime libraries.
707
132
    if (cmLinkImplementation const* impl =
708
132
          this->GetLinkImplementation(config, UseTo::Link, secondPass)) {
709
132
      iface.Languages = impl->Languages;
710
132
    }
711
132
  }
712
713
1.48k
  if (this->GetType() == cm::TargetType::STATIC_LIBRARY) {
714
    // Construct the property name suffix for this configuration.
715
132
    std::string suffix = "_";
716
132
    if (!config.empty()) {
717
126
      suffix += cmSystemTools::UpperCase(config);
718
126
    } else {
719
6
      suffix += "NOCONFIG";
720
6
    }
721
722
    // How many repetitions are needed if this library has cyclic
723
    // dependencies?
724
132
    std::string propName = cmStrCat("LINK_INTERFACE_MULTIPLICITY", suffix);
725
132
    if (cmValue config_reps = this->GetProperty(propName)) {
726
0
      sscanf(config_reps->c_str(), "%u", &iface.Multiplicity);
727
132
    } else if (cmValue reps =
728
132
                 this->GetProperty("LINK_INTERFACE_MULTIPLICITY")) {
729
0
      sscanf(reps->c_str(), "%u", &iface.Multiplicity);
730
0
    }
731
132
  }
732
1.48k
}
733
734
cmLinkInterfaceLibraries const* cmGeneratorTarget::GetLinkInterfaceLibraries(
735
  std::string const& config, cmGeneratorTarget const* head, UseTo usage) const
736
48.4k
{
737
  // Imported targets have their own link interface.
738
48.4k
  if (this->IsImported()) {
739
12.0k
    return this->GetImportLinkInterface(config, head, usage);
740
12.0k
  }
741
742
  // Link interfaces are not supported for executables that do not
743
  // export symbols.
744
36.3k
  if (this->GetType() == cm::TargetType::EXECUTABLE &&
745
8
      !this->IsExecutableWithExports()) {
746
8
    return nullptr;
747
8
  }
748
749
  // Lookup any existing link interface for this configuration.
750
36.3k
  cmHeadToLinkInterfaceMap& hm =
751
36.3k
    (usage == UseTo::Compile
752
36.3k
       ? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
753
36.3k
       : this->GetHeadToLinkInterfaceMap(config));
754
755
  // If the link interface does not depend on the head target
756
  // then reuse the one from the head we computed first.
757
36.3k
  if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
758
23.9k
    head = hm.begin()->first;
759
23.9k
  }
760
761
36.3k
  cmOptionalLinkInterface& iface = hm[head];
762
36.3k
  MaybeEnableCheckLinkLibraries(iface);
763
36.3k
  if (!iface.LibrariesDone) {
764
12.0k
    iface.LibrariesDone = true;
765
12.0k
    this->ComputeLinkInterfaceLibraries(config, iface, head, usage);
766
12.0k
  }
767
768
36.3k
  return iface.Exists ? &iface : nullptr;
769
36.3k
}
770
771
void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
772
  std::string const& config, cmOptionalLinkInterface& iface,
773
  cmGeneratorTarget const* headTarget, UseTo usage) const
774
12.0k
{
775
  // Construct the property name suffix for this configuration.
776
12.0k
  std::string suffix = "_";
777
12.0k
  if (!config.empty()) {
778
10.4k
    suffix += cmSystemTools::UpperCase(config);
779
10.4k
  } else {
780
1.54k
    suffix += "NOCONFIG";
781
1.54k
  }
782
783
  // An explicit list of interface libraries may be set for shared
784
  // libraries and executables that export symbols.
785
12.0k
  bool const haveExplicitLibraries =
786
12.0k
    !this->Target->GetLinkInterfaceEntries().empty() ||
787
4.32k
    !this->Target->GetLinkInterfaceDirectEntries().empty() ||
788
4.32k
    !this->Target->GetLinkInterfaceDirectExcludeEntries().empty();
789
790
  // There is no implicit link interface for executables or modules
791
  // so if none was explicitly set then there is no link interface.
792
12.0k
  if (!haveExplicitLibraries &&
793
4.32k
      (this->GetType() == cm::TargetType::EXECUTABLE ||
794
4.32k
       (this->GetType() == cm::TargetType::MODULE_LIBRARY))) {
795
0
    return;
796
0
  }
797
12.0k
  iface.Exists = true;
798
799
  // The interface libraries are specified by INTERFACE_LINK_LIBRARIES.
800
  // Use its special representation directly to get backtraces.
801
12.0k
  this->ExpandLinkItems(
802
12.0k
    kINTERFACE_LINK_LIBRARIES, this->Target->GetLinkInterfaceEntries(), config,
803
12.0k
    headTarget, usage, LinkInterfaceField::Libraries, iface);
804
12.0k
  this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT,
805
12.0k
                        this->Target->GetLinkInterfaceDirectEntries(), config,
806
12.0k
                        headTarget, usage, LinkInterfaceField::HeadInclude,
807
12.0k
                        iface);
808
12.0k
  this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
809
12.0k
                        this->Target->GetLinkInterfaceDirectExcludeEntries(),
810
12.0k
                        config, headTarget, usage,
811
12.0k
                        LinkInterfaceField::HeadExclude, iface);
812
12.0k
}
813
814
std::vector<cmLinkItem> cmGeneratorTarget::ComputeImplicitLanguageTargets(
815
  std::string const& lang, std::string const& config) const
816
0
{
817
0
  cmListFileBacktrace bt;
818
0
  std::vector<cmLinkItem> result;
819
0
  cmLocalGenerator* lg = this->GetLocalGenerator();
820
821
0
  std::string const& runtimeLibrary =
822
0
    this->GetRuntimeLinkLibrary(lang, config);
823
0
  if (cmValue runtimeLinkOptions = this->Makefile->GetDefinition(
824
0
        cmStrCat("CMAKE_", lang, "_RUNTIME_LIBRARIES_", runtimeLibrary))) {
825
0
    cmList libsList{ *runtimeLinkOptions };
826
0
    result.reserve(libsList.size());
827
828
0
    for (auto const& i : libsList) {
829
0
      cmGeneratorTarget::TargetOrString resolved =
830
0
        this->ResolveTargetReference(i, lg);
831
0
      if (resolved.Target) {
832
0
        result.emplace_back(resolved.Target, false, bt);
833
0
      }
834
0
    }
835
0
  }
836
837
0
  return result;
838
0
}
839
840
void cmGeneratorTarget::ComputeLinkInterfaceRuntimeLibraries(
841
  std::string const& config, cmOptionalLinkInterface& iface) const
842
1.48k
{
843
1.48k
  for (std::string const& lang : iface.Languages) {
844
132
    if ((lang == "CUDA" || lang == "HIP") &&
845
0
        iface.LanguageRuntimeLibraries.find(lang) ==
846
0
          iface.LanguageRuntimeLibraries.end()) {
847
0
      iface.LanguageRuntimeLibraries[lang] =
848
0
        this->ComputeImplicitLanguageTargets(lang, config);
849
0
    }
850
132
  }
851
1.48k
}
852
853
void cmGeneratorTarget::ComputeLinkImplementationRuntimeLibraries(
854
  std::string const& config, cmOptionalLinkImplementation& impl) const
855
603
{
856
603
  for (std::string const& lang : impl.Languages) {
857
603
    if ((lang == "CUDA" || lang == "HIP") &&
858
0
        impl.LanguageRuntimeLibraries.find(lang) ==
859
0
          impl.LanguageRuntimeLibraries.end()) {
860
0
      impl.LanguageRuntimeLibraries[lang] =
861
0
        this->ComputeImplicitLanguageTargets(lang, config);
862
0
    }
863
603
  }
864
603
}
865
866
cmLinkInterface const* cmGeneratorTarget::GetImportLinkInterface(
867
  std::string const& config, cmGeneratorTarget const* headTarget, UseTo usage,
868
  bool secondPass) const
869
13.0k
{
870
13.0k
  cmGeneratorTarget::ImportInfo const* info = this->GetImportInfo(config);
871
13.0k
  if (!info) {
872
0
    return nullptr;
873
0
  }
874
875
13.0k
  cmHeadToLinkInterfaceMap& hm =
876
13.0k
    (usage == UseTo::Compile
877
13.0k
       ? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
878
13.0k
       : this->GetHeadToLinkInterfaceMap(config));
879
880
  // If the link interface does not depend on the head target
881
  // then reuse the one from the head we computed first.
882
13.0k
  if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
883
9.06k
    headTarget = hm.begin()->first;
884
9.06k
  }
885
886
13.0k
  cmOptionalLinkInterface& iface = hm[headTarget];
887
13.0k
  if (secondPass) {
888
0
    iface = cmOptionalLinkInterface();
889
0
  }
890
13.0k
  MaybeEnableCheckLinkLibraries(iface);
891
13.0k
  if (!iface.AllDone) {
892
4.02k
    iface.AllDone = true;
893
4.02k
    iface.LibrariesDone = true;
894
4.02k
    iface.Multiplicity = info->Multiplicity;
895
4.02k
    cmExpandList(info->Languages, iface.Languages);
896
4.02k
    this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT,
897
4.02k
                          cmMakeRange(info->LibrariesHeadInclude), config,
898
4.02k
                          headTarget, usage, LinkInterfaceField::HeadInclude,
899
4.02k
                          iface);
900
4.02k
    this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
901
4.02k
                          cmMakeRange(info->LibrariesHeadExclude), config,
902
4.02k
                          headTarget, usage, LinkInterfaceField::HeadExclude,
903
4.02k
                          iface);
904
4.02k
    this->ExpandLinkItems(info->LibrariesProp, cmMakeRange(info->Libraries),
905
4.02k
                          config, headTarget, usage,
906
4.02k
                          LinkInterfaceField::Libraries, iface);
907
4.02k
    cmList deps{ info->SharedDeps };
908
4.02k
    LookupLinkItemScope scope{ this->LocalGenerator };
909
910
4.02k
    auto linkFeature = cmLinkItem::DEFAULT;
911
4.02k
    for (auto const& dep : deps) {
912
0
      if (auto maybeLinkFeature = ParseLinkFeature(dep)) {
913
0
        linkFeature = std::move(*maybeLinkFeature);
914
0
        continue;
915
0
      }
916
917
0
      if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem(
918
0
            dep, cmListFileBacktrace(), linkFeature, &scope, LookupSelf::No)) {
919
0
        iface.SharedDeps.emplace_back(std::move(*maybeItem));
920
0
      }
921
0
    }
922
4.02k
  }
923
924
13.0k
  return &iface;
925
13.0k
}
926
927
cmHeadToLinkInterfaceMap& cmGeneratorTarget::GetHeadToLinkInterfaceMap(
928
  std::string const& config) const
929
14.1k
{
930
14.1k
  return this->LinkInterfaceMap[cmSystemTools::UpperCase(config)];
931
14.1k
}
932
933
cmHeadToLinkInterfaceMap&
934
cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap(
935
  std::string const& config) const
936
36.9k
{
937
36.9k
  return this
938
36.9k
    ->LinkInterfaceUsageRequirementsOnlyMap[cmSystemTools::UpperCase(config)];
939
36.9k
}
940
941
cmLinkImplementation const* cmGeneratorTarget::GetLinkImplementation(
942
  std::string const& config, UseTo usage) const
943
0
{
944
0
  return this->GetLinkImplementation(config, usage, false);
945
0
}
946
947
cmLinkImplementation const* cmGeneratorTarget::GetLinkImplementation(
948
  std::string const& config, UseTo usage, bool secondPass) const
949
831
{
950
  // There is no link implementation for targets that cannot compile sources.
951
831
  if (!this->CanCompileSources()) {
952
0
    return nullptr;
953
0
  }
954
955
831
  cmOptionalLinkImplementation& impl =
956
831
    (usage == UseTo::Compile
957
831
       ? this
958
0
           ->LinkImplUsageRequirementsOnlyMap[cmSystemTools::UpperCase(config)]
959
831
       : this->LinkImplMap[cmSystemTools::UpperCase(config)]);
960
831
  if (secondPass) {
961
0
    impl = cmOptionalLinkImplementation();
962
0
  }
963
831
  MaybeEnableCheckLinkLibraries(impl);
964
831
  if (!impl.LibrariesDone) {
965
597
    impl.LibrariesDone = true;
966
597
    this->ComputeLinkImplementationLibraries(config, impl, usage);
967
597
  }
968
831
  if (!impl.LanguagesDone) {
969
603
    impl.LanguagesDone = true;
970
603
    this->ComputeLinkImplementationLanguages(config, impl);
971
603
    this->ComputeLinkImplementationRuntimeLibraries(config, impl);
972
603
  }
973
831
  return &impl;
974
831
}
975
976
cmLinkImplementationLibraries const*
977
cmGeneratorTarget::GetLinkImplementationLibraries(std::string const& config,
978
                                                  UseTo usage) const
979
14.7k
{
980
  // There is no link implementation for targets that cannot compile sources.
981
14.7k
  if (!this->CanCompileSources()) {
982
37
    return nullptr;
983
37
  }
984
985
  // Populate the link implementation libraries for this configuration.
986
14.6k
  cmOptionalLinkImplementation& impl =
987
14.6k
    (usage == UseTo::Compile
988
14.6k
       ? this
989
11.4k
           ->LinkImplUsageRequirementsOnlyMap[cmSystemTools::UpperCase(config)]
990
14.6k
       : this->LinkImplMap[cmSystemTools::UpperCase(config)]);
991
14.6k
  MaybeEnableCheckLinkLibraries(impl);
992
14.6k
  if (!impl.LibrariesDone) {
993
7.99k
    impl.LibrariesDone = true;
994
7.99k
    this->ComputeLinkImplementationLibraries(config, impl, usage);
995
7.99k
  }
996
14.6k
  return &impl;
997
14.7k
}
998
999
namespace {
1000
class TransitiveLinkImpl
1001
{
1002
  cmGeneratorTarget const* Self;
1003
  std::string const& Config;
1004
  UseTo ImplFor;
1005
  cmLinkImplementation& Impl;
1006
1007
  std::set<cmLinkItem> Emitted;
1008
  std::set<cmLinkItem> Excluded;
1009
  std::unordered_set<cmGeneratorTarget const*> Followed;
1010
1011
  void Follow(cmGeneratorTarget const* target);
1012
1013
public:
1014
  TransitiveLinkImpl(cmGeneratorTarget const* self, std::string const& config,
1015
                     UseTo usage, cmLinkImplementation& impl)
1016
8.58k
    : Self(self)
1017
8.58k
    , Config(config)
1018
8.58k
    , ImplFor(usage)
1019
8.58k
    , Impl(impl)
1020
8.58k
  {
1021
8.58k
  }
1022
1023
  void Compute();
1024
};
1025
1026
void TransitiveLinkImpl::Follow(cmGeneratorTarget const* target)
1027
137k
{
1028
137k
  if (!target || !this->Followed.insert(target).second) {
1029
121k
    return;
1030
121k
  }
1031
1032
  // Get this target's usage requirements.
1033
15.6k
  cmLinkInterfaceLibraries const* iface =
1034
15.6k
    target->GetLinkInterfaceLibraries(this->Config, this->Self, this->ImplFor);
1035
15.6k
  if (!iface) {
1036
0
    return;
1037
0
  }
1038
15.6k
  if (iface->HadContextSensitiveCondition) {
1039
2.74k
    this->Impl.HadContextSensitiveCondition = true;
1040
2.74k
  }
1041
1042
  // Process 'INTERFACE_LINK_LIBRARIES_DIRECT' usage requirements.
1043
15.6k
  for (cmLinkItem const& item : iface->HeadInclude) {
1044
    // Inject direct dependencies from the item's usage requirements
1045
    // before the item itself.
1046
0
    this->Follow(item.Target);
1047
1048
    // Add the item itself, but at most once.
1049
0
    if (this->Emitted.insert(item).second) {
1050
0
      this->Impl.Libraries.emplace_back(item);
1051
0
    }
1052
0
  }
1053
1054
  // Follow transitive dependencies.
1055
27.1k
  for (cmLinkItem const& item : iface->Libraries) {
1056
27.1k
    this->Follow(item.Target);
1057
27.1k
  }
1058
1059
  // Record exclusions from 'INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE'
1060
  // usage requirements.
1061
15.6k
  for (cmLinkItem const& item : iface->HeadExclude) {
1062
0
    this->Excluded.insert(item);
1063
0
  }
1064
15.6k
}
1065
1066
void TransitiveLinkImpl::Compute()
1067
8.58k
{
1068
  // Save the original items and start with an empty list.
1069
8.58k
  std::vector<cmLinkItem> original = std::move(this->Impl.Libraries);
1070
1071
  // Avoid injecting any original items as usage requirements.
1072
  // This gives LINK_LIBRARIES final control over the order
1073
  // if it explicitly lists everything.
1074
8.58k
  this->Emitted.insert(original.cbegin(), original.cend());
1075
1076
  // Process each original item.
1077
110k
  for (cmLinkItem& item : original) {
1078
    // Inject direct dependencies listed in 'INTERFACE_LINK_LIBRARIES_DIRECT'
1079
    // usage requirements before the item itself.
1080
110k
    this->Follow(item.Target);
1081
1082
    // Add the item itself.
1083
110k
    this->Impl.Libraries.emplace_back(std::move(item));
1084
110k
  }
1085
1086
  // Remove items listed in 'INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE'
1087
  // usage requirements found through any dependency above.
1088
8.58k
  this->Impl.Libraries.erase(
1089
8.58k
    std::remove_if(this->Impl.Libraries.begin(), this->Impl.Libraries.end(),
1090
110k
                   [this](cmLinkItem const& item) {
1091
110k
                     return this->Excluded.find(item) != this->Excluded.end();
1092
110k
                   }),
1093
8.58k
    this->Impl.Libraries.end());
1094
8.58k
}
1095
1096
void ComputeLinkImplTransitive(cmGeneratorTarget const* self,
1097
                               std::string const& config, UseTo usage,
1098
                               cmLinkImplementation& impl)
1099
8.58k
{
1100
8.58k
  TransitiveLinkImpl transitiveLinkImpl(self, config, usage, impl);
1101
8.58k
  transitiveLinkImpl.Compute();
1102
8.58k
}
1103
}
1104
1105
void cmGeneratorTarget::ComputeLinkImplementationLibraries(
1106
  std::string const& config, cmOptionalLinkImplementation& impl,
1107
  UseTo usage) const
1108
8.59k
{
1109
8.59k
  cm::GenEx::Context context(this->LocalGenerator, config,
1110
8.59k
                             this->LinkerLanguage);
1111
8.59k
  cmLocalGenerator const* lg = this->LocalGenerator;
1112
8.59k
  cmMakefile const* mf = lg->GetMakefile();
1113
8.59k
  cmBTStringRange entryRange = this->Target->GetLinkImplementationEntries();
1114
8.59k
  auto const& synthTargetsForConfig = this->Configs[config].SyntheticDeps;
1115
  // Collect libraries directly linked in this configuration.
1116
10.8k
  for (auto const& entry : entryRange) {
1117
    // Keep this logic in sync with ExpandLinkItems.
1118
10.8k
    cmGeneratorExpressionDAGChecker dagChecker{
1119
10.8k
      this,
1120
10.8k
      "LINK_LIBRARIES",
1121
10.8k
      nullptr,
1122
10.8k
      nullptr,
1123
10.8k
      context,
1124
10.8k
      cmListFileBacktrace(),
1125
10.8k
      cmGeneratorExpressionDAGChecker::ComputingLinkLibraries::Yes,
1126
10.8k
    };
1127
    // The $<LINK_ONLY> expression may be used to specify link dependencies
1128
    // that are otherwise excluded from usage requirements.
1129
10.8k
    if (usage == UseTo::Compile) {
1130
6.31k
      dagChecker.SetTransitivePropertiesOnly();
1131
6.31k
      switch (this->GetPolicyStatusCMP0131()) {
1132
0
        case cmPolicies::WARN:
1133
0
        case cmPolicies::OLD:
1134
0
          break;
1135
6.31k
        case cmPolicies::NEW:
1136
6.31k
          dagChecker.SetTransitivePropertiesOnlyCMP0131();
1137
6.31k
          break;
1138
6.31k
      }
1139
6.31k
    }
1140
10.8k
    cmGeneratorExpression ge(*this->LocalGenerator->GetCMakeInstance(),
1141
10.8k
                             entry.Backtrace);
1142
10.8k
    std::unique_ptr<cmCompiledGeneratorExpression> const cge =
1143
10.8k
      ge.Parse(entry.Value);
1144
10.8k
    cge->SetEvaluateForBuildsystem(true);
1145
10.8k
    std::string const& evaluated = cge->Evaluate(context, &dagChecker, this);
1146
10.8k
    cmList llibs(evaluated);
1147
10.8k
    if (cge->GetHadHeadSensitiveCondition()) {
1148
77
      impl.HadHeadSensitiveCondition = true;
1149
77
    }
1150
10.8k
    if (cge->GetHadContextSensitiveCondition()) {
1151
68
      impl.HadContextSensitiveCondition = true;
1152
68
    }
1153
10.8k
    if (cge->GetHadLinkLanguageSensitiveCondition()) {
1154
0
      impl.HadLinkLanguageSensitiveCondition = true;
1155
0
    }
1156
1157
10.8k
    auto linkFeature = cmLinkItem::DEFAULT;
1158
113k
    for (auto const& lib : llibs) {
1159
113k
      if (auto maybeLinkFeature = ParseLinkFeature(lib)) {
1160
2.49k
        linkFeature = std::move(*maybeLinkFeature);
1161
2.49k
        continue;
1162
2.49k
      }
1163
1164
110k
      if (this->IsLinkLookupScope(lib, lg)) {
1165
16
        continue;
1166
16
      }
1167
1168
      // Skip entries that resolve to the target itself or are empty.
1169
110k
      std::string name = this->CheckCMP0004(lib);
1170
110k
      if (this->GetPolicyStatusCMP0108() == cmPolicies::NEW) {
1171
        // resolve alias name
1172
110k
        auto* target =
1173
110k
          this->Makefile->FindTargetToUse(name, cm::AllTargetDomains);
1174
110k
        if (target) {
1175
9.28k
          name = target->GetName();
1176
9.28k
        }
1177
110k
      }
1178
110k
      if (name == this->GetName() || name.empty()) {
1179
8
        if (name == this->GetName()) {
1180
8
          this->LocalGenerator->GetCMakeInstance()->IssueMessage(
1181
8
            MessageType::FATAL_ERROR,
1182
8
            cmStrCat("Target \"", this->GetName(), "\" links to itself."),
1183
8
            this->GetBacktrace());
1184
8
          return;
1185
8
        }
1186
0
        continue;
1187
8
      }
1188
1189
      // The entry is meant for this configuration.
1190
110k
      cmLinkItem item = this->ResolveLinkItem(
1191
110k
        BT<std::string>(name, entry.Backtrace), lg, linkFeature);
1192
110k
      if (item.Target) {
1193
9.26k
        auto depsForTarget = synthTargetsForConfig.find(item.Target);
1194
9.26k
        if (depsForTarget != synthTargetsForConfig.end()) {
1195
0
          for (auto const* depForTarget : depsForTarget->second) {
1196
0
            cmLinkItem synthItem(depForTarget, item.Cross, item.Backtrace);
1197
0
            impl.Libraries.emplace_back(std::move(synthItem));
1198
0
          }
1199
0
        }
1200
101k
      } else {
1201
        // Report explicitly linked object files separately.
1202
101k
        std::string const& maybeObj = item.AsStr();
1203
101k
        if (cmSystemTools::FileIsFullPath(maybeObj)) {
1204
43.1k
          cmSourceFile const* sf =
1205
43.1k
            mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
1206
43.1k
          if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
1207
0
            item.ObjectSource = sf;
1208
0
            impl.Objects.emplace_back(std::move(item));
1209
0
            continue;
1210
0
          }
1211
43.1k
        }
1212
101k
      }
1213
1214
110k
      impl.Libraries.emplace_back(std::move(item));
1215
110k
    }
1216
1217
10.8k
    std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
1218
10.8k
    for (std::string const& sp : seenProps) {
1219
396
      if (!this->GetProperty(sp)) {
1220
264
        this->LinkImplicitNullProperties.insert(sp);
1221
264
      }
1222
396
    }
1223
10.8k
    cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards);
1224
10.8k
  }
1225
1226
  // Update the list of direct link dependencies from usage requirements.
1227
8.58k
  ComputeLinkImplTransitive(this, config, usage, impl);
1228
1229
  // Get the list of configurations considered to be DEBUG.
1230
8.58k
  std::vector<std::string> debugConfigs =
1231
8.58k
    this->Makefile->GetCMakeInstance()->GetDebugConfigs();
1232
1233
8.58k
  cmTargetLinkLibraryType linkType = ComputeLinkType(config, debugConfigs);
1234
8.58k
  cmTarget::LinkLibraryVectorType const& oldllibs =
1235
8.58k
    this->Target->GetOriginalLinkLibraries();
1236
1237
8.58k
  auto linkFeature = cmLinkItem::DEFAULT;
1238
8.58k
  for (cmTarget::LibraryID const& oldllib : oldllibs) {
1239
8.17k
    if (auto maybeLinkFeature = ParseLinkFeature(oldllib.first)) {
1240
0
      linkFeature = std::move(*maybeLinkFeature);
1241
0
      continue;
1242
0
    }
1243
1244
8.17k
    if (oldllib.second != GENERAL_LibraryType && oldllib.second != linkType) {
1245
0
      std::string name = this->CheckCMP0004(oldllib.first);
1246
0
      if (name == this->GetName() || name.empty()) {
1247
0
        continue;
1248
0
      }
1249
0
    }
1250
8.17k
  }
1251
8.58k
}
1252
1253
cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference(
1254
  std::string const& name) const
1255
0
{
1256
0
  return this->ResolveTargetReference(name, this->LocalGenerator);
1257
0
}
1258
1259
cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference(
1260
  std::string const& name, cmLocalGenerator const* lg) const
1261
153k
{
1262
153k
  TargetOrString resolved;
1263
1264
153k
  if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(name)) {
1265
19.2k
    resolved.Target = tgt;
1266
134k
  } else {
1267
134k
    resolved.String = name;
1268
134k
  }
1269
1270
153k
  return resolved;
1271
153k
}
1272
1273
cmLinkItem cmGeneratorTarget::ResolveLinkItem(
1274
  BT<std::string> const& name, std::string const& linkFeature) const
1275
0
{
1276
0
  return this->ResolveLinkItem(name, this->LocalGenerator, linkFeature);
1277
0
}
1278
1279
cmLinkItem cmGeneratorTarget::ResolveLinkItem(
1280
  BT<std::string> const& name, cmLocalGenerator const* lg,
1281
  std::string const& linkFeature) const
1282
153k
{
1283
153k
  auto bt = name.Backtrace;
1284
153k
  TargetOrString resolved = this->ResolveTargetReference(name.Value, lg);
1285
1286
153k
  if (!resolved.Target) {
1287
134k
    return cmLinkItem(resolved.String, false, bt, linkFeature);
1288
134k
  }
1289
1290
  // Check deprecation, issue message with `bt` backtrace.
1291
19.2k
  if (resolved.Target->IsDeprecated()) {
1292
0
    this->LocalGenerator->IssueDiagnostic(
1293
0
      cmDiagnostics::CMD_AUTHOR,
1294
0
      cmStrCat("The library that is being linked to, ",
1295
0
               resolved.Target->GetName(),
1296
0
               ", is marked as being deprecated by the owner.  The message "
1297
0
               "provided by the developer is: \n",
1298
0
               resolved.Target->GetDeprecation(), '\n'),
1299
0
      bt);
1300
0
  }
1301
1302
  // Skip targets that will not really be linked.  This is probably a
1303
  // name conflict between an external library and an executable
1304
  // within the project.
1305
19.2k
  if (resolved.Target->GetType() == cm::TargetType::EXECUTABLE &&
1306
26
      !resolved.Target->IsExecutableWithExports()) {
1307
26
    return cmLinkItem(resolved.Target->GetName(), false, bt, linkFeature);
1308
26
  }
1309
1310
19.2k
  return cmLinkItem(resolved.Target, false, bt, linkFeature);
1311
19.2k
}