Coverage Report

Created: 2026-10-28 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmInstallGetRuntimeDependenciesGenerator.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 "cmInstallGetRuntimeDependenciesGenerator.h"
4
5
#include <memory>
6
#include <ostream>
7
#include <set>
8
#include <string>
9
#include <utility>
10
#include <vector>
11
12
#include <cm/optional>
13
#include <cm/string_view>
14
#include <cmext/string_view>
15
16
#include "cmDiagnosticContext.h"
17
#include "cmGeneratorExpression.h"
18
#include "cmInstallRuntimeDependencySet.h"
19
#include "cmListFileCache.h"
20
#include "cmLocalGenerator.h"
21
#include "cmMakefile.h"
22
#include "cmOutputConverter.h"
23
#include "cmPolicies.h"
24
#include "cmScriptGenerator.h"
25
#include "cmStringAlgorithms.h"
26
27
class cmGeneratorTarget;
28
29
namespace {
30
template <typename T, typename F>
31
void WriteMultiArgument(std::ostream& os, cm::string_view keyword,
32
                        std::vector<T> const& list,
33
                        cmScriptGeneratorIndent indent, F transform)
34
0
{
35
0
  bool first = true;
36
0
  for (auto const& item : list) {
37
0
    cm::optional<std::string> result = transform(item);
38
0
    if (result) {
39
0
      if (first) {
40
0
        os << indent << "  " << keyword << "\n";
41
0
        first = false;
42
0
      }
43
0
      os << indent << "    " << *result << "\n";
44
0
    }
45
0
  }
46
0
}
Unexecuted instantiation: cmInstallGetRuntimeDependenciesGenerator.cxx:void (anonymous namespace)::WriteMultiArgument<std::__1::unique_ptr<cmInstallRuntimeDependencySet::Item, std::__1::default_delete<cmInstallRuntimeDependencySet::Item> >, (anonymous namespace)::WriteFilesArgument(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::vector<std::__1::unique_ptr<cmInstallRuntimeDependencySet::Item, std::__1::default_delete<cmInstallRuntimeDependencySet::Item> >, std::__1::allocator<std::__1::unique_ptr<cmInstallRuntimeDependencySet::Item, std::__1::default_delete<cmInstallRuntimeDependencySet::Item> > > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cmScriptGeneratorIndent)::$_0>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::vector<std::__1::unique_ptr<cmInstallRuntimeDependencySet::Item, std::__1::default_delete<cmInstallRuntimeDependencySet::Item> >, std::__1::allocator<std::__1::unique_ptr<cmInstallRuntimeDependencySet::Item, std::__1::default_delete<cmInstallRuntimeDependencySet::Item> > > > const&, cmScriptGeneratorIndent, (anonymous namespace)::WriteFilesArgument(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::vector<std::__1::unique_ptr<cmInstallRuntimeDependencySet::Item, std::__1::default_delete<cmInstallRuntimeDependencySet::Item> >, std::__1::allocator<std::__1::unique_ptr<cmInstallRuntimeDependencySet::Item, std::__1::default_delete<cmInstallRuntimeDependencySet::Item> > > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cmScriptGeneratorIndent)::$_0)
Unexecuted instantiation: cmInstallGetRuntimeDependenciesGenerator.cxx:void (anonymous namespace)::WriteMultiArgument<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, (anonymous namespace)::WriteGenexEvaluatorArgument(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, 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&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cmLocalGenerator*, cmScriptGeneratorIndent)::$_0>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, 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&, cmScriptGeneratorIndent, (anonymous namespace)::WriteGenexEvaluatorArgument(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string_view<char, std::__1::char_traits<char> >, 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&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cmLocalGenerator*, cmScriptGeneratorIndent)::$_0)
47
48
void WriteFilesArgument(
49
  std::ostream& os, cm::string_view keyword,
50
  std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>> const&
51
    items,
52
  std::string const& config, cmScriptGeneratorIndent indent)
53
0
{
54
0
  WriteMultiArgument(
55
0
    os, keyword, items, indent,
56
0
    [config](std::unique_ptr<cmInstallRuntimeDependencySet::Item> const& i)
57
0
      -> std::string { return cmStrCat('"', i->GetItemPath(config), '"'); });
58
0
}
59
60
void WriteGenexEvaluatorArgument(std::ostream& os, cm::string_view keyword,
61
                                 std::vector<std::string> const& genexes,
62
                                 std::string const& config,
63
                                 cmLocalGenerator* lg,
64
                                 cmScriptGeneratorIndent indent)
