Coverage Report

Created: 2026-10-28 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmGeneratorTarget_Sources.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 "cmConfigure.h"
8
9
#include <algorithm>
10
#include <cstddef>
11
#include <functional>
12
#include <map>
13
#include <memory>
14
#include <set>
15
#include <string>
16
#include <unordered_set>
17
#include <utility>
18
#include <vector>
19
20
#include <cm/string_view>
21
#include <cmext/algorithm>
22
23
#include "cmsys/RegularExpression.hxx"
24
25
#include "cmEvaluatedTargetProperty.h"
26
#include "cmFileSetMetadata.h"
27
#include "cmGenExContext.h"
28
#include "cmGeneratorExpression.h"
29
#include "cmGeneratorExpressionDAGChecker.h"
30
#include "cmGeneratorFileSet.h"
31
#include "cmGeneratorFileSets.h"
32
#include "cmGlobalGenerator.h"
33
#include "cmLinkItem.h"
34
#include "cmList.h"
35
#include "cmListFileCache.h"
36
#include "cmLocalGenerator.h"
37
#include "cmMakefile.h"
38
#include "cmMessageType.h"
39
#include "cmPolicies.h"
40
#include "cmSourceFile.h"
41
#include "cmSourceFileLocation.h"
42
#include "cmSourceGroup.h"
43
#include "cmStringAlgorithms.h"
44
#include "cmSystemTools.h"
45
#include "cmTarget.h"
46
#include "cmTargetTypes.h"
47
#include "cmValue.h"
48
#include "cmake.h"
49
50
namespace {
51
using UseTo = cmGeneratorTarget::UseTo;
52
53
void AddObjectEntries(cmGeneratorTarget const* headTarget,
54
                      cm::GenEx::Context const& context,
55
                      cmGeneratorExpressionDAGChecker* dagChecker,
56
                      cm::EvaluatedTargetPropertyEntries& entries)
57
626
{
58
626
  if (cmLinkImplementationLibraries const* impl =
59
626
        headTarget->GetLinkImplementationLibraries(context.Config,
60
626
                                                   UseTo::Link)) {
61
616
    entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
62
1.46k
    for (cmLinkItem const& lib : impl->Libraries) {
63
1.46k
      if (lib.Target &&
64
1.46k
          lib.Target->GetType() == cm::TargetType::OBJECT_LIBRARY) {
65
455
        std::string uniqueName =
66
455
          headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
67
455
            lib.Target);
68
455
        std::string genex =
69
455
          cmStrCat("$<TARGET_OBJECTS:", std::move(uniqueName), '>');
70
455
        cmGeneratorExpression ge(*headTarget->Makefile->GetCMakeInstance(),
71
455
                                 lib.Backtrace);
72
455
        std::unique_ptr<cmCompiledGeneratorExpression> cge =
73
455
          ge.Parse(std::move(genex));
74
455
        cge->SetEvaluateForBuildsystem(true);
75
76
455
        cm::EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
77
455
        cmExpandList(cge->Evaluate(context, dagChecker, headTarget),
78
455
                     ee.Values);
79
455
        if (cge->GetHadContextSensitiveCondition()) {
80
0
          ee.ContextDependent = true;
81
0
        }
82
455
        entries.Entries.emplace_back(std::move(ee));
83
455
      }
84
1.46k
    }
85
616
  }
86
626
}
87
88
void AddFileSetEntries(cmGeneratorTarget const* headTarget,
89
                       cmGeneratorFileSets const* fileSets,
90
                       cm::GenEx::Context const& context,
91
                       cmGeneratorExpressionDAGChecker* dagChecker,
92
                       cm::EvaluatedTargetPropertyEntries& entries)
93
974
{
94
974
  auto sources =
95
974
    fileSets->GetSources(context, headTarget,
96
974
                         cm::FileSetMetadata::FileSetDomainSet{
97
974
                           cm::FileSetMetadata::FileSetDomain::NATIVE },
98
974
                         dagChecker);
99
974
  entries =
100
974
    EvaluateTargetPropertyEntries(headTarget, context, dagChecker, sources);
101
974
}
102
103
bool processSources(cmGeneratorTarget const* tgt, std::string const& config,
104
                    cm::EvaluatedTargetPropertyEntries& entries,
105
                    std::vector<BT<std::string>>& srcs,
106
                    std::unordered_set<std::string>& uniqueSrcs,
107
                    bool debugSources,
108
                    std::function<void(cmSourceFile*)> postProcess = {})
