cmGeneratorTarget.cxx 175 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 "cmAlgorithms.h"
6
#include "cmComputeLinkInformation.h"
7
#include "cmCustomCommand.h"
8
#include "cmCustomCommandGenerator.h"
9
#include "cmCustomCommandLines.h"
10
11
12
13
14
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
15
#include "cmPropertyMap.h"
16
#include "cmSourceFile.h"
17
#include "cmSourceFileLocation.h"
18
#include "cmState.h"
19
#include "cmSystemTools.h"
20
#include "cmTarget.h"
21
#include "cmTargetLinkLibraryType.h"
22
#include "cmTargetPropertyComputer.h"
23
24
#include "cm_auto_ptr.hxx"
#include "cmake.h"
25

26
27
28
#include <algorithm>
#include <assert.h>
#include <cmsys/RegularExpression.hxx>
29
#include <errno.h>
30
31
32
33
34
35
#include <iterator>
#include <queue>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
36

37
38
39
40
#if defined(CMake_HAVE_CXX_UNORDERED_SET)
#include <unordered_set>
#define UNORDERED_SET std::unordered_set
#elif defined(CMAKE_BUILD_WITH_CMAKE)
41
42
43
44
45
46
#include <cmsys/hash_set.hxx>
#define UNORDERED_SET cmsys::hash_set
#else
#define UNORDERED_SET std::set
#endif

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
template <>
const char* cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
  cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
  cmListFileBacktrace const& /* context */)
{
  return tgt->GetSourcesProperty();
}

template <>
const char* cmTargetPropertyComputer::ComputeLocationForBuild<
  cmGeneratorTarget>(cmGeneratorTarget const* tgt)
{
  return tgt->GetLocation("");
}

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

69
70
class cmGeneratorTarget::TargetPropertyEntry
{
71
  static cmLinkImplItem NoLinkImplItem;
72

73
public:
74
  TargetPropertyEntry(CM_AUTO_PTR<cmCompiledGeneratorExpression> cge,
75
                      cmLinkImplItem const& item = NoLinkImplItem)
76
77
78
79
    : ge(cge)
    , LinkImplItem(item)
  {
  }
80
  const CM_AUTO_PTR<cmCompiledGeneratorExpression> ge;
81
82
83
84
  cmLinkImplItem const& LinkImplItem;
};
cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;

85
void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib,
86
                     cmGeneratorTarget const* target, cmake* cm)
87
{
88
  if (!badObjLib.empty()) {
89
    std::ostringstream e;
90
    e << "OBJECT library \"" << target->GetName() << "\" contains:\n";
91
92
    for (std::vector<cmSourceFile*>::const_iterator i = badObjLib.begin();
         i != badObjLib.end(); ++i) {
93
      e << "  " << (*i)->GetLocation().GetName() << "\n";
94
    }
95
96
    e << "but may contain only sources that compile, header files, and "
         "other files that would not affect linking of a normal library.";
97
98
    cm->IssueMessage(cmake::FATAL_ERROR, e.str(), target->GetBacktrace());
  }
99
100
}

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
struct ObjectSourcesTag
{
};
struct CustomCommandsTag
{
};
struct ExtraSourcesTag
{
};
struct HeaderSourcesTag
{
};
struct ExternalObjectsTag
{
};
struct IDLSourcesTag
{
};
struct ResxTag
{
};
struct ModuleDefinitionFileTag
{
};
struct AppManifestTag
{
};
struct ManifestsTag
{
};
struct CertificatesTag
{
};
struct XamlTag
{
};

template <typename Tag, typename OtherTag>
139
140
struct IsSameTag
{
141
142
  enum
  {
143
144
145
146
    Result = false
  };
};

147
template <typename Tag>
148
149
struct IsSameTag<Tag, Tag>
{
150
151
  enum
  {
152
153
154
155
    Result = true
  };
};

156
template <bool>
157
158
struct DoAccept
{
159
  template <typename T>
160
  static void Do(T& /*unused*/, cmSourceFile* /*unused*/)
161
162
  {
  }
163
164
};

