Coverage Report

Created: 2026-04-29 07:01

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 <cstddef>
10
#include <functional>
11
#include <map>
12
#include <memory>
13
#include <set>
14
#include <sstream>
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 "cmDiagnostics.h"
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->IssueDiagnostic(cmDiagnostics::CMD_AUTHOR, 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
        if (auto const* fileSet =
164
0
              tgt->GetGeneratorFileSets()->GetFileSetForSource(config, src)) {
165
0
          switch (tgt->GetPolicyStatusCMP0211()) {
166
0
            case cmPolicies::WARN:
167
0
              tgt->GetLocalGenerator()->IssueDiagnostic(
168
0
                cmDiagnostics::CMD_AUTHOR,
169
0
                cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0211),
170
0
                         "\nIn target \"", tgt->GetName(), "\" the file\n  ",
171
0
                         src, "\nalready belongs to file set \"",
172
0
                         fileSet->GetName(), "\"."));
173
0
              CM_FALLTHROUGH;
174
0
            case cmPolicies::OLD:
175
0
              break;
176
0
            default:
177
0
              tgt->GetLocalGenerator()->IssueMessage(
178
0
                MessageType::FATAL_ERROR,
179
0
                cmStrCat("In target \"", tgt->GetName(), "\" the file\n  ",
180
0
                         src, "\nalready belongs to file set \"",
181
0
                         fileSet->GetName(), "\"."));
182
0
          }
183
0
        }
184
0
      }
185
0
    }
186
0
    if (!usedSources.empty()) {
187
0
      tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
188
0
        MessageType::LOG,
189
0
        cmStrCat("Used sources for target ", tgt->GetName(), ":\n",
190
0
                 usedSources),
191
0
        entry.Backtrace);
192
0
    }
193
0
  }
194
0
  return contextDependent;
195
0
}
196
}
197
198
std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
199
  std::string const& config) const
200
0
{
201
0
  std::vector<BT<std::string>> files;
202
203
0
  cmList debugProperties{ this->Makefile->GetDefinition(
204
0
    "CMAKE_DEBUG_TARGET_PROPERTIES") };
205
0
  bool debugSources =
206
0
    !this->DebugSourcesDone && cm::contains(debugProperties, "SOURCES");
207
208
0
  this->DebugSourcesDone = true;
209
210
0
  cm::GenEx::Context context(this->LocalGenerator, config,
211
0
                             /*language=*/std::string());
212
213
0
  cmGeneratorExpressionDAGChecker dagChecker{
214
0
    this, "SOURCES", nullptr, nullptr, context,
215
0
  };
216
217
0
  cm::EvaluatedTargetPropertyEntries entries =
218
0
    cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
219
0
                                      this->SourceEntries);
220
221
0
  std::unordered_set<std::string> uniqueSrcs;
222
0
  bool contextDependentDirectSources =
223
0
    processSources(this, config, entries, files, uniqueSrcs, debugSources);
224
225
  // Collect INTERFACE_SOURCES of all direct link-dependencies.
226
0
  cm::EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
227
0
  cm::AddInterfaceEntries(this, "INTERFACE_SOURCES", context, &dagChecker,
228
0
                          linkInterfaceSourcesEntries,
229
0
                          cm::IncludeRuntimeInterface::No, UseTo::Compile);
230
0
  bool contextDependentInterfaceSources =
231
0
    processSources(this, config, linkInterfaceSourcesEntries, files,
232
0
                   uniqueSrcs, debugSources);
233
234
  // Collect TARGET_OBJECTS of direct object link-dependencies.
235
0
  bool contextDependentObjects = false;
236
0
  if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
237
0
    cm::EvaluatedTargetPropertyEntries linkObjectsEntries;
238
0
    AddObjectEntries(this, context, &dagChecker, linkObjectsEntries);
239
0
    contextDependentObjects = processSources(this, config, linkObjectsEntries,
240
0
                                             files, uniqueSrcs, debugSources);
241
    // Note that for imported targets or multi-config generators supporting
242
    // cross-config builds the paths to the object files must be per-config,
243
    // so contextDependentObjects will be true here even if object libraries
244
    // are specified without per-config generator expressions.
245
0
  }
246
247
  // Collect this target's file sets.
248
0
  cmGeneratorExpressionDAGChecker fsDagChecker{
249
0
    this, "SOURCES", nullptr, nullptr, context,
250
0
  };
