cmGeneratorTarget.cxx 193 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>
17

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

38
class cmMessenger;
39

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

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

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

63
64
class cmGeneratorTarget::TargetPropertyEntry
{
65
  static cmLinkImplItem NoLinkImplItem;
66

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

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

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

114
115
  this->GlobalGenerator->ComputeTargetObjectDirectory(this);

116
117
118
  CreatePropertyGeneratorExpressions(t->GetIncludeDirectoriesEntries(),
                                     t->GetIncludeDirectoriesBacktraces(),
                                     this->IncludeDirectoriesEntries);
119

120
121
122
  CreatePropertyGeneratorExpressions(t->GetCompileOptionsEntries(),
                                     t->GetCompileOptionsBacktraces(),
                                     this->CompileOptionsEntries);
123

124
125
126
  CreatePropertyGeneratorExpressions(t->GetCompileFeaturesEntries(),
                                     t->GetCompileFeaturesBacktraces(),
                                     this->CompileFeaturesEntries);
127

128
129
130
  CreatePropertyGeneratorExpressions(t->GetCompileDefinitionsEntries(),
                                     t->GetCompileDefinitionsBacktraces(),
                                     this->CompileDefinitionsEntries);
131

132
133
134
135
  CreatePropertyGeneratorExpressions(t->GetLinkOptionsEntries(),
                                     t->GetLinkOptionsBacktraces(),
                                     this->LinkOptionsEntries);

136
137
138
  CreatePropertyGeneratorExpressions(t->GetSourceEntries(),
                                     t->GetSourceBacktraces(),
                                     this->SourceEntries, true);
139

140
  this->DLLPlatform =
141
    !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
142
143

  this->PolicyMap = t->PolicyMap;
144
145
}

146
147
cmGeneratorTarget::~cmGeneratorTarget()
{
148
  cmDeleteAll(this->IncludeDirectoriesEntries);
149
  cmDeleteAll(this->CompileOptionsEntries);
150
  cmDeleteAll(this->CompileFeaturesEntries);
151
  cmDeleteAll(this->CompileDefinitionsEntries);
152
  cmDeleteAll(this->LinkOptionsEntries);
153
  cmDeleteAll(this->SourceEntries);
154
155
156
  cmDeleteAll(this->LinkInformation);
}

157
158
159
const char* cmGeneratorTarget::GetSourcesProperty() const
{
  std::vector<std::string> values;
160
161
  for (TargetPropertyEntry* se : this->SourceEntries) {
    values.push_back(se->ge->GetInput());
162
163
164
  }
  static std::string value;
  value.clear();
165
  value = cmJoin(values, ";");
166
167
168
  return value.c_str();
}

169
170
171
172
173
cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const
{
  return this->GetLocalGenerator()->GetGlobalGenerator();
}

174
175
176
177
178
cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const
{
  return this->LocalGenerator;
}

179
cmStateEnums::TargetType cmGeneratorTarget::GetType() const
180
181
182
183
{
  return this->Target->GetType();
}

184
const std::string& cmGeneratorTarget::GetName() const
185
186
187
188
{
  return this->Target->GetName();
}

189
190
std::string cmGeneratorTarget::GetExportName() const
{
191
  const char* exportName = this->GetProperty("EXPORT_NAME");
192

193
194
  if (exportName && *exportName) {
    if (!cmGeneratorExpression::IsValidTargetName(exportName)) {
195
196
197
198
199
200
      std::ostringstream e;
      e << "EXPORT_NAME property \"" << exportName << "\" for \""
        << this->GetName() << "\": is not valid.";
      cmSystemTools::Error(e.str().c_str());
      return "";
    }
201
202
    return exportName;
  }
203
204
205
  return this->GetName();
}

206
const char* cmGeneratorTarget::GetProperty(const std::string& prop) const
207
{
208
209
210
  if (!cmTargetPropertyComputer::PassesWhitelist(
        this->GetType(), prop, this->Makefile->GetMessenger(),
        this->GetBacktrace())) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
211
    return nullptr;
212
213
214
215
216
217
  }
  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
218
    return nullptr;
219
  }
220
221
222
  return this->Target->GetProperty(prop);
}

223
224
225
226
227
228
229
230
231
const char* cmGeneratorTarget::GetSafeProperty(const std::string& prop) const
{
  const char* ret = this->GetProperty(prop);
  if (!ret) {
    return "";
  }
  return ret;
}

232
233
const char* cmGeneratorTarget::GetOutputTargetType(
  cmStateEnums::ArtifactType artifact) const