165
template <>
166
167
struct DoAccept<true>
{
168
  static void Do(std::vector<cmSourceFile const*>& files, cmSourceFile* f)
169
  {
170
    files.push_back(f);
171
  }
172
  static void Do(cmGeneratorTarget::ResxData& data, cmSourceFile* f)
173
  {
174
175
176
177
178
179
    // Build and save the name of the corresponding .h file
    // This relationship will be used later when building the project files.
    // Both names would have been auto generated from Visual Studio
    // where the user supplied the file name and Visual Studio
    // appended the suffix.
    std::string resx = f->GetFullPath();
180
    std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
181
182
    data.ExpectedResxHeaders.insert(hFileName);
    data.ResxSources.push_back(f);
183
  }
184
  static void Do(cmGeneratorTarget::XamlData& data, cmSourceFile* f)
185
  {
186
187
188
189
190
191
192
193
194
195
196
    // Build and save the name of the corresponding .h and .cpp file
    // This relationship will be used later when building the project files.
    // Both names would have been auto generated from Visual Studio
    // where the user supplied the file name and Visual Studio
    // appended the suffix.
    std::string xaml = f->GetFullPath();
    std::string hFileName = xaml + ".h";
    std::string cppFileName = xaml + ".cpp";
    data.ExpectedXamlHeaders.insert(hFileName);
    data.ExpectedXamlSources.insert(cppFileName);
    data.XamlSources.push_back(f);
197
  }
198
  static void Do(std::string& data, cmSourceFile* f)
199
  {
200
    data = f->GetFullPath();
201
  }
202
203
};

204
template <typename Tag, typename DataType = std::vector<cmSourceFile const*> >
205
206
207
208
struct TagVisitor
{
  DataType& Data;
  std::vector<cmSourceFile*> BadObjLibFiles;
209
  cmGeneratorTarget const* Target;
210
  cmGlobalGenerator* GlobalGenerator;
211
212
213
  cmsys::RegularExpression Header;
  bool IsObjLib;

214
  TagVisitor(cmGeneratorTarget const* target, DataType& data)
215
216
217
218
    : Data(data)
    , Target(target)
    , GlobalGenerator(target->GetLocalGenerator()->GetGlobalGenerator())
    , Header(CM_HEADER_REGEX)
219
    , IsObjLib(target->GetType() == cmStateEnums::OBJECT_LIBRARY)
220
221
222
223
224
225
226
227
228
  {
  }

  ~TagVisitor()
  {
    reportBadObjLib(this->BadObjLibFiles, this->Target,
                    this->GlobalGenerator->GetCMakeInstance());
  }

229
  void Accept(cmSourceFile* sf)
230
231
  {
    std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
232
    if (sf->GetCustomCommand()) {
233
      DoAccept<IsSameTag<Tag, CustomCommandsTag>::Result>::Do(this->Data, sf);
234
    } else if (this->Target->GetType() == cmStateEnums::UTILITY) {
235
      DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
236
    } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
237
      DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
238
    } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
239
      DoAccept<IsSameTag<Tag, ExternalObjectsTag>::Result>::Do(this->Data, sf);
240
      if (this->IsObjLib) {
241
242
        this->BadObjLibFiles.push_back(sf);
      }
243
    } else if (!sf->GetLanguage().empty()) {
244
      DoAccept<IsSameTag<Tag, ObjectSourcesTag>::Result>::Do(this->Data, sf);
245
    } else if (ext == "def") {
246
247
      DoAccept<IsSameTag<Tag, ModuleDefinitionFileTag>::Result>::Do(this->Data,
                                                                    sf);
248
      if (this->IsObjLib) {
249
250
        this->BadObjLibFiles.push_back(sf);
      }
251
    } else if (ext == "idl") {
252
      DoAccept<IsSameTag<Tag, IDLSourcesTag>::Result>::Do(this->Data, sf);
253
      if (this->IsObjLib) {
254
255
        this->BadObjLibFiles.push_back(sf);
      }
256
    } else if (ext == "resx") {
257
      DoAccept<IsSameTag<Tag, ResxTag>::Result>::Do(this->Data, sf);
258
    } else if (ext == "appxmanifest") {
259
      DoAccept<IsSameTag<Tag, AppManifestTag>::Result>::Do(this->Data, sf);
260
    } else if (ext == "manifest") {
261
      DoAccept<IsSameTag<Tag, ManifestsTag>::Result>::Do(this->Data, sf);
262
    } else if (ext == "pfx") {
263
      DoAccept<IsSameTag<Tag, CertificatesTag>::Result>::Do(this->Data, sf);
264
    } else if (ext == "xaml") {
265
      DoAccept<IsSameTag<Tag, XamlTag>::Result>::Do(this->Data, sf);
266
    } else if (this->Header.find(sf->GetFullPath().c_str())) {
267
      DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
268
    } else if (this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) {
269
      DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
270
    } else {
271
      DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
272
    }
