cmGeneratorTarget.cxx 208 KB
Newer Older
1
2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
3
4
#include "cmGeneratorTarget.h"

5
#include "cmsys/RegularExpression.hxx"
6
7
8
9
#include <algorithm>
#include <assert.h>
#include <errno.h>
#include <iterator>
10
#include <memory> // IWYU pragma: keep
11
12
13
14
15
#include <queue>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
16
#include <unordered_set>
wahikihiki's avatar
wahikihiki committed
17
#include <utility>
18

19
#include "cmAlgorithms.h"
20
#include "cmComputeLinkInformation.h"
21
#include "cmCustomCommand.h"
22
#include "cmCustomCommandGenerator.h"
23
#include "cmCustomCommandLines.h"
24
25
26
27
28
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
29
#include "cmMessageType.h"
30
#include "cmPropertyMap.h"
31
#include "cmSourceFile.h"
32
#include "cmSourceFileLocation.h"
33
#include "cmState.h"
34
#include "cmSystemTools.h"
35
#include "cmTarget.h"
36
#include "cmTargetLinkLibraryType.h"
37
#include "cmTargetPropertyComputer.h"
38
#include "cmake.h"
39

40
class cmMessenger;
41

42
43
44
45
46
47
48
49
50
template <>
const char* cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
  cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
  cmListFileBacktrace const& /* context */)
{
  return tgt->GetSourcesProperty();
}

template <>
51
52
53
const char*
cmTargetPropertyComputer::ComputeLocationForBuild<cmGeneratorTarget>(
  cmGeneratorTarget const* tgt)
54
55
56
57
58
59
60
61
62
63
64
{
  return tgt->GetLocation("");
}

template <>
const char* cmTargetPropertyComputer::ComputeLocation<cmGeneratorTarget>(
  cmGeneratorTarget const* tgt, const std::string& config)
{
  return tgt->GetLocation(config);
}

65
66
class cmGeneratorTarget::TargetPropertyEntry
{
67
  static cmLinkImplItem NoLinkImplItem;
68

69
public:
70
  TargetPropertyEntry(std::unique_ptr<cmCompiledGeneratorExpression> cge,
71
                      cmLinkImplItem const& item = NoLinkImplItem)
72
    : ge(std::move(cge))
73
74
75
    , LinkImplItem(item)
  {
  }
76
  const std::unique_ptr<cmCompiledGeneratorExpression> ge;
77
78
79
80
81
  cmLinkImplItem const& LinkImplItem;
};
cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;

void CreatePropertyGeneratorExpressions(
82
  cmStringRange entries, cmBacktraceRange backtraces,
83
84
  std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items,
  bool evaluateForBuildsystem = false)
85
86
87
{
  std::vector<cmListFileBacktrace>::const_iterator btIt = backtraces.begin();
  for (std::vector<std::string>::const_iterator it = entries.begin();
88
       it != entries.end(); ++it, ++btIt) {
89
    cmGeneratorExpression ge(*btIt);
90
    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*it);
91
    cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
92
93
    items.push_back(
      new cmGeneratorTarget::TargetPropertyEntry(std::move(cge)));
94
  }
95
96
}

97
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
98
  : Target(t)
99
  , FortranModuleDirectoryCreated(false)
100
101
  , SourceFileFlagsConstructed(false)
  , PolicyWarnedCMP0022(false)
102
  , PolicyReportedCMP0069(false)
103
104
105
106
  , DebugIncludesDone(false)
  , DebugCompileOptionsDone(false)
  , DebugCompileFeaturesDone(false)
  , DebugCompileDefinitionsDone(false)
107
  , DebugLinkOptionsDone(false)
108
  , DebugLinkDirectoriesDone(false)
109
110
111
  , DebugSourcesDone(false)
  , LinkImplementationLanguageIsContextDependent(true)
  , UtilityItemsDone(false)