234
{
235
  switch (this->GetType()) {
236
    case cmStateEnums::SHARED_LIBRARY:
237
      if (this->IsDLLPlatform()) {
238
239
240
241
242
243
244
        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";
245
        }
246
      } else {
247
248
249
        // For non-DLL platforms shared libraries are treated as
        // library targets.
        return "LIBRARY";
250
      }
251
      break;
252
    case cmStateEnums::STATIC_LIBRARY:
253
254
      // Static libraries are always treated as archive targets.
      return "ARCHIVE";
255
    case cmStateEnums::MODULE_LIBRARY:
256
257
      switch (artifact) {
        case cmStateEnums::RuntimeBinaryArtifact:
258
          // Module libraries are always treated as library targets.
259
260
          return "LIBRARY";
        case cmStateEnums::ImportLibraryArtifact:
261
          // Module import libraries are treated as archive targets.
262
          return "ARCHIVE";
263
      }
264
      break;
265
266
267
    case cmStateEnums::OBJECT_LIBRARY:
      // Object libraries are always treated as object targets.
      return "OBJECT";
268
    case cmStateEnums::EXECUTABLE:
269
270
271
272
273
274
275
      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";
276
      }
277
      break;
278
279
    default:
      break;
280
  }
281
282
283
  return "";
}

284
285
std::string cmGeneratorTarget::GetOutputName(
  const std::string& config, cmStateEnums::ArtifactType artifact) const
286
{
287
  // Lookup/compute/cache the output name for this configuration.
288
  OutputNameKey key(config, artifact);
289
290
  cmGeneratorTarget::OutputNameMapType::iterator i =
    this->OutputNameMap.find(key);
291
  if (i == this->OutputNameMap.end()) {
292
293
294
    // Add empty name in map to detect potential recursion.
    OutputNameMapType::value_type entry(key, "");
    i = this->OutputNameMap.insert(entry).first;
295

296
297
    // Compute output name.
    std::vector<std::string> props;
298
    std::string type = this->GetOutputTargetType(artifact);
299
    std::string configUpper = cmSystemTools::UpperCase(config);
300
    if (!type.empty() && !configUpper.empty()) {
301
302
      // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
      props.push_back(type + "_OUTPUT_NAME_" + configUpper);
303
304
    }
    if (!type.empty()) {
305
306
      // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME
      props.push_back(type + "_OUTPUT_NAME");
307
308
    }
    if (!configUpper.empty()) {
309
310
311
312
      // OUTPUT_NAME_<CONFIG>
      props.push_back("OUTPUT_NAME_" + configUpper);
      // <CONFIG>_OUTPUT_NAME
      props.push_back(configUpper + "_OUTPUT_NAME");
313
    }
314
315
    // OUTPUT_NAME
    props.push_back("OUTPUT_NAME");
316

317
    std::string outName;
318
319
    for (std::string const& p : props) {
      if (const char* outNameProp = this->GetProperty(p)) {
320
321
322
        outName = outNameProp;
        break;
      }
323
    }
324

325
    if (outName.empty()) {
326
      outName = this->GetName();
327
    }
328
329
330

    // Now evaluate genex and update the previously-prepared map entry.
    cmGeneratorExpression ge;
331
    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outName);
332
    i->second = cge->Evaluate(this->LocalGenerator, config);
333
  } else if (i->second.empty()) {
334
335
    // An empty map entry indicates we have been called recursively
    // from the above block.
336
    this->LocalGenerator->GetCMakeInstance()->IssueMessage(
337
338
      cmake::FATAL_ERROR,
      "Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.",
339
      this->GetBacktrace());
340
  }
341
  return i->second;
342
343
}

344
345
346
347
348
349
350
void cmGeneratorTarget::ClearSourcesCache()
{
  this->KindedSourcesMap.clear();
  this->LinkImplementationLanguageIsContextDependent = true;
  this->Objects.clear();
}

351
void cmGeneratorTarget::AddSourceCommon(const std::string& src)
352
{
353
354
  cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
  cmGeneratorExpression ge(lfbt);
355
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src);
356
  cge->SetEvaluateForBuildsystem(true);
357
  this->SourceEntries.push_back(new TargetPropertyEntry(std::move(cge)));
358
  this->ClearSourcesCache();
359
360
}

361
362
363
364
365
366
void cmGeneratorTarget::AddSource(const std::string& src)
{
  this->Target->AddSource(src);
  this->AddSourceCommon(src);
}

