Coverage Report

Created: 2026-06-15 07:03

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