109
4.52k
{
110
4.52k
  cmMakefile* mf = tgt->Target->GetMakefile();
111
112
4.52k
  bool contextDependent = entries.HadContextSensitiveCondition;
113
114
4.52k
  for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) {
115
4.51k
    if (entry.ContextDependent) {
116
0
      contextDependent = true;
117
0
    }
118
119
4.51k
    cmLinkItem const& item = entry.LinkItem;
120
4.51k
    std::string const& targetName = item.AsStr();
121
122
4.51k
    for (std::string& src : entry.Values) {
123
1.31k
      cmSourceFile* sf = mf->GetOrCreateSource(src);
124
1.31k
      std::string e;
125
1.31k
      std::string w;
126
1.31k
      std::string fullPath = sf->ResolveFullPath(&e, &w);
127
1.31k
      cmLocalGenerator const* const lg = tgt->GetLocalGenerator();
128
1.31k
      if (!w.empty()) {
129
0
        lg->IssuePolicyWarning(cmPolicies::CMP0115, {}, w, entry.Backtrace);
130
0
      }
131
1.31k
      if (fullPath.empty()) {
132
0
        if (!e.empty()) {
133
0
          lg->IssueMessage(MessageType::FATAL_ERROR, e, entry.Backtrace);
134
0
        }
135
0
        return contextDependent;
136
0
      }
137
138
1.31k
      if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src)) {
139
0
        if (!targetName.empty()) {
140
0
          tgt->GetLocalGenerator()->IssueMessage(
141
0
            MessageType::FATAL_ERROR,
142
0
            cmStrCat("Target \"", targetName,
143
0
                     "\" contains relative path in its INTERFACE_SOURCES:\n  "
144
0
                     "\"",
145
0
                     src, '"'));
146
0
        } else {
147
0
          tgt->GetLocalGenerator()->IssueMessage(
148
0
            MessageType::FATAL_ERROR,
149
0
            cmStrCat("Found relative path while evaluating sources of \"",
150
0
                     tgt->GetName(), "\":\n  \"", src, "\"\n"));
151
0
        }
152
0
        return contextDependent;
153
0
      }
154
1.31k
      src = fullPath;
155
156
1.31k
      if (postProcess) {
157
0
        postProcess(sf);
158
0
      }
159
1.31k
    }
160
4.51k
    std::string usedSources;
161
4.51k
    for (std::string const& src : entry.Values) {
162
1.31k
      if (uniqueSrcs.insert(src).second) {
163
1.31k
        srcs.emplace_back(src, entry.Backtrace);
164
1.31k
        if (debugSources) {
165
0
          usedSources = cmStrCat(std::move(usedSources), " * ", src, '\n');
166
0
        }
167
1.31k
      } else {
168
0
        auto const& fileSets =
169
0
          tgt->GetGeneratorFileSets()->GetAllFileSetsForSource(config, src);
170
0
        if (fileSets.empty()) {
171
0
          continue;
172
0
        }
173
0
        auto fileMustBeUnique = [&fileSets]() -> bool {
174
0
          return std::none_of(
175
0
            fileSets.begin(), fileSets.end(),
176
0
            [](cmGeneratorFileSet const* fileSet) {
177
0
              return cm::FileSetMetadata::GetAttributes(fileSet->GetType())
178
0
                .contains(cm::FileSetMetadata::FileSetAttributes::
179
0
                            FilesInMultipleFileSets);
180
0
            });
181
0
        };
182
0
        if (fileMustBeUnique()) {
183
0
          auto const* fileSet = *fileSets.begin();
184
0
          switch (tgt->GetPolicyStatusCMP0211()) {
185
0
            case cmPolicies::WARN:
186
0
              tgt->GetLocalGenerator()->IssuePolicyWarning(
187
0
                cmPolicies::CMP0211, {},
188
0
                cmStrCat("In target \"", tgt->GetName(), "\" the file\n  ",
189
0
                         src, "\nalready belongs to file set \"",
190
0
                         fileSet->GetName(), "\"."));
191
0
              CM_FALLTHROUGH;
192
0
            case cmPolicies::OLD:
193
0
              break;
194
0
            default:
195
0
              tgt->GetLocalGenerator()->IssueMessage(
196
0
                MessageType::FATAL_ERROR,
197
0
                cmStrCat("In target \"", tgt->GetName(), "\" the file\n  ",
198
0
                         src, "\nalready belongs to file set \"",
199
0
                         fileSet->GetName(), "\"."));
200
0
          }
201
0
        }
202
0
      }
203
1.31k
    }