367
368
369
void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
  this->Target->AddTracedSources(srcs);
370
  if (!srcs.empty()) {
371
    this->AddSourceCommon(cmJoin(srcs, ";"));
372
  }
373
374
}

375
376
377
378
379
380
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);
381
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src);
382
383
384
385
386
  cge->SetEvaluateForBuildsystem(true);
  // Insert before begin/end
  std::vector<TargetPropertyEntry*>::iterator pos = before
    ? this->IncludeDirectoriesEntries.begin()
    : this->IncludeDirectoriesEntries.end();
387
388
  this->IncludeDirectoriesEntries.insert(
    pos, new TargetPropertyEntry(std::move(cge)));
389
390
}

391
392
std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(
  cmSourceFile const* sf) const
393
{
394
  SourceEntriesType::const_iterator i = this->SourceDepends.find(sf);
395
  if (i != this->SourceDepends.end()) {
396
    return &i->second.Depends;
397
  }
Daniel Pfeifer's avatar
Daniel Pfeifer committed
398
  return nullptr;
399
400
}

401
402
403
404
static void handleSystemIncludesDep(
  cmLocalGenerator* lg, cmGeneratorTarget const* depTgt,
  const std::string& config, cmGeneratorTarget const* headTarget,
  cmGeneratorExpressionDAGChecker* dagChecker,
405
406
  std::vector<std::string>& result, bool excludeImported,
  std::string const& language)
407
408
{
  if (const char* dirs =
409
        depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) {
410
    cmGeneratorExpression ge;
411
412
    cmSystemTools::ExpandListArgument(
      ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
413
                               dagChecker, language),
414
415
416
      result);
  }
  if (!depTgt->IsImported() || excludeImported) {
417
    return;
418
  }
419
420

  if (const char* dirs =
421
        depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
422
    cmGeneratorExpression ge;
423
424
    cmSystemTools::ExpandListArgument(
      ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
425
                               dagChecker, language),
426
427
      result);
  }
428
429
}

430
/* clang-format off */
431
#define IMPLEMENT_VISIT(KIND)                                                 \
432
  {                                                                           \
433
    KindedSources const& kinded = this->GetKindedSources(config);             \
434
435
436
    for (SourceAndKind const& s : kinded.Sources) {                           \
      if (s.Kind == KIND) {                                                   \
        data.push_back(s.Source);                                             \
437
      }                                                                       \
438
439
440
    }                                                                         \
  }
/* clang-format on */
441

442
443
void cmGeneratorTarget::GetObjectSources(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
444
{
445
  IMPLEMENT_VISIT(SourceKindObjectSource);
446

447
  if (!this->Objects.empty()) {
448
    return;
449
  }
450

451
452
  for (cmSourceFile const* it : data) {
    this->Objects[it];
453
  }
454
455

  this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
456
457
}

458
void cmGeneratorTarget::ComputeObjectMapping()
459
{
460
  if (!this->Objects.empty()) {
461
    return;
462
  }
463
464
465

  std::vector<std::string> configs;
  this->Makefile->GetConfigurations(configs);
466
  if (configs.empty()) {
467
    configs.emplace_back();
468
  }
469
  for (std::string const& c : configs) {
470
    std::vector<cmSourceFile const*> sourceFiles;
471
    this->GetObjectSources(sourceFiles, c);
472
  }
473
474
}

475
476
477
const char* cmGeneratorTarget::GetFeature(const std::string& feature,
                                          const std::string& config) const
{
478
  if (!config.empty()) {
479
480
481
    std::string featureConfig = feature;
    featureConfig += "_";
    featureConfig += cmSystemTools::UpperCase(config);
482
    if (const char* value = this->GetProperty(featureConfig)) {
483
484
      return value;
    }
485
486
  }
  if (const char* value = this->GetProperty(feature)) {
487
    return value;
488
  }
489
  return this->LocalGenerator->GetFeature(feature, config);
490
491
}

492
493
bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
                                     std::string const& config) const
494
{
495
  const char* feature = "INTERPROCEDURAL_OPTIMIZATION";
496
497
498
499
500
501
502
  const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config));

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

503
504
505
506
507
  if (lang != "C" && lang != "CXX" && lang != "Fortran") {
    // We do not define IPO behavior for other languages.
    return false;
  }