251
252
0
  cm::EvaluatedTargetPropertyEntries fileSetEntries;
253
0
  AddFileSetEntries(this, this->FileSets.get(), context, &fsDagChecker,
254
0
                    fileSetEntries);
255
0
  auto processFileSetEntry = [this, &config](cmSourceFile* sf) {
256
0
    auto const* fileSet = this->GetFileSetForSource(config, sf);
257
0
    if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
258
0
      sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
259
0
    }
260
0
#if !defined(CMAKE_BOOTSTRAP)
261
0
    cmMakefile* mf = this->Target->GetMakefile();
262
0
    auto const& path = sf->GetFullPath();
263
0
    bool found = false;
264
0
    for (auto const& sg : mf->GetSourceGroups()) {
265
0
      if (sg->MatchChildrenFiles(path)) {
266
0
        found = true;
267
0
        break;
268
0
      }
269
0
    }
270
0
    if (!found) {
271
0
      if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
272
0
        mf->GetOrCreateSourceGroup("Header Files")->AddGroupFile(path);
273
0
      }
274
0
    }
275
0
#endif
276
0
  };
277
0
  bool contextDependentFileSets =
278
0
    processSources(this, config, fileSetEntries, files, uniqueSrcs,
279
0
                   debugSources, processFileSetEntry);
280
281
  // Collect file sets INTERFACE_SOURCES of all direct link-dependencies.
282
0
  cm::EvaluatedTargetPropertyEntries linkInterfaceFileSetsEntries;
283
0
  cm::AddInterfaceFileSetsEntries(this, cm::FileSetMetadata::SOURCES,
284
0
                                  "INTERFACE_SOURCES", context, &fsDagChecker,
285
0
                                  linkInterfaceFileSetsEntries);
286
0
  bool contextDependentInterfaceFileSets =
287
0
    processSources(this, config, linkInterfaceFileSetsEntries, files,
288
0
                   uniqueSrcs, debugSources);
289
290
  // Determine if sources are context-dependent or not.
291
0
  if (!contextDependentDirectSources && !contextDependentInterfaceSources &&
292
0
      !contextDependentObjects && !contextDependentFileSets &&
293
0
      !contextDependentInterfaceFileSets) {
294
0
    this->SourcesAreContextDependent = Tribool::False;
295
0
  } else {
296
0
    this->SourcesAreContextDependent = Tribool::True;
297
0
  }
298
299
0
  return files;
300
0
}
301
302
void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
303
                                       std::string const& config) const
304
0
{
305
0
  std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config);
306
0
  files.reserve(tmp.size());
307
0
  for (BT<cmSourceFile*>& v : tmp) {
308
0
    files.push_back(v.Value);
309
0
  }
310
0
}
311
312
std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles(
313
  std::string const& config) const
314
0
{
315
0
  std::vector<BT<cmSourceFile*>> files;
316
0
  KindedSources const& kinded = this->GetKindedSources(config);
317
0
  files.reserve(kinded.Sources.size());
318
0
  for (SourceAndKind const& si : kinded.Sources) {
319
0
    files.push_back(si.Source);
320
0
  }
321
0
  return files;
322
0
}
323
324
void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
325
  std::vector<cmSourceFile*>& files, std::string const& config) const
326
0
{
327
0
  std::vector<BT<cmSourceFile*>> tmp =
328
0
    this->GetSourceFilesWithoutObjectLibraries(config);
329
0
  files.reserve(tmp.size());
330
0
  for (BT<cmSourceFile*>& v : tmp) {
331
0
    files.push_back(v.Value);
332
0
  }
333
0
}
334
335
std::vector<BT<cmSourceFile*>>
336
cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
337
  std::string const& config) const
338
0
{
339
0
  std::vector<BT<cmSourceFile*>> files;
340
0
  KindedSources const& kinded = this->GetKindedSources(config);
341
0
  files.reserve(kinded.Sources.size());
342
0
  for (SourceAndKind const& si : kinded.Sources) {
343
0
    if (si.Source.Value->GetObjectLibrary().empty()) {
344
0
      files.push_back(si.Source);
345
0
    }
346
0
  }
347
0
  return files;
348
0
}
349
350
cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
351
  std::string const& config) const