112
113
{
  this->Makefile = this->Target->GetMakefile();
114
  this->LocalGenerator = lg;
115
  this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
116

117
118
  this->GlobalGenerator->ComputeTargetObjectDirectory(this);

119
120
121
  CreatePropertyGeneratorExpressions(t->GetIncludeDirectoriesEntries(),
                                     t->GetIncludeDirectoriesBacktraces(),
                                     this->IncludeDirectoriesEntries);
122

123
124
125
  CreatePropertyGeneratorExpressions(t->GetCompileOptionsEntries(),
                                     t->GetCompileOptionsBacktraces(),
                                     this->CompileOptionsEntries);
126

127
128
129
  CreatePropertyGeneratorExpressions(t->GetCompileFeaturesEntries(),
                                     t->GetCompileFeaturesBacktraces(),
                                     this->CompileFeaturesEntries);
130

131
132
133
  CreatePropertyGeneratorExpressions(t->GetCompileDefinitionsEntries(),
                                     t->GetCompileDefinitionsBacktraces(),
                                     this->CompileDefinitionsEntries);
134

135
136
137
138
  CreatePropertyGeneratorExpressions(t->GetLinkOptionsEntries(),
                                     t->GetLinkOptionsBacktraces(),
                                     this->LinkOptionsEntries);

139
140
141
142
  CreatePropertyGeneratorExpressions(t->GetLinkDirectoriesEntries(),
                                     t->GetLinkDirectoriesBacktraces(),
                                     this->LinkDirectoriesEntries);

143
144
145
  CreatePropertyGeneratorExpressions(t->GetSourceEntries(),
                                     t->GetSourceBacktraces(),
                                     this->SourceEntries, true);
146

147
  this->DLLPlatform =
148
    !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
149
150

  this->PolicyMap = t->PolicyMap;
151
152
}

153
154
cmGeneratorTarget::~cmGeneratorTarget()
{
155
  cmDeleteAll(this->IncludeDirectoriesEntries);
156
  cmDeleteAll(this->CompileOptionsEntries);
157
  cmDeleteAll(this->CompileFeaturesEntries);
158
  cmDeleteAll(this->CompileDefinitionsEntries);
159
  cmDeleteAll(this->LinkOptionsEntries);
160
  cmDeleteAll(this->LinkDirectoriesEntries);
161
  cmDeleteAll(this->SourceEntries);
162
163
164
  cmDeleteAll(this->LinkInformation);
}

165
166
167
const char* cmGeneratorTarget::GetSourcesProperty() const
{
  std::vector<std::string> values;
168
169
  for (TargetPropertyEntry* se : this->SourceEntries) {
    values.push_back(se->ge->GetInput());
170
171
172
  }
  static std::string value;
  value.clear();
173
  value = cmJoin(values, ";");
174
175
176
  return value.c_str();
}

177
178
179
180
181
cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const
{
  return this->GetLocalGenerator()->GetGlobalGenerator();
}

182
183
184
185
186
cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const
{
  return this->LocalGenerator;
}

187
cmStateEnums::TargetType cmGeneratorTarget::GetType() const
188
189
190
191
{
  return this->Target->GetType();
}

192
const std::string& cmGeneratorTarget::GetName() const
193
194
195
196
{
  return this->Target->GetName();
}

197
198
std::string cmGeneratorTarget::GetExportName() const
{
199
  const char* exportName = this->GetProperty("EXPORT_NAME");
200

201
202
  if (exportName && *exportName) {
    if (!cmGeneratorExpression::IsValidTargetName(exportName)) {
203
204
205
      std::ostringstream e;
      e << "EXPORT_NAME property \"" << exportName << "\" for \""
        << this->GetName() << "\": is not valid.";
206
      cmSystemTools::Error(e.str());
207
208
      return "";
    }
209
210
    return exportName;
  }
211
212
213
  return this->GetName();
}

214
const char* cmGeneratorTarget::GetProperty(const std::string& prop) const
215
{
216
217
218
  if (!cmTargetPropertyComputer::PassesWhitelist(
        this->GetType(), prop, this->Makefile->GetMessenger(),
        this->GetBacktrace())) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
219
    return nullptr;
220
221
222
223
224
225
  }
  if (const char* result = cmTargetPropertyComputer::GetProperty(
        this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) {
    return result;
  }
  if (cmSystemTools::GetFatalErrorOccured()) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
226
    return nullptr;
227
  }