508
509
510
  cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069();

  if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) {
511
    if (this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_LEGACY_BEHAVIOR")) {
512
513
514
515
516
517
      return true;
    }
    if (this->PolicyReportedCMP0069) {
      // problem is already reported, no need to issue a message
      return false;
    }
518
519
520
    const bool in_try_compile =
      this->LocalGenerator->GetCMakeInstance()->GetIsInTryCompile();
    if (cmp0069 == cmPolicies::WARN && !in_try_compile) {
521
522
523
524
525
526
527
528
529
530
531
532
533
      std::ostringstream w;
      w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0069) << "\n";
      w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target "
        << "'" << this->GetName() << "'.";
      this->LocalGenerator->GetCMakeInstance()->IssueMessage(
        cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace());

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

  // Note: check consistency with messages from CheckIPOSupported
Daniel Pfeifer's avatar
Daniel Pfeifer committed
534
  const char* message = nullptr;
535
  if (!this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_SUPPORTED_BY_CMAKE")) {
536
    message = "CMake doesn't support IPO for current compiler";
537
538
  } else if (!this->Makefile->IsOn("_CMAKE_" + lang +
                                   "_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) {
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
    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(
    cmake::FATAL_ERROR, message, this->GetBacktrace());
  return false;
559
560
}

561
const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
562
{
563
564
  this->ComputeObjectMapping();
  return this->Objects[file];
565
566
}

567
568
569
570
571
572
573
574
575
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
576
  return nullptr;
577
578
}

579
void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
580
581
582
583
584
585
{
  this->ExplicitObjectName.insert(sf);
}

bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
{
586
  const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
587
588
  std::set<cmSourceFile const*>::const_iterator it =
    this->ExplicitObjectName.find(file);
589
590
591
  return it != this->ExplicitObjectName.end();
}

592
593
594
void cmGeneratorTarget::GetModuleDefinitionSources(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
{
595
  IMPLEMENT_VISIT(SourceKindModuleDefinition);
596
597
}

598
599
void cmGeneratorTarget::GetHeaderSources(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
600
{
601
  IMPLEMENT_VISIT(SourceKindHeader);
602
603
}

604
605
void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile const*>& data,
                                        const std::string& config) const
606
{
607
  IMPLEMENT_VISIT(SourceKindExtra);
608
609
}

610
611
void cmGeneratorTarget::GetCustomCommands(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
612
{
613
  IMPLEMENT_VISIT(SourceKindCustomCommand);
614
615
}

616
617
void cmGeneratorTarget::GetExternalObjects(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
618
{
619
  IMPLEMENT_VISIT(SourceKindExternalObject);
620
621
}

622
void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& headers,
623
                                               const std::string& config) const
624
{
625
626
  KindedSources const& kinded = this->GetKindedSources(config);
  headers = kinded.ExpectedResxHeaders;
627
628
}

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

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

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

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

653
654
void cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers,
                                               const std::string& config) const
655
{
656
657
  KindedSources const& kinded = this->GetKindedSources(config);
  headers = kinded.ExpectedXamlHeaders;
658
659
}

660
661
void cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
                                               const std::string& config) const
662
{
663
664
  KindedSources const& kinded = this->GetKindedSources(config);
  srcs = kinded.ExpectedXamlSources;
665
666
667
668
}

std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
{
669
  if (!this->UtilityItemsDone) {
670
    this->UtilityItemsDone = true;
671
    std::set<std::string> const& utilities = this->GetUtilities();
672
    for (std::string const& i : utilities) {
673
674
675
676
677
678
      if (cmGeneratorTarget* gt =
            this->LocalGenerator->FindGeneratorTargetToUse(i)) {
        this->UtilityItems.insert(cmLinkItem(gt));
      } else {
        this->UtilityItems.insert(cmLinkItem(i));
      }
679
    }
680
  }
681
  return this->UtilityItems;
682
683
}

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

690
691
692
const char* cmGeneratorTarget::GetLocation(const std::string& config) const
{
  static std::string location;
693
  if (this->IsImported()) {
694
695
    location = this->Target->ImportedGetFullPath(
      config, cmStateEnums::RuntimeBinaryArtifact);
696
  } else {
697
    location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
698
  }
699
700
701
  return location.c_str();
}

702
703
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreBuildCommands()
  const
704
705
706
707
{
  return this->Target->GetPreBuildCommands();
}

708
709
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreLinkCommands()
  const
710
711
712
713
{
  return this->Target->GetPreLinkCommands();
}

714
715
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPostBuildCommands()
  const
716
717
718
719
{
  return this->Target->GetPostBuildCommands();
}

720
721
722
723
724
bool cmGeneratorTarget::IsImported() const
{
  return this->Target->IsImported();
}

725
726
727
728
729
bool cmGeneratorTarget::IsImportedGloballyVisible() const
{
  return this->Target->IsImportedGloballyVisible();
}

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

  // Now handle the deprecated build-time configuration location.
740
  location = this->GetDirectory();
741
  const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
742
  if (cfgid && strcmp(cfgid, ".") != 0) {
743
744
    location += "/";
    location += cfgid;
745
  }
746

747
  if (this->IsAppBundleOnApple()) {
748
    std::string macdir = this->BuildBundleDirectory("", "", FullLevel);
749
    if (!macdir.empty()) {
750
751
752
      location += "/";
      location += macdir;
    }
753
  }
754
  location += "/";
755
  location += this->GetFullName("", cmStateEnums::RuntimeBinaryArtifact);
756
757
758
  return location.c_str();
}