352
0
{
353
  // If we already processed one configuration and found no dependency
354
  // on configuration then always use the one result.
355
0
  if (this->SourcesAreContextDependent == Tribool::False) {
356
0
    return this->KindedSourcesMap.begin()->second;
357
0
  }
358
359
  // Lookup any existing link implementation for this configuration.
360
0
  std::string const key = cmSystemTools::UpperCase(config);
361
0
  auto it = this->KindedSourcesMap.find(key);
362
0
  if (it != this->KindedSourcesMap.end()) {
363
0
    if (!it->second.Initialized) {
364
0
      std::ostringstream e;
365
0
      e << "The SOURCES of \"" << this->GetName()
366
0
        << "\" use a generator expression that depends on the "
367
0
           "SOURCES themselves.";
368
0
      this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
369
0
        MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
370
0
      static KindedSources empty;
371
0
      return empty;
372
0
    }
373
0
    return it->second;
374
0
  }
375
376
  // Add an entry to the map for this configuration.
377
0
  KindedSources& files = this->KindedSourcesMap[key];
378
0
  this->ComputeKindedSources(files, config);
379
0
  files.Initialized = true;
380
0
  return files;
381
0
}
382
383
void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
384
                                             std::string const& config) const
385
0
{
386
  // Get the source file paths by string.
387
0
  std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
388
389
0
  cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
390
0
  std::vector<cmSourceFile*> badObjLib;
391
392
0
  cmValue const rustMainCrateRootProp =
393
0
    this->GetProperty("Rust_MAIN_CRATE_ROOT");
394
0
  cmSourceFile const* rustMainCrateRootSf = rustMainCrateRootProp
395
0
    ? this->Makefile->GetOrCreateSource(rustMainCrateRootProp)
396
0
    : nullptr;
397
398
0
  std::set<cmSourceFile*> emitted;
399
0
  for (BT<std::string> const& s : srcs) {
400
    // Create each source at most once.
401
0
    cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
402
0
    if (!emitted.insert(sf).second) {
403
0
      continue;
404
0
    }
405
406
    // Compute the kind (classification) of this source file.
407
0
    SourceKind kind;
408
0
    std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
409
0
    cmGeneratorFileSet const* fs = this->GetFileSetForSource(config, sf);
410
0
    if (sf->GetCustomCommand()) {
411
0
      kind = SourceKindCustomCommand;
412
0
    } else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
413
0
               fs && (fs->GetType() == cm::FileSetMetadata::CXX_MODULES)) {
414
0
      kind = SourceKindCxxModuleSource;
415
0
    } else if (this->Target->GetType() == cmStateEnums::UTILITY ||
416
0
               this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY
417
               // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
418
               // NOLINTNEXTLINE(bugprone-branch-clone)
419
0
    ) {
420
0
      kind = SourceKindExtra;
421
0
    } else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
422
0
      kind = SourceKindUnityBatched;
423
      // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
424
      // NOLINTNEXTLINE(bugprone-branch-clone)
425
0
    } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
426
0
      kind = SourceKindHeader;
427
0
    } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
428
0
      kind = SourceKindExternalObject;
429
0
    } else if (!sf->GetOrDetermineLanguage().empty()) {
430
0
      if (sf->GetOrDetermineLanguage() == "Rust") {
431
        // NOLINTNEXTLINE(bugprone-branch-clone)
432
0
        if (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
433
          // There is no main crate root for object libraries.
434
0
          kind = SourceKindObjectSource;
435
0
        } else if (!rustMainCrateRootSf) {
436
          // We do not have a main crate root source file, we use the first
437
          // Rust source file for it.
438
0
          rustMainCrateRootSf = sf;
439
0
          kind = SourceKindRustMainCrateRoot;
440
0
        } else if (rustMainCrateRootSf == sf) {
441
          // Current source file is the main crate root defined in the target
442
          // Rust_MAIN_CRATE_ROOT property.
443
0
          kind = SourceKindRustMainCrateRoot;
444
0
        } else {
445
          // Any other Rust source file is treated as a normal object, but will
446
          // be built into a .rlib. Maybe in the future this could be changed?
447
0
          kind = SourceKindObjectSource;
448
0
        }
449
0
      } else {
450
0
        kind = SourceKindObjectSource;
451
0
      }
452
0
    } else if (ext == "def") {
453
0
      kind = SourceKindModuleDefinition;
454
0
      if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
455
0
        badObjLib.push_back(sf);
456
0
      }