273
274
275
  }
};

276
void CreatePropertyGeneratorExpressions(
277
278
279
  cmStringRange const& entries, cmBacktraceRange const& backtraces,
  std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items,
  bool evaluateForBuildsystem = false)
280
281
282
{
  std::vector<cmListFileBacktrace>::const_iterator btIt = backtraces.begin();
  for (std::vector<std::string>::const_iterator it = entries.begin();
283
       it != entries.end(); ++it, ++btIt) {
284
    cmGeneratorExpression ge(*btIt);
285
    CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(*it);
286
287
    cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
    items.push_back(new cmGeneratorTarget::TargetPropertyEntry(cge));
288
  }
289
290
}

291
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
292
  : Target(t)
293
  , FortranModuleDirectoryCreated(false)
294
295
296
297
298
299
300
301
302
  , SourceFileFlagsConstructed(false)
  , PolicyWarnedCMP0022(false)
  , DebugIncludesDone(false)
  , DebugCompileOptionsDone(false)
  , DebugCompileFeaturesDone(false)
  , DebugCompileDefinitionsDone(false)
  , DebugSourcesDone(false)
  , LinkImplementationLanguageIsContextDependent(true)
  , UtilityItemsDone(false)
303
304
{
  this->Makefile = this->Target->GetMakefile();
305
  this->LocalGenerator = lg;
306
  this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
307

308
309
  this->GlobalGenerator->ComputeTargetObjectDirectory(this);

310
311
312
  CreatePropertyGeneratorExpressions(t->GetIncludeDirectoriesEntries(),
                                     t->GetIncludeDirectoriesBacktraces(),
                                     this->IncludeDirectoriesEntries);
313

314
315
316
  CreatePropertyGeneratorExpressions(t->GetCompileOptionsEntries(),
                                     t->GetCompileOptionsBacktraces(),
                                     this->CompileOptionsEntries);
317

318
319
320
  CreatePropertyGeneratorExpressions(t->GetCompileFeaturesEntries(),
                                     t->GetCompileFeaturesBacktraces(),
                                     this->CompileFeaturesEntries);
321

322
323
324
  CreatePropertyGeneratorExpressions(t->GetCompileDefinitionsEntries(),
                                     t->GetCompileDefinitionsBacktraces(),
                                     this->CompileDefinitionsEntries);
325

326
327
328
  CreatePropertyGeneratorExpressions(t->GetSourceEntries(),
                                     t->GetSourceBacktraces(),
                                     this->SourceEntries, true);
329

330
331
332
  this->DLLPlatform =
    (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
     this->Makefile->IsOn("MINGW"));
333
334

  this->PolicyMap = t->PolicyMap;
335
336
}

337
338
cmGeneratorTarget::~cmGeneratorTarget()
{
339
  cmDeleteAll(this->IncludeDirectoriesEntries);
340
  cmDeleteAll(this->CompileOptionsEntries);
341
  cmDeleteAll(this->CompileFeaturesEntries);
342
  cmDeleteAll(this->CompileDefinitionsEntries);
343
  cmDeleteAll(this->SourceEntries);
344
345
346
  cmDeleteAll(this->LinkInformation);
}

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
const char* cmGeneratorTarget::GetSourcesProperty() const
{
  std::vector<std::string> values;
  for (std::vector<cmGeneratorTarget::TargetPropertyEntry *>::const_iterator
         it = this->SourceEntries.begin(),
         end = this->SourceEntries.end();
       it != end; ++it) {
    values.push_back((*it)->ge->GetInput());
  }
  static std::string value;
  value.clear();
  value = cmJoin(values, "");
  return value.c_str();
}

362
363
364
365
366
cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const
{
  return this->GetLocalGenerator()->GetGlobalGenerator();
}

367
368
369
370
371
cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const
{
  return this->LocalGenerator;
}

372
cmStateEnums::TargetType cmGeneratorTarget::GetType() const
373
374
375
376
{
  return this->Target->GetType();
}

377
const std::string& cmGeneratorTarget::GetName() const
378
379
380
381
{
  return this->Target->GetName();
}

