Coverage Report

Created: 2026-04-29 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmExportTryCompileFileGenerator.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
#include "cmExportTryCompileFileGenerator.h"
4
5
#include <map>
6
#include <utility>
7
8
#include <cm/memory>
9
#include <cm/string_view>
10
#include <cmext/string_view>
11
12
#include "cmGenExContext.h"
13
#include "cmGeneratorExpression.h"
14
#include "cmGeneratorExpressionDAGChecker.h"
15
#include "cmGeneratorFileSet.h"
16
#include "cmGeneratorTarget.h"
17
#include "cmGlobalGenerator.h"
18
#include "cmList.h"
19
#include "cmLocalGenerator.h"
20
#include "cmMakefile.h"
21
#include "cmMessageType.h"
22
#include "cmOutputConverter.h"
23
#include "cmStateTypes.h"
24
#include "cmStringAlgorithms.h"
25
#include "cmSystemTools.h"
26
#include "cmTarget.h"
27
#include "cmValue.h"
28
29
cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
30
  cmGlobalGenerator* gg, std::vector<std::string> const& targets,
31
  cmMakefile* mf, std::set<std::string> const& langs)
32
0
  : Languages(langs.begin(), langs.end())
33
0
{
34
0
  gg->CreateImportedGenerationObjects(mf, targets, this->Exports);
35
0
}
Unexecuted instantiation: cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(cmGlobalGenerator*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmMakefile*, std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&)
Unexecuted instantiation: cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(cmGlobalGenerator*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, cmMakefile*, std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&)
36
37
void cmExportTryCompileFileGenerator::IssueMessage(
38
  MessageType type, std::string const& message) const
39
0
{
40
0
  switch (type) {
41
0
    case MessageType::FATAL_ERROR:
42
0
    case MessageType::INTERNAL_ERROR:
43
0
      cmSystemTools::Error(message);
44
0
      break;
45
0
    case MessageType::WARNING:
46
0
      cmSystemTools::Message(cmStrCat("CMake Warning: "_s, message),
47
0
                             "Warning");
48
0
      break;
49
0
    default:
50
0
      cmSystemTools::Message(message);
51
0
  }
52
0
}
53
54
void cmExportTryCompileFileGenerator::IssueDiagnostic(
55
  cmDiagnosticCategory category, std::string const& message) const
56
0
{
57
0
  cm::string_view const cname =
58
0
    cmDiagnostics::GetCategoryString(category).substr(4);
59
0
  cmSystemTools::Message(
60
0
    cmStrCat("CMake Diagnostic ("_s, cname, "): "_s, message), "Diagnostic");
61
0
}
62
63
bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
64
0
{
65
0
  std::set<cmGeneratorTarget const*> emitted;
66
0
  std::set<cmGeneratorTarget const*> emittedDeps;
67
0
  while (!this->Exports.empty()) {
68
0
    cmGeneratorTarget const* te = this->Exports.back();
69
0
    this->Exports.pop_back();
70
0
    if (emitted.insert(te).second) {
71
0
      emittedDeps.insert(te);
72
0
      this->GenerateImportTargetCode(os, te, te->GetType());
73
74
0
      ImportPropertyMap properties;
75
76
0
      for (std::string const& lang : this->Languages) {
77
0
        for (auto i : cmGeneratorTarget::BuiltinTransitiveProperties) {
78
0
          this->FindTargets(std::string(i.second.InterfaceName), te, lang,
79
0
                            emittedDeps);
80
0
        }
81
0
      }
82
83
0
      this->PopulateProperties(te, properties, emittedDeps);
84
85
0
      this->GenerateInterfaceProperties(te, os, properties);
86
0
    }
87
0
  }
88
0
  return true;
89
0
}
90
91
std::string cmExportTryCompileFileGenerator::FindTargets(
92
  std::string const& propName, cmGeneratorTarget const* tgt,
93
  std::string const& language, std::set<cmGeneratorTarget const*>& emitted)