228
229
230
  return this->Target->GetProperty(prop);
}

231
232
233
234
235
236
237
238
239
const char* cmGeneratorTarget::GetSafeProperty(const std::string& prop) const
{
  const char* ret = this->GetProperty(prop);
  if (!ret) {
    return "";
  }
  return ret;
}

240
241
const char* cmGeneratorTarget::GetOutputTargetType(
  cmStateEnums::ArtifactType artifact) const
242
{
243
  switch (this->GetType()) {
244
    case cmStateEnums::SHARED_LIBRARY:
245
      if (this->IsDLLPlatform()) {
246
247
248
249
250
251
252
        switch (artifact) {
          case cmStateEnums::RuntimeBinaryArtifact:
            // A DLL shared library is treated as a runtime target.
            return "RUNTIME";
          case cmStateEnums::ImportLibraryArtifact:
            // A DLL import library is treated as an archive target.
            return "ARCHIVE";
253
        }
254
      } else {
255
256
257
        // For non-DLL platforms shared libraries are treated as
        // library targets.
        return "LIBRARY";
258
      }
259
      break;
260
    case cmStateEnums::STATIC_LIBRARY:
261
262
      // Static libraries are always treated as archive targets.
      return "ARCHIVE";
263
    case cmStateEnums::MODULE_LIBRARY:
264
265
      switch (artifact) {
        case cmStateEnums::RuntimeBinaryArtifact:
266
          // Module libraries are always treated as library targets.
267
268
          return "LIBRARY";
        case cmStateEnums::ImportLibraryArtifact:
269
          // Module import libraries are treated as archive targets.
270
          return "ARCHIVE";
271
      }
272
      break;
273
274
275
    case cmStateEnums::OBJECT_LIBRARY:
      // Object libraries are always treated as object targets.
      return "OBJECT";
276
    case cmStateEnums::EXECUTABLE:
277
278
279
280
281
282
283
      switch (artifact) {
        case cmStateEnums::RuntimeBinaryArtifact:
          // Executables are always treated as runtime targets.
          return "RUNTIME";
        case cmStateEnums::ImportLibraryArtifact:
          // Executable import libraries are treated as archive targets.
          return "ARCHIVE";
284
      }
285
      break;
286
287
    default:
      break;
288
  }
289
290
291
  return "";
}

292
293
std::string cmGeneratorTarget::GetOutputName(
  const std::string& config, cmStateEnums::ArtifactType artifact) const
294
{
295
  // Lookup/compute/cache the output name for this configuration.
296
  OutputNameKey key(config, artifact);
297
298
  cmGeneratorTarget::OutputNameMapType::iterator i =
    this->OutputNameMap.find(key);
299
  if (i == this->OutputNameMap.end()) {
300
301
302
    // Add empty name in map to detect potential recursion.
    OutputNameMapType::value_type entry(key, "");
    i = this->OutputNameMap.insert(entry).first;
303

304
305
    // Compute output name.
    std::vector<std::string> props;
306
    std::string type = this->GetOutputTargetType(artifact);
307
    std::string configUpper = cmSystemTools::UpperCase(config);
308
    if (!type.empty() && !configUpper.empty()) {
309
310
      // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
      props.push_back(type + "_OUTPUT_NAME_" + configUpper);
311
312
    }
    if (!type.empty()) {
313
314
      // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME
      props.push_back(type + "_OUTPUT_NAME");
315
316
    }
    if (!configUpper.empty()) {
317
318
319
320
      // OUTPUT_NAME_<CONFIG>
      props.push_back("OUTPUT_NAME_" + configUpper);
      // <CONFIG>_OUTPUT_NAME
      props.push_back(configUpper + "_OUTPUT_NAME");
321
    }
322
    // OUTPUT_NAME
wahikihiki's avatar
wahikihiki committed
323
    props.emplace_back("OUTPUT_NAME");
324

325
    std::string outName;
326
327
    for (std::string const& p : props) {
      if (const char* outNameProp = this->GetProperty(p)) {
328
329
330
        outName = outNameProp;
        break;
      }
331
    }
332

333
    if (outName.empty()) {
334
      outName = this->GetName();
335
    }
336
337
338

    // Now evaluate genex and update the previously-prepared map entry.
    cmGeneratorExpression ge;
339
    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outName);
340
    i->second = cge->Evaluate(this->LocalGenerator, config);
341
  } else if (i->second.empty()) {
342
343
    // An empty map entry indicates we have been called recursively
    // from the above block.
344
    this->LocalGenerator->GetCMakeInstance()->IssueMessage(
345
      MessageType::FATAL_ERROR,
346
      "Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.",
347
      this->GetBacktrace());
348
  }