457
0
    } else if (ext == "idl") {
458
0
      kind = SourceKindIDL;
459
0
      if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
460
0
        badObjLib.push_back(sf);
461
0
      }
462
0
    } else if (ext == "resx") {
463
0
      kind = SourceKindResx;
464
0
    } else if (ext == "appxmanifest") {
465
0
      kind = SourceKindAppManifest;
466
0
    } else if (ext == "manifest") {
467
0
      if (sf->GetPropertyAsBool("VS_DEPLOYMENT_CONTENT")) {
468
0
        kind = SourceKindExtra;
469
0
      } else {
470
0
        kind = SourceKindManifest;
471
0
      }
472
0
    } else if (ext == "pfx") {
473
0
      kind = SourceKindCertificate;
474
0
    } else if (ext == "xaml") {
475
0
      kind = SourceKindXaml;
476
0
    } else if (header_regex.find(sf->ResolveFullPath())) {
477
0
      kind = SourceKindHeader;
478
0
    } else {
479
0
      kind = SourceKindExtra;
480
0
    }
481
482
    // Save this classified source file in the result vector.
483
0
    files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind });
484
0
  }
485
486
0
  if (!badObjLib.empty()) {
487
0
    std::ostringstream e;
488
0
    e << "OBJECT library \"" << this->GetName() << "\" contains:\n";
489
0
    for (cmSourceFile* i : badObjLib) {
490
0
      e << "  " << i->GetLocation().GetName() << "\n";
491
0
    }
492
0
    e << "but may contain only sources that compile, header files, and "
493
0
         "other files that would not affect linking of a normal library.";
494
0
    this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
495
0
      MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
496
0
  }
497
0
}
498
499
std::vector<cmGeneratorTarget::AllConfigSource> const&
500
cmGeneratorTarget::GetAllConfigSources() const
501
0
{
502
0
  if (this->AllConfigSources.empty()) {
503
0
    this->ComputeAllConfigSources();
504
0
  }
505
0
  return this->AllConfigSources;
506
0
}
507
508
void cmGeneratorTarget::ComputeAllConfigSources() const
509
0
{
510
0
  std::vector<std::string> configs =
511
0
    this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
512
513
0
  std::map<cmSourceFile const*, size_t> index;
514
515
0
  for (size_t ci = 0; ci < configs.size(); ++ci) {
516
0
    KindedSources const& sources = this->GetKindedSources(configs[ci]);
517
0
    for (SourceAndKind const& src : sources.Sources) {
518
0
      auto mi = index.find(src.Source.Value);
519
0
      if (mi == index.end()) {
520
0
        AllConfigSource acs;
521
0
        acs.Source = src.Source.Value;
522
0
        acs.Kind = src.Kind;
523
0
        this->AllConfigSources.push_back(std::move(acs));
524
0
        std::map<cmSourceFile const*, size_t>::value_type entry(
525
0
          src.Source.Value, this->AllConfigSources.size() - 1);
526
0
        mi = index.insert(entry).first;
527
0
      }
528
0
      this->AllConfigSources[mi->second].Configs.push_back(ci);
529
0
    }
530
0
  }
531
0
}
532
533
std::vector<cmGeneratorTarget::AllConfigSource>
534
cmGeneratorTarget::GetAllConfigSources(SourceKind kind) const
535
0
{
536
0
  std::vector<AllConfigSource> result;
537
0
  for (AllConfigSource const& source : this->GetAllConfigSources()) {
538
0
    if (source.Kind == kind) {
539
0
      result.push_back(source);
540
0
    }
541
0
  }
542
0
  return result;
543
0
}
544
545
void cmGeneratorTarget::ComputeAllConfigCompileLanguages() const
546
0
{
547
0
  std::set<std::string> languages;
548
0
  std::vector<AllConfigSource> const& sources = this->GetAllConfigSources();
549
0
  for (AllConfigSource const& si : sources) {
550
0
    std::string const& lang = si.Source->GetOrDetermineLanguage();
551
0
    if (!lang.empty()) {
552
0
      languages.emplace(lang);
553
0
    }
554
0
  }
555
0
  this->AllConfigCompileLanguages = languages;
556
0
}
557
558
std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const
559
0
{
560
0
  if (this->AllConfigCompileLanguages.empty()) {
561
0
    this->ComputeAllConfigCompileLanguages();
562
0
  }
563
0
  return this->AllConfigCompileLanguages;
564
0
}