94
0
{
95
0
  cmValue prop = tgt->GetProperty(propName);
96
0
  if (!prop) {
97
0
    return std::string();
98
0
  }
99
100
0
  cm::GenEx::Context context(tgt->LocalGenerator, this->Config, language);
101
102
0
  cmGeneratorExpression ge(*tgt->Makefile->GetCMakeInstance());
103
104
0
  std::unique_ptr<cmGeneratorExpressionDAGChecker> parentDagChecker;
105
0
  if (propName == "INTERFACE_LINK_OPTIONS") {
106
    // To please constraint checks of DAGChecker, this property must have
107
    // LINK_OPTIONS property as parent
108
0
    parentDagChecker = cm::make_unique<cmGeneratorExpressionDAGChecker>(
109
0
      tgt, "LINK_OPTIONS", nullptr, nullptr, context);
110
0
  }
111
0
  cmGeneratorExpressionDAGChecker dagChecker{
112
0
    tgt, propName, nullptr, parentDagChecker.get(), context,
113
0
  };
114
115
0
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*prop);
116
117
0
  cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE,
118
0
                     cmTarget::Visibility::Normal, tgt->Target->GetMakefile(),
119
0
                     cmTarget::PerConfig::Yes);
120
0
  dummyHead.SetIsForTryCompile();
121
122
0
  cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator());
123
124
0
  std::string result = cge->Evaluate(context, &dagChecker, &gDummyHead, tgt);
125
126
0
  std::set<cmGeneratorTarget const*> const& allTargets =
127
0
    cge->GetAllTargetsSeen();
128
0
  for (cmGeneratorTarget const* target : allTargets) {
129
0
    if (emitted.insert(target).second) {
130
0
      this->Exports.push_back(target);
131
0
    }
132
0
  }
133
0
  return result;
134
0
}
135
136
void cmExportTryCompileFileGenerator::PopulateProperties(
137
  cmGeneratorTarget const* target, ImportPropertyMap& properties,
138
  std::set<cmGeneratorTarget const*>& emitted)
139
0
{
140
  // Look through all non-special properties.
141
0
  std::vector<std::string> props = target->GetPropertyKeys();
142
  // Include special properties that might be relevant here.
143
0
  props.emplace_back("INTERFACE_LINK_LIBRARIES");
144
0
  props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT");
145
0
  props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE");
146
0
  for (std::string const& p : props) {
147
0
    cmValue v = target->GetProperty(p);
148
0
    if (!v) {
149
0
      continue;
150
0
    }
151
0
    properties[p] = *v;
152
153
0
    if (cmHasLiteralPrefix(p, "IMPORTED_LINK_INTERFACE_LIBRARIES") ||
154
0
        cmHasLiteralPrefix(p, "IMPORTED_LINK_DEPENDENT_LIBRARIES") ||
155
0
        cmHasLiteralPrefix(p, "INTERFACE_LINK_LIBRARIES")) {
156
0
      std::string evalResult =
157
0
        this->FindTargets(p, target, std::string(), emitted);
158
159
0
      cmList depends{ evalResult };
160
0
      for (std::string const& li : depends) {
161
0
        cmGeneratorTarget* tgt =
162
0
          target->GetLocalGenerator()->FindGeneratorTargetToUse(li);
163
0
        if (tgt && emitted.insert(tgt).second) {
164
0
          this->Exports.push_back(tgt);
165
0
        }
166
0
      }
167
0
    }
168
0
  }
169
0
}
170
171
std::string cmExportTryCompileFileGenerator::InstallNameDir(
172
  cmGeneratorTarget const* target, std::string const& config)
173
0
{
174
0
  std::string install_name_dir;
175
176
0
  cmMakefile* mf = target->Target->GetMakefile();
177
0
  if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
178
0
    install_name_dir = target->GetInstallNameDirForBuildTree(config);
179
0
  }
180
181
0
  return install_name_dir;
182
0
}
183
184
std::string cmExportTryCompileFileGenerator::GetFileSetDirectories(
185
  cmGeneratorTarget* /*gte*/, cmGeneratorFileSet const* fileSet,
186
  cmTargetExport const* /*te*/)
187
0
{
188
0
  return cmOutputConverter::EscapeForCMake(
189
0
    cmList::to_string(fileSet->GetDirectoryEntries()));
190
0
}
191
192
std::string cmExportTryCompileFileGenerator::GetFileSetFiles(
193
  cmGeneratorTarget* /*gte*/, cmGeneratorFileSet const* fileSet,
194
  cmTargetExport const* /*te*/)
195
0
{
196
0
  return cmOutputConverter::EscapeForCMake(
197
0
    cmList::to_string(fileSet->GetFileEntries()));
198
0
}