349
  return i->second;
350
351
}

352
353
354
355
356
357
358
void cmGeneratorTarget::ClearSourcesCache()
{
  this->KindedSourcesMap.clear();
  this->LinkImplementationLanguageIsContextDependent = true;
  this->Objects.clear();
}

359
void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before)
360
{
361
362
  cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
  cmGeneratorExpression ge(lfbt);
363
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src);
364
  cge->SetEvaluateForBuildsystem(true);
365
366
367
  this->SourceEntries.insert(before ? this->SourceEntries.begin()
                                    : this->SourceEntries.end(),
                             new TargetPropertyEntry(std::move(cge)));
368
  this->ClearSourcesCache();
369
370
}

371
void cmGeneratorTarget::AddSource(const std::string& src, bool before)
372
{
373
374
  this->Target->AddSource(src, before);
  this->AddSourceCommon(src, before);
375
376
}

377
378
379
void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
  this->Target->AddTracedSources(srcs);
380
  if (!srcs.empty()) {
381
    this->AddSourceCommon(cmJoin(srcs, ";"));
382
  }
383
384
}

385
386
387
388
389
390
void cmGeneratorTarget::AddIncludeDirectory(const std::string& src,
                                            bool before)
{
  this->Target->InsertInclude(src, this->Makefile->GetBacktrace(), before);
  cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
  cmGeneratorExpression ge(lfbt);
391
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src);
392
  cge->SetEvaluateForBuildsystem(true);
393
  this->IncludeDirectoriesEntries.insert(
394
395
396
    before ? this->IncludeDirectoriesEntries.begin()
           : this->IncludeDirectoriesEntries.end(),
    new TargetPropertyEntry(std::move(cge)));
397
398
}

399
400
std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(
  cmSourceFile const* sf) const
401
{
402
  SourceEntriesType::const_iterator i = this->SourceDepends.find(sf);
403
  if (i != this->SourceDepends.end()) {
404
    return &i->second.Depends;
405
  }
Daniel Pfeifer's avatar
Daniel Pfeifer committed
406
  return nullptr;
407
408
}

409
410
411
412
static void handleSystemIncludesDep(
  cmLocalGenerator* lg, cmGeneratorTarget const* depTgt,
  const std::string& config, cmGeneratorTarget const* headTarget,
  cmGeneratorExpressionDAGChecker* dagChecker,
413
414
  std::vector<std::string>& result, bool excludeImported,
  std::string const& language)
415
416
{
  if (const char* dirs =
417
        depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) {
418
    cmGeneratorExpression ge;
419
420
    cmSystemTools::ExpandListArgument(
      ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
421
                               dagChecker, language),
422
423
424
      result);
  }
  if (!depTgt->IsImported() || excludeImported) {
425
    return;
426
  }
427
428

  if (const char* dirs =
429
        depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
430
    cmGeneratorExpression ge;
431
432
    cmSystemTools::ExpandListArgument(
      ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
433
                               dagChecker, language),
434
435
      result);
  }
436
437
}

438
/* clang-format off */
439
#define IMPLEMENT_VISIT(KIND)                                                 \
440
  do {                                                                        \
441
    KindedSources const& kinded = this->GetKindedSources(config);             \
442
443
    for (SourceAndKind const& s : kinded.Sources) {                           \
      if (s.Kind == KIND) {                                                   \
444
        data.push_back(s.Source.Value);                                       \
445
      }                                                                       \
446
    }                                                                         \
447
  } while (false)
