Coverage Report

Created: 2026-04-29 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmGeneratorTarget_LinkDirectories.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 <map>
8
#include <string>
9
#include <unordered_set>
10
#include <utility>
11
#include <vector>
12
13
#include <cmext/algorithm>
14
15
#include "cmDiagnostics.h"
16
#include "cmEvaluatedTargetProperty.h"
17
#include "cmGenExContext.h"
18
#include "cmGeneratorExpressionDAGChecker.h"
19
#include "cmLinkItem.h"
20
#include "cmList.h"
21
#include "cmListFileCache.h"
22
#include "cmLocalGenerator.h"
23
#include "cmMakefile.h"
24
#include "cmMessageType.h"
25
#include "cmPolicies.h"
26
#include "cmStringAlgorithms.h"
27
#include "cmSystemTools.h"
28
#include "cmValue.h"
29
#include "cmake.h"
30
31
namespace {
32
void processLinkDirectories(cmGeneratorTarget const* tgt,
33
                            cm::EvaluatedTargetPropertyEntries& entries,
34
                            std::vector<BT<std::string>>& directories,
35
                            std::unordered_set<std::string>& uniqueDirectories,
36
                            bool debugDirectories)
37
0
{
38
0
  for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) {
39
0
    cmLinkItem const& item = entry.LinkItem;
40
0
    std::string const& targetName = item.AsStr();
41
42
0
    std::string usedDirectories;
43
0
    for (std::string& entryDirectory : entry.Values) {
44
0
      if (!cmSystemTools::FileIsFullPath(entryDirectory)) {
45
0
        if (!targetName.empty()) {
46
0
          tgt->GetLocalGenerator()->IssueMessage(
47
0
            MessageType::FATAL_ERROR,
48
0
            cmStrCat("Target \"", targetName,
49
0
                     "\" contains relative path"
50
0
                     " in its INTERFACE_LINK_DIRECTORIES:\n  \"",
51
0
                     entryDirectory, "\""));
52
0
          return;
53
0
        }
54
0
        switch (tgt->GetPolicyStatusCMP0081()) {
55
0
          case cmPolicies::WARN:
56
0
            tgt->GetLocalGenerator()->IssueDiagnostic(
57
0
              cmDiagnostics::CMD_AUTHOR,
58
0
              cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0081),
59
0
                       "\nFound relative path while evaluating"
60
0
                       " link directories of \"",
61
0
                       tgt->GetName(), "\":\n  \"", entryDirectory, "\"\n"));
62
0
            break;
63
0
          case cmPolicies::OLD:
64
0
            break;
65
0
          case cmPolicies::NEW:
66
0
            tgt->GetLocalGenerator()->IssueMessage(
67
0
              MessageType::FATAL_ERROR,
68
0
              cmStrCat("Found relative path while evaluating"
69
0
                       " link directories of \"",
70
0
                       tgt->GetName(), "\":\n  \"", entryDirectory, "\"\n"));
71
0
            return;
72
0
        }
73
0
      }
74
75
      // Sanitize the path the same way the link_directories command does
76
      // in case projects set the LINK_DIRECTORIES property directly.
77
0
      cmSystemTools::ConvertToUnixSlashes(entryDirectory);
78
0
      if (uniqueDirectories.insert(entryDirectory).second) {
79
0
        directories.emplace_back(entryDirectory, entry.Backtrace);
80
0
        if (debugDirectories) {
81
0
          usedDirectories += cmStrCat(" * ", entryDirectory, '\n');
82
0
        }
83
0
      }
84
0
    }
85
0
    if (!usedDirectories.empty()) {
86
0
      tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
87
0
        MessageType::LOG,
88
0
        cmStrCat("Used link directories for target ", tgt->GetName(), ":\n",
89
0
                 usedDirectories),
90
0
        entry.Backtrace);
91
0
    }
92
0
  }
93
0
}
94
}
95
96
void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result,
97
                                           std::string const& config,
98
                                           std::string const& language) const
99
0
{
100
0
  std::vector<BT<std::string>> tmp =
101
0
    this->GetLinkDirectories(config, language);
102
0
  result.reserve(tmp.size());
103
0
  for (BT<std::string>& v : tmp) {
104
0
    result.emplace_back(std::move(v.Value));
105
0
  }
106
0
}
107
108
std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories(
109
  std::string const& config, std::string const& language) const
110
0
{
111
0
  ConfigAndLanguage cacheKey(
112
0
    config, cmStrCat(language, this->IsDeviceLink() ? "-device" : ""));
113
0
  {
114
0
    auto it = this->LinkDirectoriesCache.find(cacheKey);
115
0
    if (it != this->LinkDirectoriesCache.end()) {
116
0
      return it->second;
117
0
    }
118
0
  }
119
0
  std::vector<BT<std::string>> result;
120
0
  std::unordered_set<std::string> uniqueDirectories;
121
122
0
  cm::GenEx::Context context(this->LocalGenerator, config, language);
123
0
  cmGeneratorExpressionDAGChecker dagChecker{
124
0
    this, "LINK_DIRECTORIES", nullptr, nullptr, context,
125
0
  };
126
127
0
  cmList debugProperties{ this->Makefile->GetDefinition(
128
0
    "CMAKE_DEBUG_TARGET_PROPERTIES") };
129
0
  bool debugDirectories = !this->DebugLinkDirectoriesDone &&
130
0
    cm::contains(debugProperties, "LINK_DIRECTORIES");
131
132
0
  this->DebugLinkDirectoriesDone = true;
133
134
0
  cm::EvaluatedTargetPropertyEntries entries =
135
0
    cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
136
0
                                      this->LinkDirectoriesEntries);
137
138
0
  AddInterfaceEntries(this, "INTERFACE_LINK_DIRECTORIES", context, &dagChecker,
139
0
                      entries, cm::IncludeRuntimeInterface::Yes,
140
0
                      this->GetPolicyStatusCMP0099() == cmPolicies::NEW
141
0
                        ? UseTo::Link
142
0
                        : UseTo::Compile);
143
144
0
  processLinkDirectories(this, entries, result, uniqueDirectories,
145
0
                         debugDirectories);
146
147
0
  this->LinkDirectoriesCache.emplace(cacheKey, result);
148
0
  return result;
149
0
}