65
0
{
66
0
  WriteMultiArgument(
67
0
    os, keyword, genexes, indent,
68
0
    [config, lg](std::string const& genex) -> cm::optional<std::string> {
69
0
      std::string result = cmGeneratorExpression::Evaluate(genex, lg, config);
70
0
      if (result.empty()) {
71
0
        return cm::nullopt;
72
0
      }
73
0
      return cmOutputConverter::EscapeForCMake(result);
74
0
    });
75
0
}
76
}
77
78
cmInstallGetRuntimeDependenciesGenerator::
79
  cmInstallGetRuntimeDependenciesGenerator(
80
    cmInstallRuntimeDependencySet* runtimeDependencySet,
81
    std::vector<std::string> directories,
82
    std::vector<std::string> preIncludeRegexes,
83
    std::vector<std::string> preExcludeRegexes,
84
    std::vector<std::string> postIncludeRegexes,
85
    std::vector<std::string> postExcludeRegexes,
86
    std::vector<std::string> postIncludeFiles,
87
    std::vector<std::string> postExcludeFiles, std::string libraryComponent,
88
    std::string frameworkComponent, bool noInstallRPath, char const* depsVar,
89
    char const* rpathPrefix, std::vector<std::string> const& configurations,
90
    MessageLevel message, bool excludeFromAll, cmListFileBacktrace backtrace,
91
    cmPolicies::PolicyStatus policyStatusCMP0207)
92
0
  : cmInstallGenerator("", configurations, "", message, excludeFromAll, false,
93
0
                       cmDiagnosticContext{ std::move(backtrace) })
94
0
  , RuntimeDependencySet(runtimeDependencySet)
95
0
  , Directories(std::move(directories))
96
0
  , PreIncludeRegexes(std::move(preIncludeRegexes))
97
0
  , PreExcludeRegexes(std::move(preExcludeRegexes))
98
0
  , PostIncludeRegexes(std::move(postIncludeRegexes))
99
0
  , PostExcludeRegexes(std::move(postExcludeRegexes))
100
0
  , PostIncludeFiles(std::move(postIncludeFiles))
101
0
  , PostExcludeFiles(std::move(postExcludeFiles))
102
0
  , LibraryComponent(std::move(libraryComponent))
103
0
  , FrameworkComponent(std::move(frameworkComponent))
104
0
  , PolicyStatusCMP0207(policyStatusCMP0207)
105
0
  , NoInstallRPath(noInstallRPath)
106
0
  , DepsVar(depsVar)
107
0
  , RPathPrefix(rpathPrefix)
108
0
{
109
0
  this->ActionsPerConfig = true;
110
0
}
111
112
bool cmInstallGetRuntimeDependenciesGenerator::Compute(cmLocalGenerator* lg)
113
0
{
114
0
  this->LocalGenerator = lg;
115
0
  return true;
116
0
}
117
118
void cmInstallGetRuntimeDependenciesGenerator::GetInstallBuildDependencies(
119
  std::string const&, std::vector<BuildDependency>& dependencies) const
120
0
{
121
0
  std::vector<cmGeneratorTarget const*> targets;
122
0
  this->RuntimeDependencySet->GetInstallBuildDependencies(targets);
123
0
  for (cmGeneratorTarget const* target : targets) {
124
0
    dependencies.push_back({ target, BuildDependencyType::Normal });
125
0
  }
126
0
}
127
128
void cmInstallGetRuntimeDependenciesGenerator::
129
  GetInstallBuildDependencyComponents(
130
    std::vector<std::string>& components) const
131
0
{
132
0
  if (!this->LibraryComponent.empty()) {
133
0
    components.push_back(this->LibraryComponent);
134
0
  }
135
0
  if (!this->FrameworkComponent.empty() &&
136
0
      this->FrameworkComponent != this->LibraryComponent) {
137
0
    components.push_back(this->FrameworkComponent);
138
0
  }
139
0
}
140
141
void cmInstallGetRuntimeDependenciesGenerator::GenerateScript(std::ostream& os)
142
0
{
143
  // Track indentation.
144
0
  Indent indent;
145
146
  // Begin this block of installation.
147
0
  os << indent << "if(";
148
0
  if (this->FrameworkComponent.empty() ||
149
0
      this->FrameworkComponent == this->LibraryComponent) {
150
0
    os << this->CreateComponentTest(this->LibraryComponent,
151
0
                                    this->ExcludeFromAll);
152
0
  } else {
153
0
    os << this->CreateComponentTest(this->LibraryComponent, true) << " OR "
154
0
       << this->CreateComponentTest(this->FrameworkComponent,
155
0
                                    this->ExcludeFromAll);
156
0
  }
157
0
  os << ")\n";
158
159
  // Generate the script possibly with per-configuration code.
160
0
  this->GenerateScriptConfigs(os, indent.Next());
161
162
  // End this block of installation.
163
0
  os << indent << "endif()\n\n";
164
0
}
165
166
void cmInstallGetRuntimeDependenciesGenerator::GenerateScriptForConfig(
167
  std::ostream& os, std::string const& config, Indent indent)