448
/* clang-format on */
449

450
451
void cmGeneratorTarget::GetObjectSources(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
452
{
453
  IMPLEMENT_VISIT(SourceKindObjectSource);
454

455
  if (!this->Objects.empty()) {
456
    return;
457
  }
458

459
460
  for (cmSourceFile const* it : data) {
    this->Objects[it];
461
  }
462
463

  this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
464
465
}

466
void cmGeneratorTarget::ComputeObjectMapping()
467
{
468
  if (!this->Objects.empty()) {
469
    return;
470
  }
471
472
473

  std::vector<std::string> configs;
  this->Makefile->GetConfigurations(configs);
474
  if (configs.empty()) {
475
    configs.emplace_back();
476
  }
477
  for (std::string const& c : configs) {
478
    std::vector<cmSourceFile const*> sourceFiles;
479
    this->GetObjectSources(sourceFiles, c);
480
  }
481
482
}

483
484
485
const char* cmGeneratorTarget::GetFeature(const std::string& feature,
                                          const std::string& config) const
{
486
  if (!config.empty()) {
487
488
489
    std::string featureConfig = feature;
    featureConfig += "_";
    featureConfig += cmSystemTools::UpperCase(config);
490
    if (const char* value = this->GetProperty(featureConfig)) {
491
492
      return value;
    }
493
494
  }
  if (const char* value = this->GetProperty(feature)) {
495
    return value;
496
  }
497
  return this->LocalGenerator->GetFeature(feature, config);
498
499
}

500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
const char* cmGeneratorTarget::GetLinkPIEProperty(
  const std::string& config) const
{
  static std::string PICValue;

  PICValue = this->GetLinkInterfaceDependentStringAsBoolProperty(
    "POSITION_INDEPENDENT_CODE", config);

  if (PICValue == "(unset)") {
    // POSITION_INDEPENDENT_CODE is not set
    return nullptr;
  }

  switch (this->GetPolicyStatusCMP0083()) {
    case cmPolicies::WARN: {
      std::ostringstream e;
      e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0083);
517
      this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
518
519
520
521
522
523
524
525
526
527
528
529
      CM_FALLTHROUGH;
    }
    case cmPolicies::OLD:
      return nullptr;
    default:
      // nothing to do
      break;
  }

  return PICValue.c_str();
}

530
531
bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
                                     std::string const& config) const
532
{
533
  const char* feature = "INTERPROCEDURAL_OPTIMIZATION";
534
535
536
537
538
539
540
  const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config));

  if (!result) {
    // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies
    return false;
  }

541
542
543
544
545
  if (lang != "C" && lang != "CXX" && lang != "Fortran") {
    // We do not define IPO behavior for other languages.
    return false;
  }

546
547
548
  cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069();

  if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) {
549
    if (this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_LEGACY_BEHAVIOR")) {
550
551
552
553
554
555
      return true;
    }
    if (this->PolicyReportedCMP0069) {
      // problem is already reported, no need to issue a message
      return false;
    }
556
557
558
    const bool in_try_compile =
      this->LocalGenerator->GetCMakeInstance()->GetIsInTryCompile();
    if (cmp0069 == cmPolicies::WARN && !in_try_compile) {
559
560
561
562
563
      std::ostringstream w;
      w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0069) << "\n";
      w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target "
        << "'" << this->GetName() << "'.";
      this->LocalGenerator->GetCMakeInstance()->IssueMessage(
564
        MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace());
565
566
567
568
569
570
571

      this->PolicyReportedCMP0069 = true;
    }
    return false;
  }

  // Note: check consistency with messages from CheckIPOSupported
Daniel Pfeifer's avatar
Daniel Pfeifer committed
572
  const char* message = nullptr;