382
383
std::string cmGeneratorTarget::GetExportName() const
{
384
  const char* exportName = this->GetProperty("EXPORT_NAME");
385

386
387
  if (exportName && *exportName) {
    if (!cmGeneratorExpression::IsValidTargetName(exportName)) {
388
389
390
391
392
393
      std::ostringstream e;
      e << "EXPORT_NAME property \"" << exportName << "\" for \""
        << this->GetName() << "\": is not valid.";
      cmSystemTools::Error(e.str().c_str());
      return "";
    }
394
395
    return exportName;
  }
396
397
398
  return this->GetName();
}

399
const char* cmGeneratorTarget::GetProperty(const std::string& prop) const
400
{
401
402
403
404
405
406
407
408
409
410
411
412
  if (!cmTargetPropertyComputer::PassesWhitelist(
        this->GetType(), prop, this->Makefile->GetMessenger(),
        this->GetBacktrace())) {
    return 0;
  }
  if (const char* result = cmTargetPropertyComputer::GetProperty(
        this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) {
    return result;
  }
  if (cmSystemTools::GetFatalErrorOccured()) {
    return CM_NULLPTR;
  }
413
414
415
  return this->Target->GetProperty(prop);
}

416
417
const char* cmGeneratorTarget::GetOutputTargetType(bool implib) const
{
418
  switch (this->GetType()) {
419
    case cmStateEnums::SHARED_LIBRARY:
420
421
      if (this->IsDLLPlatform()) {
        if (implib) {
422
423
424
          // A DLL import library is treated as an archive target.
          return "ARCHIVE";
        }
425
426
        // A DLL shared library is treated as a runtime target.
        return "RUNTIME";
427
      } else {
428
429
430
        // For non-DLL platforms shared libraries are treated as
        // library targets.
        return "LIBRARY";
431
      }
432
    case cmStateEnums::STATIC_LIBRARY:
433
434
      // Static libraries are always treated as archive targets.
      return "ARCHIVE";
435
    case cmStateEnums::MODULE_LIBRARY:
436
      if (implib) {
437
438
        // Module libraries are always treated as library targets.
        return "ARCHIVE";
439
      } else {
440
441
        // Module import libraries are treated as archive targets.
        return "LIBRARY";
442
      }
443
    case cmStateEnums::EXECUTABLE:
444
      if (implib) {
445
446
        // Executable import libraries are treated as archive targets.
        return "ARCHIVE";
447
      } else {
448
449
        // Executables are always treated as runtime targets.
        return "RUNTIME";
450
      }
451
452
    default:
      break;
453
  }
454
455
456
  return "";
}

457
458
459
std::string cmGeneratorTarget::GetOutputName(const std::string& config,
                                             bool implib) const
{
460
461
462
463
  // Lookup/compute/cache the output name for this configuration.
  OutputNameKey key(config, implib);
  cmGeneratorTarget::OutputNameMapType::iterator i =
    this->OutputNameMap.find(key);
464
  if (i == this->OutputNameMap.end()) {
465
466
467
    // Add empty name in map to detect potential recursion.
    OutputNameMapType::value_type entry(key, "");
    i = this->OutputNameMap.insert(entry).first;
468

469
470
    // Compute output name.
    std::vector<std::string> props;
471
    std::string type = this->GetOutputTargetType(implib);
472
    std::string configUpper = cmSystemTools::UpperCase(config);
473
    if (!type.empty() && !configUpper.empty()) {
474
475
      // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
      props.push_back(type + "_OUTPUT_NAME_" + configUpper);
476
477
    }
    if (!type.empty()) {
478
479
      // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME
      props.push_back(type + "_OUTPUT_NAME");
480
481
    }
    if (!configUpper.empty()) {
482
483
484
485
      // OUTPUT_NAME_<CONFIG>
      props.push_back("OUTPUT_NAME_" + configUpper);
      // <CONFIG>_OUTPUT_NAME
      props.push_back(configUpper + "_OUTPUT_NAME");
486
    }
487
488
    // OUTPUT_NAME
    props.push_back("OUTPUT_NAME");
489

490
    std::string outName;
491
492
493
    for (std::vector<std::string>::const_iterator it = props.begin();
         it != props.end(); ++it) {
      if (const char* outNameProp = this->GetProperty(*it)) {
494
495
496
        outName = outNameProp;
        break;
      }
497
    }
498

499
    if (outName.empty()) {
500
      outName = this->GetName();
501
    }
502
503
504

    // Now evaluate genex and update the previously-prepared map entry.
    cmGeneratorExpression ge;
505
    CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(outName);
506
    i->second = cge->Evaluate(this->LocalGenerator, config);
507
  } else if (i->second.empty()) {
508
509
    // An empty map entry indicates we have been called recursively
    // from the above block.
510
    this->LocalGenerator->GetCMakeInstance()->IssueMessage(
511
512
      cmake::FATAL_ERROR,
      "Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.",
513
      this->GetBacktrace());
514
  }
515
  return i->second;
516
517
}

518
void cmGeneratorTarget::AddSourceCommon(const std::string& src)
519
{
520
521
  cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
  cmGeneratorExpression ge(lfbt);
522
  CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(src);
523
  cge->SetEvaluateForBuildsystem(true);
524
  this->SourceEntries.push_back(new TargetPropertyEntry(cge));
525
526
  this->SourceFilesMap.clear();
  this->LinkImplementationLanguageIsContextDependent = true;
527
528
}

529
530
531
532
533
534
void cmGeneratorTarget::AddSource(const std::string& src)
{
  this->Target->AddSource(src);
  this->AddSourceCommon(src);
}

535
536
537
void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
  this->Target->AddTracedSources(srcs);
538
  if (!srcs.empty()) {
539
    this->AddSourceCommon(cmJoin(srcs, ";"));
540
  }
541
542
}