168
0
{
169
0
  std::string installNameTool =
170
0
    this->LocalGenerator->GetMakefile()->GetSafeDefinition(
171
0
      "CMAKE_INSTALL_NAME_TOOL");
172
173
0
  Indent inputIndent = indent;
174
0
  if (this->PolicyStatusCMP0207 != cmPolicies::WARN) {
175
0
    indent = indent.Next();
176
0
    os << inputIndent << "block(SCOPE_FOR POLICIES)\n"
177
0
       << indent << "cmake_policy(SET CMP0207 "
178
0
       << (this->PolicyStatusCMP0207 == cmPolicies::NEW ? "NEW" : "OLD")
179
0
       << ")\n";
180
0
  }
181
0
  os << indent << "file(GET_RUNTIME_DEPENDENCIES\n"
182
0
     << indent << "  RESOLVED_DEPENDENCIES_VAR " << this->DepsVar << '\n';
183
0
  WriteFilesArgument(os, "EXECUTABLES"_s,
184
0
                     this->RuntimeDependencySet->GetExecutables(), config,
185
0
                     indent);
186
0
  WriteFilesArgument(os, "LIBRARIES"_s,
187
0
                     this->RuntimeDependencySet->GetLibraries(), config,
188
0
                     indent);
189
0
  WriteFilesArgument(os, "MODULES"_s, this->RuntimeDependencySet->GetModules(),
190
0
                     config, indent);
191
0
  if (this->RuntimeDependencySet->GetBundleExecutable()) {
192
0
    os << indent << "  BUNDLE_EXECUTABLE \""
193
0
       << this->RuntimeDependencySet->GetBundleExecutable()->GetItemPath(
194
0
            config)
195
0
       << "\"\n";
196
0
  }
197
0
  WriteGenexEvaluatorArgument(os, "DIRECTORIES"_s, this->Directories, config,
198
0
                              this->LocalGenerator, indent);
199
0
  WriteGenexEvaluatorArgument(os, "PRE_INCLUDE_REGEXES"_s,
200
0
                              this->PreIncludeRegexes, config,
201
0
                              this->LocalGenerator, indent);
202
0
  WriteGenexEvaluatorArgument(os, "PRE_EXCLUDE_REGEXES"_s,
203
0
                              this->PreExcludeRegexes, config,
204
0
                              this->LocalGenerator, indent);
205
0
  WriteGenexEvaluatorArgument(os, "POST_INCLUDE_REGEXES"_s,
206
0
                              this->PostIncludeRegexes, config,
207
0
                              this->LocalGenerator, indent);
208
0
  WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_REGEXES"_s,
209
0
                              this->PostExcludeRegexes, config,
210
0
                              this->LocalGenerator, indent);
211
0
  WriteGenexEvaluatorArgument(os, "POST_INCLUDE_FILES"_s,
212
0
                              this->PostIncludeFiles, config,
213
0
                              this->LocalGenerator, indent);
214
0
  WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_FILES"_s,
215
0
                              this->PostExcludeFiles, config,
216
0
                              this->LocalGenerator, indent);
217
218
0
  std::set<std::string> postExcludeFiles;
219
0
  auto const addPostExclude =
220
0
    [config, &postExcludeFiles, this](
221
0
      std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>> const&
222
0
        tgts) {
223
0
      for (auto const& item : tgts) {
224
0
        item->AddPostExcludeFiles(config, postExcludeFiles,
225
0
                                  this->RuntimeDependencySet);
226
0
      }
227
0
    };
228
0
  addPostExclude(this->RuntimeDependencySet->GetExecutables());
229
0
  addPostExclude(this->RuntimeDependencySet->GetLibraries());
230
0
  addPostExclude(this->RuntimeDependencySet->GetModules());
231
0
  bool first = true;
232
0
  for (auto const& file : postExcludeFiles) {
233
0
    if (first) {
234
0
      os << indent << "  POST_EXCLUDE_FILES_STRICT\n";
235
0
      first = false;
236
0
    }
237
0
    os << indent << "    \"" << file << "\"\n";
238
0
  }
239
240
0
  if (!installNameTool.empty() && !this->NoInstallRPath) {
241
0
    os << indent << "  RPATH_PREFIX " << this->RPathPrefix << '\n';
242
0
  }
243
0
  os << indent << "  )\n";
244
245
0
  if (this->PolicyStatusCMP0207 != cmPolicies::WARN) {
246
0
    os << inputIndent << "endblock()\n";
247
0
  }
248
0
}