759
bool cmGeneratorTarget::IsSystemIncludeDirectory(
760
761
  const std::string& dir, const std::string& config,
  const std::string& language) const
762
{
763
  assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
764
  std::string config_upper;
765
  if (!config.empty()) {
766
    config_upper = cmSystemTools::UpperCase(config);
767
  }
768

769
  typedef std::map<std::string, std::vector<std::string>> IncludeCacheType;
770
  IncludeCacheType::const_iterator iter =
771
    this->SystemIncludesCache.find(config_upper);
772

773
  if (iter == this->SystemIncludesCache.end()) {
774
    cmGeneratorExpressionDAGChecker dagChecker(
775
      this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
776

777
    bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
778

779
    std::vector<std::string> result;
780
    for (std::string const& it : this->Target->GetSystemIncludeDirectories()) {
781
      cmGeneratorExpression ge;
782
      cmSystemTools::ExpandListArgument(
783
        ge.Parse(it)->Evaluate(this->LocalGenerator, config, false, this,
784
                               &dagChecker, language),
785
786
        result);
    }
787

788
    std::vector<cmGeneratorTarget const*> const& deps =
789
      this->GetLinkImplementationClosure(config);
790
791
    for (cmGeneratorTarget const* dep : deps) {
      handleSystemIncludesDep(this->LocalGenerator, dep, config, this,
792
                              &dagChecker, result, excludeImported, language);
793
    }
794

795
796
797
798
    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());
799

800
801
    IncludeCacheType::value_type entry(config_upper, result);
    iter = this->SystemIncludesCache.insert(entry).first;
802
  }
803

Stephen Kelly's avatar
Stephen Kelly committed
804
  return std::binary_search(iter->second.begin(), iter->second.end(), dir);
805
806
}

807
bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
808
809
810
811
{
  return this->Target->GetPropertyAsBool(prop);
}

812
813
814
815
816
static void AddInterfaceEntries(
  cmGeneratorTarget const* thisTarget, std::string const& config,
  std::string const& prop,
  std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
{
817
818
  if (cmLinkImplementationLibraries const* impl =
        thisTarget->GetLinkImplementationLibraries(config)) {
819
820
    for (cmLinkImplItem const& lib : impl->Libraries) {
      if (lib.Target) {
821
822
        std::string genex =
          "$<TARGET_PROPERTY:" + lib.AsStr() + "," + prop + ">";
823
        cmGeneratorExpression ge(lib.Backtrace);
824
        std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
825
826
        cge->SetEvaluateForBuildsystem(true);
        entries.push_back(
827
          new cmGeneratorTarget::TargetPropertyEntry(std::move(cge), lib));
828
829
      }
    }
830
  }
831
832
}

833
834
835
836
837
838
839
840
841
static void AddObjectEntries(
  cmGeneratorTarget const* thisTarget, std::string const& config,
  std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
{
  if (cmLinkImplementationLibraries const* impl =
        thisTarget->GetLinkImplementationLibraries(config)) {
    for (cmLinkImplItem const& lib : impl->Libraries) {
      if (lib.Target &&
          lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
842
        std::string genex = "$<TARGET_OBJECTS:" + lib.AsStr() + ">";
843
844
845
846
847
848
849
850
851
852
        cmGeneratorExpression ge(lib.Backtrace);
        std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
        cge->SetEvaluateForBuildsystem(true);
        entries.push_back(
          new cmGeneratorTarget::TargetPropertyEntry(std::move(cge), lib));
      }
    }
  }
}

853
854
855
static bool processSources(
  cmGeneratorTarget const* tgt,
  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,