543
544
std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(
  cmSourceFile const* sf) const
545
{
546
  SourceEntriesType::const_iterator i = this->SourceDepends.find(sf);
547
  if (i != this->SourceDepends.end()) {
548
    return &i->second.Depends;
549
  }
Daniel Pfeifer's avatar
Daniel Pfeifer committed
550
  return CM_NULLPTR;
551
552
}

553
554
555
556
557
static void handleSystemIncludesDep(
  cmLocalGenerator* lg, cmGeneratorTarget const* depTgt,
  const std::string& config, cmGeneratorTarget const* headTarget,
  cmGeneratorExpressionDAGChecker* dagChecker,
  std::vector<std::string>& result, bool excludeImported)
558
559
{
  if (const char* dirs =
560
        depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) {
561
    cmGeneratorExpression ge;
562
563
564
565
566
567
    cmSystemTools::ExpandListArgument(
      ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
                               dagChecker),
      result);
  }
  if (!depTgt->IsImported() || excludeImported) {
568
    return;
569
  }
570
571

  if (const char* dirs =
572
        depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
573
    cmGeneratorExpression ge;
574
575
576
577
578
    cmSystemTools::ExpandListArgument(
      ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
                               dagChecker),
      result);
  }
579
580
}

581
582
583
584
585
586
587
588
589
590
591
592
/* clang-format off */
#define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE)                                  \
  {                                                                           \
    std::vector<cmSourceFile*> sourceFiles;                                   \
    this->GetSourceFiles(sourceFiles, config);                                \
    TagVisitor< DATA##Tag DATATYPE > visitor(this, data);                     \
    for (std::vector<cmSourceFile*>::const_iterator si = sourceFiles.begin(); \
         si != sourceFiles.end(); ++si) {                                     \
      visitor.Accept(*si);                                                    \
    }                                                                         \
  }
/* clang-format on */
593

594
#define IMPLEMENT_VISIT(DATA) IMPLEMENT_VISIT_IMPL(DATA, EMPTY)
595
596
597
598

#define EMPTY
#define COMMA ,

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

604
  if (!this->Objects.empty()) {
605
    return;
606
  }
607

608
609
  for (std::vector<cmSourceFile const*>::const_iterator it = data.begin();
       it != data.end(); ++it) {
610
    this->Objects[*it];
611
  }
612
613

  this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
614
615
}

616
void cmGeneratorTarget::ComputeObjectMapping()
617
{
618
  if (!this->Objects.empty()) {
619
    return;
620
  }
621
622
623

  std::vector<std::string> configs;
  this->Makefile->GetConfigurations(configs);
624
  if (configs.empty()) {
625
    configs.push_back("");
626
627
628
  }
  for (std::vector<std::string>::const_iterator ci = configs.begin();
       ci != configs.end(); ++ci) {
629
630
    std::vector<cmSourceFile const*> sourceFiles;
    this->GetObjectSources(sourceFiles, *ci);
631
  }
632
633
}