204
4.51k
    if (!usedSources.empty()) {
205
0
      tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
206
0
        MessageType::LOG,
207
0
        cmStrCat("Used sources for target ", tgt->GetName(), ":\n",
208
0
                 usedSources),
209
0
        entry.Backtrace);
210
0
    }
211
4.51k
  }
212
4.52k
  return contextDependent;
213
4.52k
}
214
}
215
216
std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
217
  std::string const& config) const
218
974
{
219
974
  std::vector<BT<std::string>> files;
220
221
974
  cmList debugProperties{ this->Makefile->GetDefinition(
222
974
    "CMAKE_DEBUG_TARGET_PROPERTIES") };
223
974
  bool debugSources =
224
974
    !this->DebugSourcesDone && cm::contains(debugProperties, "SOURCES");
225
226
974
  this->DebugSourcesDone = true;
227
228
974
  cm::GenEx::Context context(this->LocalGenerator, config,
229
974
                             /*language=*/std::string());
230
231
974
  cmGeneratorExpressionDAGChecker dagChecker{
232
974
    this, "SOURCES", nullptr, nullptr, context,
233
974
  };
234
235
974
  cm::EvaluatedTargetPropertyEntries entries =
236
974
    cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
237
974
                                      this->SourceEntries);
238
239
974
  std::unordered_set<std::string> uniqueSrcs;
240
974
  bool contextDependentDirectSources =
241
974
    processSources(this, config, entries, files, uniqueSrcs, debugSources);
242
243
  // Collect INTERFACE_SOURCES of all direct link-dependencies.
244
974
  cm::EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
245
974
  cm::AddInterfaceEntries(this, "INTERFACE_SOURCES", context, &dagChecker,
246
974
                          linkInterfaceSourcesEntries,
247
974
                          cm::IncludeRuntimeInterface::No, UseTo::Compile);
248
974
  bool contextDependentInterfaceSources =
249
974
    processSources(this, config, linkInterfaceSourcesEntries, files,
250
974
                   uniqueSrcs, debugSources);
251
252
  // Collect TARGET_OBJECTS of direct object link-dependencies.
253
974
  bool contextDependentObjects = false;
254
974
  if (this->GetType() != cm::TargetType::OBJECT_LIBRARY) {
255
626
    cm::EvaluatedTargetPropertyEntries linkObjectsEntries;
256
626
    AddObjectEntries(this, context, &dagChecker, linkObjectsEntries);
257
626
    contextDependentObjects = processSources(this, config, linkObjectsEntries,
258
626
                                             files, uniqueSrcs, debugSources);
259
    // Note that for imported targets or multi-config generators supporting
260
    // cross-config builds the paths to the object files must be per-config,
261
    // so contextDependentObjects will be true here even if object libraries
262
    // are specified without per-config generator expressions.
263
626
  }
264
265
  // Collect this target's file sets.
266
974
  cmGeneratorExpressionDAGChecker fsDagChecker{
267
974
    this, "SOURCES", nullptr, nullptr, context,
268
974
  };
269
270
974
  cm::EvaluatedTargetPropertyEntries fileSetEntries;
271
974
  AddFileSetEntries(this, this->FileSets.get(), context, &fsDagChecker,
272
974
                    fileSetEntries);
273
974
  auto processFileSetEntry = [this, &config](cmSourceFile* sf) {
274
0
    cmGeneratorFileSet const* fileSet = this->GetFileSetForSource(config, sf);
275
0
    if (fileSet && fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
276
0
      sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
277
0
#if !defined(CMAKE_BOOTSTRAP)
278
0
      cmMakefile* mf = this->Target->GetMakefile();
279
0
      std::string const& path = sf->GetFullPath();
280
0
      bool found = false;
281
0
      for (auto const& sg : mf->GetSourceGroups()) {
282
0
        if (sg->MatchChildrenFiles(path)) {
283
0
          found = true;
284
0
          break;
285
0
        }
286
0
      }
287
0
      if (!found) {
288
0
        mf->GetOrCreateSourceGroup("Header Files")->AddGroupFile(path);
289
0
      }
290
0
#endif
291
0
    }
292
0
  };
