Coverage Report

Created: 2026-10-28 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmGeneratorTarget_Wrappers.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 <map>
9
#include <string>
10
#include <unordered_set>
11
#include <utility>
12
#include <vector>
13
14
#include <cmext/algorithm>
15
16
#include "cmEvaluatedTargetProperty.h"
17
#include "cmGenExContext.h"
18
#include "cmGeneratorExpressionDAGChecker.h"
19
#include "cmList.h"
20
#include "cmListFileCache.h"
21
#include "cmLocalGenerator.h"
22
#include "cmMakefile.h"
23
#include "cmMessageType.h"
24
#include "cmStringAlgorithms.h"
25
#include "cmUnreachable.h"
26
#include "cmValue.h"
27
#include "cmake.h"
28
29
namespace {
30
31
enum class WrapperType
32
{
33
  Compile,
34
  Link,
35
};
36
37
std::string WrapperTypeToString(WrapperType type)
38
0
{
39
0
  switch (type) {
40
0
    case WrapperType::Compile:
41
0
      return "compile";
42
0
    case WrapperType::Link:
43
0
      return "link";
44
0
  }
45
0
  CM_UNREACHABLE;
46
0
}
47
48
void ProcessWrappers(cmGeneratorTarget const* tgt,
49
                     cm::EvaluatedTargetPropertyEntries const& entries,
50
                     std::vector<BT<std::string>>& wrappers,
51
                     std::unordered_set<std::string>& uniqueWrappers,
52
                     WrapperType wrapperType, bool debugWrapper)
53
0
{
54
0
  for (cm::EvaluatedTargetPropertyEntry const& entry : entries.Entries) {
55
0
    std::string usedOptions;
56
0
    for (std::string const& entryOption : entry.Values) {
57
0
      if (uniqueWrappers.insert(entryOption).second) {
58
0
        wrappers.emplace_back(entryOption, entry.Backtrace);
59
0
        if (debugWrapper) {
60
0
          usedOptions =
61
0
            cmStrCat(std::move(usedOptions), " * ", entryOption, '\n');
62
0
        }
63
0
      }
64
0
    }
65
0
    if (!usedOptions.empty()) {
66
0
      tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
67
0
        MessageType::LOG,
68
0
        cmStrCat("Used ", WrapperTypeToString(wrapperType),
69
0
                 " wrappers for target ", tgt->GetName(), ":\n", usedOptions),
70
0
        entry.Backtrace);
71
0
    }
72
0
  }
73
74
  // Order wrappers lexicographically based on their name.
75
0
  std::sort(wrappers.begin(), wrappers.end(),
76
0
            [](BT<std::string> const& a, BT<std::string> const& b) {
77
0
              return a.Value < b.Value;
78
0
            });
79
0
}
80
} // namespace
81
82
std::vector<BT<std::string>> cmGeneratorTarget::GetLinkWrappers(
83
  std::string const& config, std::string const& lang) const
84
0
{
85
0
  ConfigAndLanguage cacheKey(config, lang);
86
0
  {
87
0
    auto it = this->LinkWrappersCache.find(cacheKey);
88
0
    if (it != this->LinkWrappersCache.end()) {
89
0
      return it->second;
90
0
    }
91
0
  }
92
93
0
  std::vector<BT<std::string>> wrappers;
94
0
  std::unordered_set<std::string> uniqueWrappers;
95
0
  cm::GenEx::Context context(this->LocalGenerator, config, lang);
96
0
  cmGeneratorExpressionDAGChecker dagChecker{
97
0
    this, "LINK_WRAPPERS", nullptr, nullptr, context,
98
0
  };
99
100
0
  cmList debugProperties{ this->Makefile->GetDefinition(
101
0
    "CMAKE_DEBUG_TARGET_PROPERTIES") };
102
0
  bool debugWrappers = !this->DebugLinkWrappersDone &&
103
0
    cm::contains(debugProperties, "LINK_WRAPPERS");
104
0
  this->DebugLinkWrappersDone = true;
105
106
0
  cm::EvaluatedTargetPropertyEntries entries =
107
0
    cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
108
0
                                      this->LinkWrappersEntries);
109
0
  AddInterfaceEntries(this, "INTERFACE_LINK_WRAPPERS", context, &dagChecker,
110
0
                      entries, cm::IncludeRuntimeInterface::Yes, UseTo::Link);
111
112
0
  ProcessWrappers(this, entries, wrappers, uniqueWrappers, WrapperType::Link,
113
0
                  debugWrappers);
114
115
0
  this->LinkWrappersCache.emplace(cacheKey, wrappers);
116
0
  return wrappers;
117
0
}
118
119
std::vector<BT<std::string>> cmGeneratorTarget::GetCompileWrappers(
120
  std::string const& config, std::string const& lang) const
121
0
{
122
0
  ConfigAndLanguage cacheKey(config, lang);
123
0
  {
124
0
    auto it = this->CompileWrappersCache.find(cacheKey);
125
0
    if (it != this->CompileWrappersCache.end()) {
126
0
      return it->second;
127
0
    }
128
0
  }
129
130
0
  std::vector<BT<std::string>> wrappers;
131
0
  std::unordered_set<std::string> uniqueWrappers;
132
0
  cm::GenEx::Context context(this->LocalGenerator, config, lang);
133
0
  cmGeneratorExpressionDAGChecker dagChecker{
134
0
    this, "COMPILE_WRAPPERS", nullptr, nullptr, context,
135
0
  };
136
137
0
  cmList debugProperties{ this->Makefile->GetDefinition(
138
0
    "CMAKE_DEBUG_TARGET_PROPERTIES") };
139
0
  bool debugWrappers = !this->DebugCompileWrappersDone &&
140
0
    cm::contains(debugProperties, "COMPILE_WRAPPERS");
141
0
  this->DebugCompileWrappersDone = true;
142
143
0
  cm::EvaluatedTargetPropertyEntries entries =
144
0
    cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
145
0
                                      this->CompileWrappersEntries);
146
0
  AddInterfaceEntries(this, "INTERFACE_COMPILE_WRAPPERS", context, &dagChecker,
147
0
                      entries, cm::IncludeRuntimeInterface::Yes,
148
0
                      UseTo::Compile);
149
150
0
  ProcessWrappers(this, entries, wrappers, uniqueWrappers,
151
0
                  WrapperType::Compile, debugWrappers);
152
153
0
  this->CompileWrappersCache.emplace(cacheKey, wrappers);
154
0
  return wrappers;
155
0
}