634
635
636
const char* cmGeneratorTarget::GetFeature(const std::string& feature,
                                          const std::string& config) const
{
637
  if (!config.empty()) {
638
639
640
    std::string featureConfig = feature;
    featureConfig += "_";
    featureConfig += cmSystemTools::UpperCase(config);
641
    if (const char* value = this->GetProperty(featureConfig)) {
642
643
      return value;
    }
644
645
  }
  if (const char* value = this->GetProperty(feature)) {
646
    return value;
647
  }
648
  return this->LocalGenerator->GetFeature(feature, config);
649
650
651
652
653
654
655
656
}

bool cmGeneratorTarget::GetFeatureAsBool(const std::string& feature,
                                         const std::string& config) const
{
  return cmSystemTools::IsOn(this->GetFeature(feature, config));
}

657
const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
658
{
659
660
  this->ComputeObjectMapping();
  return this->Objects[file];
661
662
}

663
void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
664
665
666
667
668
669
{
  this->ExplicitObjectName.insert(sf);
}

bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
{
670
  const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
671
672
  std::set<cmSourceFile const*>::const_iterator it =
    this->ExplicitObjectName.find(file);
673
674
675
  return it != this->ExplicitObjectName.end();
}

676
677
void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile const*>& data,
                                      const std::string& config) const
678
{
679
  IMPLEMENT_VISIT(IDLSources);
680
681
}

682
683
void cmGeneratorTarget::GetHeaderSources(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
684
{
685
  IMPLEMENT_VISIT(HeaderSources);
686
687
}

688
689
void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile const*>& data,
                                        const std::string& config) const
690
{
691
  IMPLEMENT_VISIT(ExtraSources);
692
693
}

694
695
void cmGeneratorTarget::GetCustomCommands(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
696
{
697
  IMPLEMENT_VISIT(CustomCommands);
698
699
}

700
701
void cmGeneratorTarget::GetExternalObjects(
  std::vector<cmSourceFile const*>& data, const std::string& config) const
702
{
703
  IMPLEMENT_VISIT(ExternalObjects);
704
705
}

706
707
void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& srcs,
                                               const std::string& config) const
708
{
709
710
711
  ResxData data;
  IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
  srcs = data.ExpectedResxHeaders;
712
713
}

714
715
void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& srcs,
                                       const std::string& config) const
716
{
717
718
719
  ResxData data;
  IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
  srcs = data.ResxSources;
720
721
}

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

728
729
void cmGeneratorTarget::GetManifests(std::vector<cmSourceFile const*>& data,
                                     const std::string& config) const
730
731
732
733
{
  IMPLEMENT_VISIT(Manifests);
}

734
735
void cmGeneratorTarget::GetCertificates(std::vector<cmSourceFile const*>& data,
                                        const std::string& config) const
736
737
738
739
{
  IMPLEMENT_VISIT(Certificates);
}

740
741
void cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers,
                                               const std::string& config) const
742
743
744
745
746
747
{
  XamlData data;
  IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
  headers = data.ExpectedXamlHeaders;
}

748
749
void cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
                                               const std::string& config) const
750
751
752
{
  XamlData data;
  IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
753
  srcs = data.ExpectedXamlSources;
754
755
756
757
}

std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
{
758
  if (!this->UtilityItemsDone) {
759
    this->UtilityItemsDone = true;
760
    std::set<std::string> const& utilities = this->GetUtilities();
761
762
    for (std::set<std::string>::const_iterator i = utilities.begin();
         i != utilities.end(); ++i) {
763
      cmGeneratorTarget* gt =
764
        this->LocalGenerator->FindGeneratorTargetToUse(*i);
765
      this->UtilityItems.insert(cmLinkItem(*i, gt));
766
    }
767
  }
768
  return this->UtilityItems;
769
770
}

771
772
void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& srcs,
                                       const std::string& config) const
773
774
775
776
777
778
{
  XamlData data;
  IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
  srcs = data.XamlSources;
}

779
780
781
const char* cmGeneratorTarget::GetLocation(const std::string& config) const
{
  static std::string location;
782
  if (this->IsImported()) {
783
    location = this->Target->ImportedGetFullPath(config, false);
784
  } else {
785
    location = this->GetFullPath(config, false);
786
  }
787
788
789
  return location.c_str();
}