293
974
  bool contextDependentFileSets =
294
974
    processSources(this, config, fileSetEntries, files, uniqueSrcs,
295
974
                   debugSources, processFileSetEntry);
296
297
  // Collect file sets INTERFACE_SOURCES of all direct link-dependencies.
298
974
  cm::EvaluatedTargetPropertyEntries linkInterfaceFileSetsEntries;
299
974
  cm::AddInterfaceFileSetsEntries(this, cm::FileSetMetadata::SOURCES,
300
974
                                  "INTERFACE_SOURCES", context, &fsDagChecker,
301
974
                                  linkInterfaceFileSetsEntries);
302
974
  bool contextDependentInterfaceFileSets =
303
974
    processSources(this, config, linkInterfaceFileSetsEntries, files,
304
974
                   uniqueSrcs, debugSources);
305
306
  // Determine if sources are context-dependent or not.
307
974
  if (!contextDependentDirectSources && !contextDependentInterfaceSources &&
308
456
      !contextDependentObjects && !contextDependentFileSets &&
309
455
      !contextDependentInterfaceFileSets) {
310
455
    this->SourcesAreContextDependent = Tribool::False;
311
519
  } else {
312
519
    this->SourcesAreContextDependent = Tribool::True;
313
519
  }
314
315
974
  return files;
316
974
}
317
318
void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
319
                                       std::string const& config) const
320
603
{
321
603
  std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config);
322
603
  files.reserve(tmp.size());
323
603
  for (BT<cmSourceFile*>& v : tmp) {
324
603
    files.push_back(v.Value);
325
603
  }
326
603
}
327
328
std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles(
329
  std::string const& config) const
330
1.20k
{
331
1.20k
  std::vector<BT<cmSourceFile*>> files;
332
1.20k
  KindedSources const& kinded = this->GetKindedSources(config);
333
1.20k
  files.reserve(kinded.Sources.size());
334
1.68k
  for (SourceAndKind const& si : kinded.Sources) {
335
1.68k
    files.push_back(si.Source);
336
1.68k
  }
337
1.20k
  return files;
338
1.20k
}
339
340
void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
341
  std::vector<cmSourceFile*>& files, std::string const& config) const
342
0
{
343
0
  std::vector<BT<cmSourceFile*>> tmp =
344
0
    this->GetSourceFilesWithoutObjectLibraries(config);
345
0
  files.reserve(tmp.size());
346
0
  for (BT<cmSourceFile*>& v : tmp) {
347
0
    files.push_back(v.Value);
348
0
  }
349
0
}
350
351
std::vector<BT<cmSourceFile*>>
352
cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
353
  std::string const& config) const
354
0
{
355
0
  std::vector<BT<cmSourceFile*>> files;
356
0
  KindedSources const& kinded = this->GetKindedSources(config);
357
0
  files.reserve(kinded.Sources.size());
358
0
  for (SourceAndKind const& si : kinded.Sources) {
359
0
    if (si.Source.Value->GetObjectLibrary().empty()) {
360
0
      files.push_back(si.Source);
361
0
    }
362
0
  }
363
0
  return files;
364
0
}
365
366
cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
367
  std::string const& config) const
368
2.36k
{
369
  // If we already processed one configuration and found no dependency
370
  // on configuration then always use the one result.
371
2.36k
  if (this->SourcesAreContextDependent == Tribool::False) {
372
834
    return this->KindedSourcesMap.begin()->second;
373
834
  }
374
375
  // Lookup any existing link implementation for this configuration.
376
1.52k
  std::string const key = cmSystemTools::UpperCase(config);
377
1.52k
  auto it = this->KindedSourcesMap.find(key);
378
1.52k
  if (it != this->KindedSourcesMap.end()) {
379
553
    if (!it->second.Initialized) {
380
4
      this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
381
4
        MessageType::FATAL_ERROR,
382
4
        cmStrCat("The SOURCES of \"", this->GetName(),
383
4
                 "\" use a generator expression that depends on the "
384
4
                 "SOURCES themselves."),
385
4
        this->GetBacktrace());
386
4
      static KindedSources empty;
387
4
      return empty;
388
4
    }
389
549
    return it->second;
390
553
  }
391
392
  // Add an entry to the map for this configuration.
393
974
  KindedSources& files = this->KindedSourcesMap[key];
394
974
  this->ComputeKindedSources(files, config);