573
  if (!this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_SUPPORTED_BY_CMAKE")) {
574
    message = "CMake doesn't support IPO for current compiler";
575
576
  } else if (!this->Makefile->IsOn("_CMAKE_" + lang +
                                   "_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) {
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
    message = "Compiler doesn't support IPO";
  } else if (!this->GlobalGenerator->IsIPOSupported()) {
    message = "CMake doesn't support IPO for current generator";
  }

  if (!message) {
    // No error/warning messages
    return true;
  }

  if (this->PolicyReportedCMP0069) {
    // problem is already reported, no need to issue a message
    return false;
  }

  this->PolicyReportedCMP0069 = true;

  this->LocalGenerator->GetCMakeInstance()->IssueMessage(
595
    MessageType::FATAL_ERROR, message, this->GetBacktrace());
596
  return false;
597
598
}

599
const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
600
{
601
602
  this->ComputeObjectMapping();
  return this->Objects[file];
603
604
}

605
606
607
608
609
610
611
612
613
const char* cmGeneratorTarget::GetCustomObjectExtension() const
{
  static std::string extension;
  const bool has_ptx_extension =
    this->GetPropertyAsBool("CUDA_PTX_COMPILATION");
  if (has_ptx_extension) {
    extension = ".ptx";
    return extension.c_str();
  }
Daniel Pfeifer's avatar
Daniel Pfeifer committed
614
  return nullptr;
615
616
}

617
void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
618
619
620
621
622
623
{
  this->ExplicitObjectName.insert(sf);
}

bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
{
624
  const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
625
626
  std::set<cmSourceFile const*>::const_iterator it =
    this->ExplicitObjectName.find(file);
627
628
629
  return it != this->ExplicitObjectName.end();
}

630
631
632
void cmGeneratorTarget::GetModuleDefinitionSources(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
{
633
  IMPLEMENT_VISIT(SourceKindModuleDefinition);
634
635
}

636
637
void cmGeneratorTarget::GetHeaderSources(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
638
{
639
  IMPLEMENT_VISIT(SourceKindHeader);
640
641
}

642
643
void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile const*>& data,
                                        const std::string& config) const
644
{
645
  IMPLEMENT_VISIT(SourceKindExtra);
646
647
}

648
649
void cmGeneratorTarget::GetCustomCommands(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
650
{
651
  IMPLEMENT_VISIT(SourceKindCustomCommand);
652
653
}

654
655
void cmGeneratorTarget::GetExternalObjects(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
656
{
657
  IMPLEMENT_VISIT(SourceKindExternalObject);
658
659
}

660
void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& headers,
661
                                               const std::string& config) const
662
{
663
664
  KindedSources const& kinded = this->GetKindedSources(config);
  headers = kinded.ExpectedResxHeaders;
665
666
}

667
void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& data,
668
                                       const std::string& config) const
669
{
670
  IMPLEMENT_VISIT(SourceKindResx);
671
672
}

673
674
void cmGeneratorTarget::GetAppManifest(std::vector<cmSourceFile const*>& data,
                                       const std::string& config) const
675
{
676
  IMPLEMENT_VISIT(SourceKindAppManifest);
677
678
}

679
680
void cmGeneratorTarget::GetManifests(std::vector<cmSourceFile const*>& data,
                                     const std::string& config) const
681
{
682
  IMPLEMENT_VISIT(SourceKindManifest);
683
684
}

685
686
void cmGeneratorTarget::GetCertificates(std::vector<cmSourceFile const*>& data,
                                        const std::string& config) const
687
{
688
  IMPLEMENT_VISIT(SourceKindCertificate);
689
690
}

691
692
void cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers,
                                               const std::string& config) const
693
{
694
695
  KindedSources const& kinded = this->GetKindedSources(config);
  headers = kinded.ExpectedXamlHeaders;
696
697
}

698
699
void cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
                                               const std::string& config) const
700
{
701
702
  KindedSources const& kinded = this->GetKindedSources(config);
  srcs = kinded.ExpectedXamlSources;
703
704
705
706
}

std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
{
707
  if (!this->UtilityItemsDone) {
708
    this->UtilityItemsDone = true;
709
710
    std::set<BT<std::string>> const& utilities = this->GetUtilities();
    for (BT<std::string> const& i : utilities) {
711
      if (cmGeneratorTarget* gt =
712
713
            this->LocalGenerator->FindGeneratorTargetToUse(i.Value)) {
        this->UtilityItems.insert(cmLinkItem(gt, i.Backtrace));
714
      } else {
715
        this->UtilityItems.insert(cmLinkItem(i.Value, i.Backtrace));
716
      }
717
    }
718
  }
719
  return this->UtilityItems;
720
721
}