790
791
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreBuildCommands()
  const
792
793
794
795
{
  return this->Target->GetPreBuildCommands();
}

796
797
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreLinkCommands()
  const
798
799
800
801
{
  return this->Target->GetPreLinkCommands();
}

802
803
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPostBuildCommands()
  const
804
805
806
807
{
  return this->Target->GetPostBuildCommands();
}

808
809
810
811
812
bool cmGeneratorTarget::IsImported() const
{
  return this->Target->IsImported();
}

813
814
815
816
817
bool cmGeneratorTarget::IsImportedGloballyVisible() const
{
  return this->Target->IsImportedGloballyVisible();
}

818
819
820
const char* cmGeneratorTarget::GetLocationForBuild() const
{
  static std::string location;
821
  if (this->IsImported()) {
822
823
    location = this->Target->ImportedGetFullPath("", false);
    return location.c_str();
824
  }
825
826

  // Now handle the deprecated build-time configuration location.
827
  location = this->GetDirectory();
828
  const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
829
  if (cfgid && strcmp(cfgid, ".") != 0) {
830
831
    location += "/";
    location += cfgid;
832
  }
833

834
835
836
  if (this->IsAppBundleOnApple()) {
    std::string macdir = this->BuildMacContentDirectory("", "", false);
    if (!macdir.empty()) {
837
838
839
      location += "/";
      location += macdir;
    }
840
  }
841
  location += "/";
842
  location += this->GetFullName("", false);
843
844
845
  return location.c_str();
}

846
847
bool cmGeneratorTarget::IsSystemIncludeDirectory(
  const std::string& dir, const std::string& config) const
848
{
849
  assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
850
  std::string config_upper;
851
  if (!config.empty()) {
852
    config_upper = cmSystemTools::UpperCase(config);
853
  }
854
855

  typedef std::map<std::string, std::vector<std::string> > IncludeCacheType;
856
  IncludeCacheType::const_iterator iter =
857
    this->SystemIncludesCache.find(config_upper);
858

859
  if (iter == this->SystemIncludesCache.end()) {
860
    cmGeneratorExpressionDAGChecker dagChecker(
Daniel Pfeifer's avatar
Daniel Pfeifer committed
861
      this->GetName(), "SYSTEM_INCLUDE_DIRECTORIES", CM_NULLPTR, CM_NULLPTR);
862

863
    bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
864

865
    std::vector<std::string> result;
866
867
868
    for (std::set<std::string>::const_iterator it =
           this->Target->GetSystemIncludeDirectories().begin();
         it != this->Target->GetSystemIncludeDirectories().end(); ++it) {
869
      cmGeneratorExpression ge;
870
871
872
873
874
      cmSystemTools::ExpandListArgument(
        ge.Parse(*it)->Evaluate(this->LocalGenerator, config, false, this,
                                &dagChecker),
        result);
    }
875

876
    std::vector<cmGeneratorTarget const*> const& deps =
877
      this->GetLinkImplementationClosure(config);
878
879
880
881
    for (std::vector<cmGeneratorTarget const *>::const_iterator
           li = deps.begin(),
           le = deps.end();
         li != le; ++li) {
882
      handleSystemIncludesDep(this->LocalGenerator, *li, config, this,
883
                              &dagChecker, result, excludeImported);
884
    }
885

886
887
888
889
    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());
890

891
892
    IncludeCacheType::value_type entry(config_upper, result);
    iter = this->SystemIncludesCache.insert(entry).first;
893
  }
894

Stephen Kelly's avatar
Stephen Kelly committed
895
  return std::binary_search(iter->second.begin(), iter->second.end(), dir);
896
897
}

898
bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
899
900
901
902
{
  return this->Target->GetPropertyAsBool(prop);
}

903
904
905
906
907
static void AddInterfaceEntries(
  cmGeneratorTarget const* thisTarget, std::string const& config,
  std::string const& prop,
  std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
{
908
909
  if (cmLinkImplementationLibraries const* impl =
        thisTarget->GetLinkImplementationLibraries(config)) {
910
    for (std::vector<cmLinkImplItem>::const_iterator
911
912
913
914
915
           it = impl->Libraries.begin(),
           end = impl->Libraries.end();
         it != end; ++it) {
      if (it->Target) {
        std::string genex = "$<TARGET_PROPERTY:"