395
974
  files.Initialized = true;
396
974
  return files;
397
1.52k
}
398
399
void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
400
                                             std::string const& config) const
401
974
{
402
  // Get the source file paths by string.
403
974
  std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
404
405
974
  cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
406
974
  std::vector<cmSourceFile*> badObjLib;
407
408
974
  cmValue const rustMainCrateRootProp =
409
974
    this->GetProperty("Rust_MAIN_CRATE_ROOT");
410
974
  cmSourceFile const* rustMainCrateRootSf = rustMainCrateRootProp
411
974
    ? this->Makefile->GetOrCreateSource(rustMainCrateRootProp)
412
974
    : nullptr;
413
414
974
  std::set<cmSourceFile*> emitted;
415
1.31k
  for (BT<std::string> const& s : srcs) {
416
    // Create each source at most once.
417
1.31k
    cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
418
1.31k
    if (!emitted.insert(sf).second) {
419
0
      continue;
420
0
    }
421
422
    // Compute the kind (classification) of this source file.
423
1.31k
    SourceKind kind;
424
1.31k
    std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
425
1.31k
    cmGeneratorFileSet const* fs = this->GetFileSetForSource(config, sf);
426
1.31k
    sf->GetOrDetermineLanguage();
427
1.31k
    std::string const language = this->GetSourceFileLanguage(sf, config);
428
1.31k
    if (sf->GetCustomCommand()) {
429
0
      kind = SourceKindCustomCommand;
430
1.31k
    } else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
431
0
               fs && (fs->GetType() == cm::FileSetMetadata::CXX_MODULES)) {
432
0
      kind = this->Target->CxxModuleNeedsInterfaceObjects()
433
0
        ? SourceKindObjectSource
434
0
        : SourceKindCxxModuleSource;
435
1.31k
    } else if (this->Target->GetType() == cm::TargetType::UTILITY ||
436
1.31k
               this->Target->GetType() == cm::TargetType::INTERFACE_LIBRARY
437
               // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
438
               // NOLINTNEXTLINE(bugprone-branch-clone)
439
1.31k
    ) {
440
0
      kind = SourceKindExtra;
441
1.31k
    } else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
442
0
      kind = SourceKindUnityBatched;
443
      // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
444
      // NOLINTNEXTLINE(bugprone-branch-clone)
445
1.31k
    } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
446
0
      kind = SourceKindHeader;
447
1.31k
    } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
448
0
      kind = SourceKindExternalObject;
449
1.31k
    } else if (!language.empty()) {
450
1.31k
      if (language == "Rust") {
451
        // NOLINTNEXTLINE(bugprone-branch-clone)
452
0
        if (this->Target->GetType() == cm::TargetType::OBJECT_LIBRARY) {
453
          // There is no main crate root for object libraries.
454
0
          kind = SourceKindObjectSource;
455
0
        } else if (!rustMainCrateRootSf) {
456
          // We do not have a main crate root source file, we use the first
457
          // Rust source file for it.
458
0
          rustMainCrateRootSf = sf;
459
0
          kind = SourceKindRustMainCrateRoot;
460
0
        } else if (rustMainCrateRootSf == sf) {
461
          // Current source file is the main crate root defined in the target
462
          // Rust_MAIN_CRATE_ROOT property.
463
0
          kind = SourceKindRustMainCrateRoot;
464
0
        } else {
465
          // Any other Rust source file is treated as a normal object, but will
466
          // be built into a .rlib. Maybe in the future this could be changed?
467
0
          kind = SourceKindObjectSource;
468
0
        }
469
1.31k
      } else {
470
1.31k
        kind = SourceKindObjectSource;
471
1.31k
      }
472
1.31k
    } else if (ext == "def") {
473
0
      kind = SourceKindModuleDefinition;
474
0
      if (this->GetType() == cm::TargetType::OBJECT_LIBRARY) {
475
0
        badObjLib.push_back(sf);
476
0
      }
477
0
    } else if (ext == "idl") {
478
0
      kind = SourceKindIDL;
479
0
      if (this->GetType() == cm::TargetType::OBJECT_LIBRARY) {
480
0
        badObjLib.push_back(sf);
481
0
      }
482
0
    } else if (ext == "resx") {
483
0
      kind = SourceKindResx;
484
0
    } else if (ext == "appxmanifest") {
485
0
      kind = SourceKindAppManifest;
486
0
    } else if (ext == "manifest") {
487
0
      if (sf->GetPropertyAsBool("VS_DEPLOYMENT_CONTENT")) {
488
0
        kind = SourceKindExtra;
489
0
      } else {
490
0
        kind = SourceKindManifest;
491
0
      }
492
0
    } else if (ext == "pfx") {
493
0
      kind = SourceKindCertificate;
494
0
    } else if (ext == "xaml") {
495
0
      kind = SourceKindXaml;
496
0
    } else if (header_regex.find(sf->ResolveFullPath())) {
497
0
      kind = SourceKindHeader;
498
0
    } else {
499
0
      kind = SourceKindExtra;
500
0
    }