722
void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& data,
723
                                       const std::string& config) const
724
{
725
  IMPLEMENT_VISIT(SourceKindXaml);
726
727
}

728
729
730
const char* cmGeneratorTarget::GetLocation(const std::string& config) const
{
  static std::string location;
731
  if (this->IsImported()) {
732
733
    location = this->Target->ImportedGetFullPath(
      config, cmStateEnums::RuntimeBinaryArtifact);
734
  } else {
735
    location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
736
  }
737
738
739
  return location.c_str();
}

740
741
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreBuildCommands()
  const
742
743
744
745
{
  return this->Target->GetPreBuildCommands();
}

746
747
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreLinkCommands()
  const
748
749
750
751
{
  return this->Target->GetPreLinkCommands();
}

752
753
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPostBuildCommands()
  const
754
755
756
757
{
  return this->Target->GetPostBuildCommands();
}

758
759
760
761
762
bool cmGeneratorTarget::IsImported() const
{
  return this->Target->IsImported();
}

763
764
765
766
767
bool cmGeneratorTarget::IsImportedGloballyVisible() const
{
  return this->Target->IsImportedGloballyVisible();
}

768
769
770
const char* cmGeneratorTarget::GetLocationForBuild() const
{
  static std::string location;
771
  if (this->IsImported()) {
772
773
    location = this->Target->ImportedGetFullPath(
      "", cmStateEnums::RuntimeBinaryArtifact);
774
    return location.c_str();
775
  }
776
777

  // Now handle the deprecated build-time configuration location.
778
  location = this->GetDirectory();
779
  const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
780
  if (cfgid && strcmp(cfgid, ".") != 0) {
781
782
    location += "/";
    location += cfgid;
783
  }
784

785
  if (this->IsAppBundleOnApple()) {
786
    std::string macdir = this->BuildBundleDirectory("", "", FullLevel);
787
    if (!macdir.empty()) {
788
789
790
      location += "/";
      location += macdir;
    }
791
  }
792
  location += "/";
793
  location += this->GetFullName("", cmStateEnums::RuntimeBinaryArtifact);
794
795
796
  return location.c_str();
}

797
bool cmGeneratorTarget::IsSystemIncludeDirectory(
798
799
  const std::string& dir, const std::string& config,
  const std::string& language) const
800
{
801
  assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
802
  std::string config_upper;
803
  if (!config.empty()) {
804
    config_upper = cmSystemTools::UpperCase(config);
805
  }
806

807
  typedef std::map<std::string, std::vector<std::string>> IncludeCacheType;
808
  IncludeCacheType::const_iterator iter =
809
    this->SystemIncludesCache.find(config_upper);
810

811
  if (iter == this->SystemIncludesCache.end()) {
812
    cmGeneratorExpressionDAGChecker dagChecker(
813
      this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
814

815
    bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
816

817
    std::vector<std::string> result;
818
    for (std::string const& it : this->Target->GetSystemIncludeDirectories()) {
819
      cmGeneratorExpression ge;
820
      cmSystemTools::ExpandListArgument(
821
        ge.Parse(it)->Evaluate(this->LocalGenerator, config, false, this,
822
                               &dagChecker, language),
823
824
        result);
    }
825

826
    std::vector<cmGeneratorTarget const*> const& deps =
827
      this->GetLinkImplementationClosure(config);
828
829
    for (cmGeneratorTarget const* dep : deps) {
      handleSystemIncludesDep(this->LocalGenerator, dep, config, this,
830
                              &dagChecker, result, excludeImported, language);
831
    }
832

833
834
835
836
    std::for_each(result.begin(), result.end(),
                  cmSystemTools::ConvertToUnixSlashes);
    std::sort(result.begin(), result.end());
    result.erase(std::unique(result.begin(), result.end()), result.end());
837

838
839
    IncludeCacheType::value_type entry