501
502
    // Save this classified source file in the result vector.
503
1.31k
    files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind });
504
1.31k
  }
505
506
974
  if (!badObjLib.empty()) {
507
0
    std::string e =
508
0
      cmStrCat("OBJECT library \"", this->GetName(), "\" contains:\n");
509
0
    for (cmSourceFile* i : badObjLib) {
510
0
      e = cmStrCat(std::move(e), "  ", i->GetLocation().GetName(), '\n');
511
0
    }
512
0
    e =
513
0
      cmStrCat(std::move(e),
514
0
               "but may contain only sources that compile, header files, and "
515
0
               "other files that would not affect linking of a normal "
516
0
               "library.");
517
0
    this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
518
0
      MessageType::FATAL_ERROR, e, this->GetBacktrace());
519
0
  }
520
974
}
521
522
std::vector<cmGeneratorTarget::AllConfigSource> const&
523
cmGeneratorTarget::GetAllConfigSources() const
524
0
{
525
0
  if (this->AllConfigSources.empty()) {
526
0
    this->ComputeAllConfigSources();
527
0
  }
528
0
  return this->AllConfigSources;
529
0
}
530
531
void cmGeneratorTarget::ComputeAllConfigSources() const
532
0
{
533
0
  std::vector<std::string> configs =
534
0
    this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
535
536
0
  std::map<cmSourceFile const*, size_t> index;
537
538
0
  for (size_t ci = 0; ci < configs.size(); ++ci) {
539
0
    KindedSources const& sources = this->GetKindedSources(configs[ci]);
540
0
    for (SourceAndKind const& src : sources.Sources) {
541
0
      auto mi = index.find(src.Source.Value);
542
0
      if (mi == index.end()) {
543
0
        AllConfigSource acs;
544
0
        acs.Source = src.Source.Value;
545
0
        acs.Kind = src.Kind;
546
0
        this->AllConfigSources.push_back(std::move(acs));
547
0
        std::map<cmSourceFile const*, size_t>::value_type entry(
548
0
          src.Source.Value, this->AllConfigSources.size() - 1);
549
0
        mi = index.insert(entry).first;
550
0
      }
551
0
      this->AllConfigSources[mi->second].Configs.push_back(ci);
552
0
    }
553
0
  }
554
0
}
555
556
std::vector<cmGeneratorTarget::AllConfigSource>
557
cmGeneratorTarget::GetAllConfigSources(SourceKind kind) const
558
0
{
559
0
  std::vector<AllConfigSource> result;
560
0
  for (AllConfigSource const& source : this->GetAllConfigSources()) {
561
0
    if (source.Kind == kind) {
562
0
      result.push_back(source);
563
0
    }
564
0
  }
565
0
  return result;
566
0
}
567
568
void cmGeneratorTarget::ComputeAllConfigCompileLanguages() const
569
0
{
570
0
  std::set<std::string> languages;
571
0
  std::vector<std::string> const configs =
572
0
    this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
573
0
  std::vector<AllConfigSource> const& sources = this->GetAllConfigSources();
574
0
  for (AllConfigSource const& si : sources) {
575
0
    for (size_t const configIndex : si.Configs) {
576
0
      std::string const lang =
577
0
        this->GetSourceFileLanguage(si.Source, configs[configIndex]);
578
0
      if (!lang.empty()) {
579
0
        languages.emplace(lang);
580
0
      }
581
0
    }
582
0
  }
583
0
  this->AllConfigCompileLanguages = languages;
584
0
}
585
586
std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const
587
0
{
588
0
  if (this->AllConfigCompileLanguages.empty()) {
589
0
    this->ComputeAllConfigCompileLanguages();
590
0
  }
591
0
  return this->AllConfigCompileLanguages;
592
0
}