Imported Upstream version 3.18.2
[platform/upstream/cmake.git] / Source / cmGeneratorTarget.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmGeneratorTarget.h"
4
5 #include <algorithm>
6 #include <cassert>
7 #include <cerrno>
8 #include <cstddef>
9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 #include <iterator>
13 #include <queue>
14 #include <sstream>
15 #include <unordered_set>
16 #include <utility>
17
18 #include <cm/memory>
19 #include <cm/string_view>
20 #include <cmext/algorithm>
21 #include <cmext/string_view>
22
23 #include "cmsys/RegularExpression.hxx"
24
25 #include "cmAlgorithms.h"
26 #include "cmComputeLinkInformation.h"
27 #include "cmCustomCommand.h"
28 #include "cmCustomCommandGenerator.h"
29 #include "cmCustomCommandLines.h"
30 #include "cmFileTimes.h"
31 #include "cmGeneratedFileStream.h"
32 #include "cmGeneratorExpression.h"
33 #include "cmGeneratorExpressionContext.h"
34 #include "cmGeneratorExpressionDAGChecker.h"
35 #include "cmGeneratorExpressionNode.h"
36 #include "cmGlobalGenerator.h"
37 #include "cmLocalGenerator.h"
38 #include "cmMakefile.h"
39 #include "cmMessageType.h"
40 #include "cmOutputConverter.h"
41 #include "cmPropertyMap.h"
42 #include "cmRange.h"
43 #include "cmSourceFile.h"
44 #include "cmSourceFileLocation.h"
45 #include "cmSourceFileLocationKind.h"
46 #include "cmState.h"
47 #include "cmStringAlgorithms.h"
48 #include "cmSystemTools.h"
49 #include "cmTarget.h"
50 #include "cmTargetLinkLibraryType.h"
51 #include "cmTargetPropertyComputer.h"
52 #include "cmake.h"
53
54 class cmMessenger;
55
56 template <>
57 cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
58   cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
59   cmListFileBacktrace const& /* context */)
60 {
61   return &tgt->GetSourcesProperty();
62 }
63
64 template <>
65 const std::string&
66 cmTargetPropertyComputer::ComputeLocationForBuild<cmGeneratorTarget>(
67   cmGeneratorTarget const* tgt)
68 {
69   return tgt->GetLocation("");
70 }
71
72 template <>
73 const std::string&
74 cmTargetPropertyComputer::ComputeLocation<cmGeneratorTarget>(
75   cmGeneratorTarget const* tgt, const std::string& config)
76 {
77   return tgt->GetLocation(config);
78 }
79
80 class cmGeneratorTarget::TargetPropertyEntry
81 {
82 protected:
83   static cmLinkImplItem NoLinkImplItem;
84
85 public:
86   TargetPropertyEntry(cmLinkImplItem const& item)
87     : LinkImplItem(item)
88   {
89   }
90   virtual ~TargetPropertyEntry() = default;
91
92   virtual const std::string& Evaluate(
93     cmLocalGenerator* lg, const std::string& config,
94     cmGeneratorTarget const* headTarget,
95     cmGeneratorExpressionDAGChecker* dagChecker,
96     std::string const& language) const = 0;
97
98   virtual cmListFileBacktrace GetBacktrace() const = 0;
99   virtual std::string const& GetInput() const = 0;
100   virtual bool GetHadContextSensitiveCondition() const { return false; }
101
102   cmLinkImplItem const& LinkImplItem;
103 };
104 cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
105
106 class TargetPropertyEntryGenex : public cmGeneratorTarget::TargetPropertyEntry
107 {
108 public:
109   TargetPropertyEntryGenex(std::unique_ptr<cmCompiledGeneratorExpression> cge,
110                            cmLinkImplItem const& item = NoLinkImplItem)
111     : cmGeneratorTarget::TargetPropertyEntry(item)
112     , ge(std::move(cge))
113   {
114   }
115
116   const std::string& Evaluate(cmLocalGenerator* lg, const std::string& config,
117                               cmGeneratorTarget const* headTarget,
118                               cmGeneratorExpressionDAGChecker* dagChecker,
119                               std::string const& language) const override
120   {
121     return this->ge->Evaluate(lg, config, headTarget, dagChecker, nullptr,
122                               language);
123   }
124
125   cmListFileBacktrace GetBacktrace() const override
126   {
127     return this->ge->GetBacktrace();
128   }
129
130   std::string const& GetInput() const override { return this->ge->GetInput(); }
131
132   bool GetHadContextSensitiveCondition() const override
133   {
134     return this->ge->GetHadContextSensitiveCondition();
135   }
136
137 private:
138   const std::unique_ptr<cmCompiledGeneratorExpression> ge;
139 };
140
141 class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry
142 {
143 public:
144   TargetPropertyEntryString(std::string propertyValue,
145                             cmListFileBacktrace backtrace,
146                             cmLinkImplItem const& item = NoLinkImplItem)
147     : cmGeneratorTarget::TargetPropertyEntry(item)
148     , PropertyValue(std::move(propertyValue))
149     , Backtrace(std::move(backtrace))
150   {
151   }
152
153   const std::string& Evaluate(cmLocalGenerator*, const std::string&,
154                               cmGeneratorTarget const*,
155                               cmGeneratorExpressionDAGChecker*,
156                               std::string const&) const override
157   {
158     return this->PropertyValue;
159   }
160
161   cmListFileBacktrace GetBacktrace() const override { return this->Backtrace; }
162   std::string const& GetInput() const override { return this->PropertyValue; }
163
164 private:
165   std::string PropertyValue;
166   cmListFileBacktrace Backtrace;
167 };
168
169 std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>
170 CreateTargetPropertyEntry(
171   const std::string& propertyValue,
172   cmListFileBacktrace backtrace = cmListFileBacktrace(),
173   bool evaluateForBuildsystem = false)
174 {
175   if (cmGeneratorExpression::Find(propertyValue) != std::string::npos) {
176     cmGeneratorExpression ge(std::move(backtrace));
177     std::unique_ptr<cmCompiledGeneratorExpression> cge =
178       ge.Parse(propertyValue);
179     cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
180     return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>(
181       cm::make_unique<TargetPropertyEntryGenex>(std::move(cge)));
182   }
183
184   return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>(
185     cm::make_unique<TargetPropertyEntryString>(propertyValue,
186                                                std::move(backtrace)));
187 }
188
189 void CreatePropertyGeneratorExpressions(
190   cmStringRange entries, cmBacktraceRange backtraces,
191   std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items,
192   bool evaluateForBuildsystem = false)
193 {
194   auto btIt = backtraces.begin();
195   for (auto it = entries.begin(); it != entries.end(); ++it, ++btIt) {
196     items.push_back(
197       CreateTargetPropertyEntry(*it, *btIt, evaluateForBuildsystem));
198   }
199 }
200
201 namespace {
202 // Represent a target property entry after evaluating generator expressions
203 // and splitting up lists.
204 struct EvaluatedTargetPropertyEntry
205 {
206   EvaluatedTargetPropertyEntry(cmLinkImplItem const& item,
207                                cmListFileBacktrace bt)
208     : LinkImplItem(item)
209     , Backtrace(std::move(bt))
210   {
211   }
212
213   // Move-only.
214   EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry&&) = default;
215   EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry const&) = delete;
216   EvaluatedTargetPropertyEntry& operator=(EvaluatedTargetPropertyEntry&&) =
217     delete;
218   EvaluatedTargetPropertyEntry& operator=(
219     EvaluatedTargetPropertyEntry const&) = delete;
220
221   cmLinkImplItem const& LinkImplItem;
222   cmListFileBacktrace Backtrace;
223   std::vector<std::string> Values;
224   bool ContextDependent = false;
225 };
226
227 EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
228   cmGeneratorTarget const* thisTarget, std::string const& config,
229   std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
230   cmGeneratorTarget::TargetPropertyEntry& entry)
231 {
232   EvaluatedTargetPropertyEntry ee(entry.LinkImplItem, entry.GetBacktrace());
233   cmExpandList(entry.Evaluate(thisTarget->GetLocalGenerator(), config,
234                               thisTarget, dagChecker, lang),
235                ee.Values);
236   if (entry.GetHadContextSensitiveCondition()) {
237     ee.ContextDependent = true;
238   }
239   return ee;
240 }
241
242 struct EvaluatedTargetPropertyEntries
243 {
244   std::vector<EvaluatedTargetPropertyEntry> Entries;
245   bool HadContextSensitiveCondition = false;
246 };
247
248 EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
249   cmGeneratorTarget const* thisTarget, std::string const& config,
250   std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
251   std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
252     in)
253 {
254   EvaluatedTargetPropertyEntries out;
255   out.Entries.reserve(in.size());
256   for (auto& entry : in) {
257     out.Entries.emplace_back(EvaluateTargetPropertyEntry(
258       thisTarget, config, lang, dagChecker, *entry));
259   }
260   return out;
261 }
262 }
263
264 cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
265   : Target(t)
266   , FortranModuleDirectoryCreated(false)
267   , SourceFileFlagsConstructed(false)
268   , PolicyWarnedCMP0022(false)
269   , PolicyReportedCMP0069(false)
270   , DebugIncludesDone(false)
271   , DebugCompileOptionsDone(false)
272   , DebugCompileFeaturesDone(false)
273   , DebugCompileDefinitionsDone(false)
274   , DebugLinkOptionsDone(false)
275   , DebugLinkDirectoriesDone(false)
276   , DebugPrecompileHeadersDone(false)
277   , DebugSourcesDone(false)
278   , LinkImplementationLanguageIsContextDependent(true)
279   , UtilityItemsDone(false)
280 {
281   this->Makefile = this->Target->GetMakefile();
282   this->LocalGenerator = lg;
283   this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
284
285   this->GlobalGenerator->ComputeTargetObjectDirectory(this);
286
287   CreatePropertyGeneratorExpressions(t->GetIncludeDirectoriesEntries(),
288                                      t->GetIncludeDirectoriesBacktraces(),
289                                      this->IncludeDirectoriesEntries);
290
291   CreatePropertyGeneratorExpressions(t->GetCompileOptionsEntries(),
292                                      t->GetCompileOptionsBacktraces(),
293                                      this->CompileOptionsEntries);
294
295   CreatePropertyGeneratorExpressions(t->GetCompileFeaturesEntries(),
296                                      t->GetCompileFeaturesBacktraces(),
297                                      this->CompileFeaturesEntries);
298
299   CreatePropertyGeneratorExpressions(t->GetCompileDefinitionsEntries(),
300                                      t->GetCompileDefinitionsBacktraces(),
301                                      this->CompileDefinitionsEntries);
302
303   CreatePropertyGeneratorExpressions(t->GetLinkOptionsEntries(),
304                                      t->GetLinkOptionsBacktraces(),
305                                      this->LinkOptionsEntries);
306
307   CreatePropertyGeneratorExpressions(t->GetLinkDirectoriesEntries(),
308                                      t->GetLinkDirectoriesBacktraces(),
309                                      this->LinkDirectoriesEntries);
310
311   CreatePropertyGeneratorExpressions(t->GetPrecompileHeadersEntries(),
312                                      t->GetPrecompileHeadersBacktraces(),
313                                      this->PrecompileHeadersEntries);
314
315   CreatePropertyGeneratorExpressions(t->GetSourceEntries(),
316                                      t->GetSourceBacktraces(),
317                                      this->SourceEntries, true);
318
319   this->PolicyMap = t->GetPolicyMap();
320
321   // Get hard-coded linker language
322   if (this->Target->GetProperty("HAS_CXX")) {
323     this->LinkerLanguage = "CXX";
324   } else {
325     this->LinkerLanguage = this->Target->GetSafeProperty("LINKER_LANGUAGE");
326   }
327 }
328
329 cmGeneratorTarget::~cmGeneratorTarget() = default;
330
331 const std::string& cmGeneratorTarget::GetSourcesProperty() const
332 {
333   std::vector<std::string> values;
334   for (auto& se : this->SourceEntries) {
335     values.push_back(se->GetInput());
336   }
337   static std::string value;
338   value.clear();
339   value = cmJoin(values, ";");
340   return value;
341 }
342
343 cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const
344 {
345   return this->GetLocalGenerator()->GetGlobalGenerator();
346 }
347
348 cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const
349 {
350   return this->LocalGenerator;
351 }
352
353 cmStateEnums::TargetType cmGeneratorTarget::GetType() const
354 {
355   return this->Target->GetType();
356 }
357
358 const std::string& cmGeneratorTarget::GetName() const
359 {
360   return this->Target->GetName();
361 }
362
363 std::string cmGeneratorTarget::GetExportName() const
364 {
365   cmProp exportName = this->GetProperty("EXPORT_NAME");
366
367   if (exportName && !exportName->empty()) {
368     if (!cmGeneratorExpression::IsValidTargetName(*exportName)) {
369       std::ostringstream e;
370       e << "EXPORT_NAME property \"" << *exportName << "\" for \""
371         << this->GetName() << "\": is not valid.";
372       cmSystemTools::Error(e.str());
373       return "";
374     }
375     return *exportName;
376   }
377   return this->GetName();
378 }
379
380 cmProp cmGeneratorTarget::GetProperty(const std::string& prop) const
381 {
382   if (!cmTargetPropertyComputer::PassesWhitelist(
383         this->GetType(), prop, this->Makefile->GetMessenger(),
384         this->GetBacktrace())) {
385     return nullptr;
386   }
387   if (cmProp result = cmTargetPropertyComputer::GetProperty(
388         this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) {
389     return result;
390   }
391   if (cmSystemTools::GetFatalErrorOccured()) {
392     return nullptr;
393   }
394   return this->Target->GetProperty(prop);
395 }
396
397 std::string const& cmGeneratorTarget::GetSafeProperty(
398   std::string const& prop) const
399 {
400   cmProp ret = this->GetProperty(prop);
401   if (ret) {
402     return *ret;
403   }
404
405   static std::string const s_empty;
406   return s_empty;
407 }
408
409 const char* cmGeneratorTarget::GetOutputTargetType(
410   cmStateEnums::ArtifactType artifact) const
411 {
412   switch (this->GetType()) {
413     case cmStateEnums::SHARED_LIBRARY:
414       if (this->IsDLLPlatform()) {
415         switch (artifact) {
416           case cmStateEnums::RuntimeBinaryArtifact:
417             // A DLL shared library is treated as a runtime target.
418             return "RUNTIME";
419           case cmStateEnums::ImportLibraryArtifact:
420             // A DLL import library is treated as an archive target.
421             return "ARCHIVE";
422         }
423       } else {
424         // For non-DLL platforms shared libraries are treated as
425         // library targets.
426         return "LIBRARY";
427       }
428       break;
429     case cmStateEnums::STATIC_LIBRARY:
430       // Static libraries are always treated as archive targets.
431       return "ARCHIVE";
432     case cmStateEnums::MODULE_LIBRARY:
433       switch (artifact) {
434         case cmStateEnums::RuntimeBinaryArtifact:
435           // Module libraries are always treated as library targets.
436           return "LIBRARY";
437         case cmStateEnums::ImportLibraryArtifact:
438           // Module import libraries are treated as archive targets.
439           return "ARCHIVE";
440       }
441       break;
442     case cmStateEnums::OBJECT_LIBRARY:
443       // Object libraries are always treated as object targets.
444       return "OBJECT";
445     case cmStateEnums::EXECUTABLE:
446       switch (artifact) {
447         case cmStateEnums::RuntimeBinaryArtifact:
448           // Executables are always treated as runtime targets.
449           return "RUNTIME";
450         case cmStateEnums::ImportLibraryArtifact:
451           // Executable import libraries are treated as archive targets.
452           return "ARCHIVE";
453       }
454       break;
455     default:
456       break;
457   }
458   return "";
459 }
460
461 std::string cmGeneratorTarget::GetOutputName(
462   const std::string& config, cmStateEnums::ArtifactType artifact) const
463 {
464   // Lookup/compute/cache the output name for this configuration.
465   OutputNameKey key(config, artifact);
466   auto i = this->OutputNameMap.find(key);
467   if (i == this->OutputNameMap.end()) {
468     // Add empty name in map to detect potential recursion.
469     OutputNameMapType::value_type entry(key, "");
470     i = this->OutputNameMap.insert(entry).first;
471
472     // Compute output name.
473     std::vector<std::string> props;
474     std::string type = this->GetOutputTargetType(artifact);
475     std::string configUpper = cmSystemTools::UpperCase(config);
476     if (!type.empty() && !configUpper.empty()) {
477       // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
478       props.push_back(type + "_OUTPUT_NAME_" + configUpper);
479     }
480     if (!type.empty()) {
481       // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME
482       props.push_back(type + "_OUTPUT_NAME");
483     }
484     if (!configUpper.empty()) {
485       // OUTPUT_NAME_<CONFIG>
486       props.push_back("OUTPUT_NAME_" + configUpper);
487       // <CONFIG>_OUTPUT_NAME
488       props.push_back(configUpper + "_OUTPUT_NAME");
489     }
490     // OUTPUT_NAME
491     props.emplace_back("OUTPUT_NAME");
492
493     std::string outName;
494     for (std::string const& p : props) {
495       if (cmProp outNameProp = this->GetProperty(p)) {
496         outName = *outNameProp;
497         break;
498       }
499     }
500
501     if (outName.empty()) {
502       outName = this->GetName();
503     }
504
505     // Now evaluate genex and update the previously-prepared map entry.
506     i->second =
507       cmGeneratorExpression::Evaluate(outName, this->LocalGenerator, config);
508   } else if (i->second.empty()) {
509     // An empty map entry indicates we have been called recursively
510     // from the above block.
511     this->LocalGenerator->GetCMakeInstance()->IssueMessage(
512       MessageType::FATAL_ERROR,
513       "Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.",
514       this->GetBacktrace());
515   }
516   return i->second;
517 }
518
519 std::string cmGeneratorTarget::GetFilePrefix(
520   const std::string& config, cmStateEnums::ArtifactType artifact) const
521 {
522   if (this->IsImported()) {
523     const char* prefix = this->GetFilePrefixInternal(config, artifact);
524
525     return prefix ? prefix : std::string();
526   }
527
528   std::string prefix;
529   std::string suffix;
530   std::string base;
531   this->GetFullNameInternal(config, artifact, prefix, base, suffix);
532   return prefix;
533 }
534 std::string cmGeneratorTarget::GetFileSuffix(
535   const std::string& config, cmStateEnums::ArtifactType artifact) const
536 {
537   if (this->IsImported()) {
538     const char* suffix = this->GetFileSuffixInternal(config, artifact);
539
540     return suffix ? suffix : std::string();
541   }
542
543   std::string prefix;
544   std::string suffix;
545   std::string base;
546   this->GetFullNameInternal(config, artifact, prefix, base, suffix);
547   return suffix;
548 }
549
550 std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const
551 {
552   cmProp postfix = nullptr;
553   std::string frameworkPostfix;
554   if (!config.empty()) {
555     std::string configProp =
556       cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
557     postfix = this->GetProperty(configProp);
558
559     // Mac application bundles and frameworks have no regular postfix like
560     // libraries do.
561     if (!this->IsImported() && postfix &&
562         (this->IsAppBundleOnApple() || this->IsFrameworkOnApple())) {
563       postfix = nullptr;
564     }
565
566     // Frameworks created by multi config generators can have a special
567     // framework postfix.
568     frameworkPostfix = GetFrameworkMultiConfigPostfix(config);
569     if (!frameworkPostfix.empty()) {
570       postfix = &frameworkPostfix;
571     }
572   }
573   return postfix ? *postfix : std::string();
574 }
575
576 std::string cmGeneratorTarget::GetFrameworkMultiConfigPostfix(
577   const std::string& config) const
578 {
579   cmProp postfix = nullptr;
580   if (!config.empty()) {
581     std::string configProp = cmStrCat("FRAMEWORK_MULTI_CONFIG_POSTFIX_",
582                                       cmSystemTools::UpperCase(config));
583     postfix = this->GetProperty(configProp);
584
585     if (!this->IsImported() && postfix &&
586         (this->IsFrameworkOnApple() &&
587          !GetGlobalGenerator()->IsMultiConfig())) {
588       postfix = nullptr;
589     }
590   }
591   return postfix ? *postfix : std::string();
592 }
593
594 const char* cmGeneratorTarget::GetFilePrefixInternal(
595   std::string const& config, cmStateEnums::ArtifactType artifact,
596   const std::string& language) const
597 {
598   // no prefix for non-main target types.
599   if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
600       this->GetType() != cmStateEnums::SHARED_LIBRARY &&
601       this->GetType() != cmStateEnums::MODULE_LIBRARY &&
602       this->GetType() != cmStateEnums::EXECUTABLE) {
603     return nullptr;
604   }
605
606   const bool isImportedLibraryArtifact =
607     (artifact == cmStateEnums::ImportLibraryArtifact);
608
609   // Return an empty prefix for the import library if this platform
610   // does not support import libraries.
611   if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) {
612     return nullptr;
613   }
614
615   // The implib option is only allowed for shared libraries, module
616   // libraries, and executables.
617   if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
618       this->GetType() != cmStateEnums::MODULE_LIBRARY &&
619       this->GetType() != cmStateEnums::EXECUTABLE) {
620     artifact = cmStateEnums::RuntimeBinaryArtifact;
621   }
622
623   // Compute prefix value.
624   cmProp targetPrefix =
625     (isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX")
626                                : this->GetProperty("PREFIX"));
627
628   if (!targetPrefix) {
629     const char* prefixVar = this->Target->GetPrefixVariableInternal(artifact);
630     if (!language.empty() && prefixVar && *prefixVar) {
631       std::string langPrefix = prefixVar + std::string("_") + language;
632       targetPrefix = this->Makefile->GetDef(langPrefix);
633     }
634
635     // if there is no prefix on the target nor specific language
636     // use the cmake definition.
637     if (!targetPrefix && prefixVar) {
638       targetPrefix = this->Makefile->GetDef(prefixVar);
639     }
640   }
641
642   return targetPrefix ? targetPrefix->c_str() : nullptr;
643 }
644 const char* cmGeneratorTarget::GetFileSuffixInternal(
645   std::string const& config, cmStateEnums::ArtifactType artifact,
646   const std::string& language) const
647 {
648   // no suffix for non-main target types.
649   if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
650       this->GetType() != cmStateEnums::SHARED_LIBRARY &&
651       this->GetType() != cmStateEnums::MODULE_LIBRARY &&
652       this->GetType() != cmStateEnums::EXECUTABLE) {
653     return nullptr;
654   }
655
656   const bool isImportedLibraryArtifact =
657     (artifact == cmStateEnums::ImportLibraryArtifact);
658
659   // Return an empty suffix for the import library if this platform
660   // does not support import libraries.
661   if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) {
662     return nullptr;
663   }
664
665   // The implib option is only allowed for shared libraries, module
666   // libraries, and executables.
667   if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
668       this->GetType() != cmStateEnums::MODULE_LIBRARY &&
669       this->GetType() != cmStateEnums::EXECUTABLE) {
670     artifact = cmStateEnums::RuntimeBinaryArtifact;
671   }
672
673   // Compute suffix value.
674   cmProp targetSuffix =
675     (isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX")
676                                : this->GetProperty("SUFFIX"));
677
678   if (!targetSuffix) {
679     const char* suffixVar = this->Target->GetSuffixVariableInternal(artifact);
680     if (!language.empty() && suffixVar && *suffixVar) {
681       std::string langSuffix = suffixVar + std::string("_") + language;
682       targetSuffix = this->Makefile->GetDef(langSuffix);
683     }
684
685     // if there is no suffix on the target nor specific language
686     // use the cmake definition.
687     if (!targetSuffix && suffixVar) {
688       targetSuffix = this->Makefile->GetDef(suffixVar);
689     }
690   }
691
692   return targetSuffix ? targetSuffix->c_str() : nullptr;
693 }
694
695 void cmGeneratorTarget::ClearSourcesCache()
696 {
697   this->AllConfigSources.clear();
698   this->KindedSourcesMap.clear();
699   this->LinkImplementationLanguageIsContextDependent = true;
700   this->Objects.clear();
701   this->VisitedConfigsForObjects.clear();
702 }
703
704 void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before)
705 {
706   this->SourceEntries.insert(
707     before ? this->SourceEntries.begin() : this->SourceEntries.end(),
708     CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true));
709   this->ClearSourcesCache();
710 }
711
712 void cmGeneratorTarget::AddSource(const std::string& src, bool before)
713 {
714   this->Target->AddSource(src, before);
715   this->AddSourceCommon(src, before);
716 }
717
718 void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs)
719 {
720   this->Target->AddTracedSources(srcs);
721   if (!srcs.empty()) {
722     this->AddSourceCommon(cmJoin(srcs, ";"));
723   }
724 }
725
726 void cmGeneratorTarget::AddIncludeDirectory(const std::string& src,
727                                             bool before)
728 {
729   this->Target->InsertInclude(src, this->Makefile->GetBacktrace(), before);
730   this->IncludeDirectoriesEntries.insert(
731     before ? this->IncludeDirectoriesEntries.begin()
732            : this->IncludeDirectoriesEntries.end(),
733     CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true));
734 }
735
736 std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(
737   cmSourceFile const* sf) const
738 {
739   auto i = this->SourceDepends.find(sf);
740   if (i != this->SourceDepends.end()) {
741     return &i->second.Depends;
742   }
743   return nullptr;
744 }
745
746 namespace {
747 void handleSystemIncludesDep(cmLocalGenerator* lg,
748                              cmGeneratorTarget const* depTgt,
749                              const std::string& config,
750                              cmGeneratorTarget const* headTarget,
751                              cmGeneratorExpressionDAGChecker* dagChecker,
752                              std::vector<std::string>& result,
753                              bool excludeImported, std::string const& language)
754 {
755   if (cmProp dirs =
756         depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) {
757     cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget,
758                                                  dagChecker, depTgt, language),
759                  result);
760   }
761   if (!depTgt->IsImported() || excludeImported) {
762     return;
763   }
764
765   if (cmProp dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
766     cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget,
767                                                  dagChecker, depTgt, language),
768                  result);
769   }
770 }
771 }
772
773 /* clang-format off */
774 #define IMPLEMENT_VISIT(KIND)                                                 \
775   do {                                                                        \
776     KindedSources const& kinded = this->GetKindedSources(config);             \
777     for (SourceAndKind const& s : kinded.Sources) {                           \
778       if (s.Kind == KIND) {                                                   \
779         data.push_back(s.Source.Value);                                       \
780       }                                                                       \
781     }                                                                         \
782   } while (false)
783 /* clang-format on */
784
785 void cmGeneratorTarget::GetObjectSources(
786   std::vector<cmSourceFile const*>& data, const std::string& config) const
787 {
788   IMPLEMENT_VISIT(SourceKindObjectSource);
789
790   if (this->VisitedConfigsForObjects.count(config)) {
791     return;
792   }
793
794   for (cmSourceFile const* it : data) {
795     this->Objects[it];
796   }
797
798   this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
799   this->VisitedConfigsForObjects.insert(config);
800 }
801
802 void cmGeneratorTarget::ComputeObjectMapping()
803 {
804   auto const& configs = this->Makefile->GetGeneratorConfigs();
805   std::set<std::string> configSet(configs.begin(), configs.end());
806   if (configSet == this->VisitedConfigsForObjects) {
807     return;
808   }
809
810   for (std::string const& c : configs) {
811     std::vector<cmSourceFile const*> sourceFiles;
812     this->GetObjectSources(sourceFiles, c);
813   }
814 }
815
816 const char* cmGeneratorTarget::GetFeature(const std::string& feature,
817                                           const std::string& config) const
818 {
819   if (!config.empty()) {
820     std::string featureConfig =
821       cmStrCat(feature, '_', cmSystemTools::UpperCase(config));
822     if (cmProp value = this->GetProperty(featureConfig)) {
823       return value->c_str();
824     }
825   }
826   if (cmProp value = this->GetProperty(feature)) {
827     return value->c_str();
828   }
829   return this->LocalGenerator->GetFeature(feature, config);
830 }
831
832 const char* cmGeneratorTarget::GetLinkPIEProperty(
833   const std::string& config) const
834 {
835   static std::string PICValue;
836
837   PICValue = this->GetLinkInterfaceDependentStringAsBoolProperty(
838     "POSITION_INDEPENDENT_CODE", config);
839
840   if (PICValue == "(unset)") {
841     // POSITION_INDEPENDENT_CODE is not set
842     return nullptr;
843   }
844
845   auto status = this->GetPolicyStatusCMP0083();
846   return (status != cmPolicies::WARN && status != cmPolicies::OLD)
847     ? PICValue.c_str()
848     : nullptr;
849 }
850
851 bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
852                                      std::string const& config) const
853 {
854   const char* feature = "INTERPROCEDURAL_OPTIMIZATION";
855   const bool result = cmIsOn(this->GetFeature(feature, config));
856
857   if (!result) {
858     // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies
859     return false;
860   }
861
862   if (lang != "C" && lang != "CXX" && lang != "Fortran") {
863     // We do not define IPO behavior for other languages.
864     return false;
865   }
866
867   cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069();
868
869   if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) {
870     if (this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_LEGACY_BEHAVIOR")) {
871       return true;
872     }
873     if (this->PolicyReportedCMP0069) {
874       // problem is already reported, no need to issue a message
875       return false;
876     }
877     const bool in_try_compile =
878       this->LocalGenerator->GetCMakeInstance()->GetIsInTryCompile();
879     if (cmp0069 == cmPolicies::WARN && !in_try_compile) {
880       std::ostringstream w;
881       w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0069) << "\n";
882       w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target "
883         << "'" << this->GetName() << "'.";
884       this->LocalGenerator->GetCMakeInstance()->IssueMessage(
885         MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace());
886
887       this->PolicyReportedCMP0069 = true;
888     }
889     return false;
890   }
891
892   // Note: check consistency with messages from CheckIPOSupported
893   const char* message = nullptr;
894   if (!this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_SUPPORTED_BY_CMAKE")) {
895     message = "CMake doesn't support IPO for current compiler";
896   } else if (!this->Makefile->IsOn("_CMAKE_" + lang +
897                                    "_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) {
898     message = "Compiler doesn't support IPO";
899   } else if (!this->GlobalGenerator->IsIPOSupported()) {
900     message = "CMake doesn't support IPO for current generator";
901   }
902
903   if (!message) {
904     // No error/warning messages
905     return true;
906   }
907
908   if (this->PolicyReportedCMP0069) {
909     // problem is already reported, no need to issue a message
910     return false;
911   }
912
913   this->PolicyReportedCMP0069 = true;
914
915   this->LocalGenerator->GetCMakeInstance()->IssueMessage(
916     MessageType::FATAL_ERROR, message, this->GetBacktrace());
917   return false;
918 }
919
920 const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
921 {
922   this->ComputeObjectMapping();
923   return this->Objects[file];
924 }
925
926 const char* cmGeneratorTarget::GetCustomObjectExtension() const
927 {
928   static std::string extension;
929   const bool has_ptx_extension =
930     this->GetPropertyAsBool("CUDA_PTX_COMPILATION");
931   if (has_ptx_extension) {
932     extension = ".ptx";
933     return extension.c_str();
934   }
935   return nullptr;
936 }
937
938 void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
939 {
940   this->ExplicitObjectName.insert(sf);
941 }
942
943 bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
944 {
945   const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
946   auto it = this->ExplicitObjectName.find(file);
947   return it != this->ExplicitObjectName.end();
948 }
949
950 void cmGeneratorTarget::GetModuleDefinitionSources(
951   std::vector<cmSourceFile const*>& data, const std::string& config) const
952 {
953   IMPLEMENT_VISIT(SourceKindModuleDefinition);
954 }
955
956 void cmGeneratorTarget::GetHeaderSources(
957   std::vector<cmSourceFile const*>& data, const std::string& config) const
958 {
959   IMPLEMENT_VISIT(SourceKindHeader);
960 }
961
962 void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile const*>& data,
963                                         const std::string& config) const
964 {
965   IMPLEMENT_VISIT(SourceKindExtra);
966 }
967
968 void cmGeneratorTarget::GetCustomCommands(
969   std::vector<cmSourceFile const*>& data, const std::string& config) const
970 {
971   IMPLEMENT_VISIT(SourceKindCustomCommand);
972 }
973
974 void cmGeneratorTarget::GetExternalObjects(
975   std::vector<cmSourceFile const*>& data, const std::string& config) const
976 {
977   IMPLEMENT_VISIT(SourceKindExternalObject);
978 }
979
980 void cmGeneratorTarget::GetManifests(std::vector<cmSourceFile const*>& data,
981                                      const std::string& config) const
982 {
983   IMPLEMENT_VISIT(SourceKindManifest);
984 }
985
986 std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
987 {
988   if (!this->UtilityItemsDone) {
989     this->UtilityItemsDone = true;
990     std::set<BT<std::pair<std::string, bool>>> const& utilities =
991       this->GetUtilities();
992     for (BT<std::pair<std::string, bool>> const& i : utilities) {
993       if (cmGeneratorTarget* gt =
994             this->LocalGenerator->FindGeneratorTargetToUse(i.Value.first)) {
995         this->UtilityItems.insert(cmLinkItem(gt, i.Value.second, i.Backtrace));
996       } else {
997         this->UtilityItems.insert(
998           cmLinkItem(i.Value.first, i.Value.second, i.Backtrace));
999       }
1000     }
1001   }
1002   return this->UtilityItems;
1003 }
1004
1005 const std::string& cmGeneratorTarget::GetLocation(
1006   const std::string& config) const
1007 {
1008   static std::string location;
1009   if (this->IsImported()) {
1010     location = this->Target->ImportedGetFullPath(
1011       config, cmStateEnums::RuntimeBinaryArtifact);
1012   } else {
1013     location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
1014   }
1015   return location;
1016 }
1017
1018 std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreBuildCommands()
1019   const
1020 {
1021   return this->Target->GetPreBuildCommands();
1022 }
1023
1024 std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreLinkCommands()
1025   const
1026 {
1027   return this->Target->GetPreLinkCommands();
1028 }
1029
1030 std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPostBuildCommands()
1031   const
1032 {
1033   return this->Target->GetPostBuildCommands();
1034 }
1035
1036 bool cmGeneratorTarget::IsImported() const
1037 {
1038   return this->Target->IsImported();
1039 }
1040
1041 bool cmGeneratorTarget::IsImportedGloballyVisible() const
1042 {
1043   return this->Target->IsImportedGloballyVisible();
1044 }
1045
1046 const std::string& cmGeneratorTarget::GetLocationForBuild() const
1047 {
1048   static std::string location;
1049   if (this->IsImported()) {
1050     location = this->Target->ImportedGetFullPath(
1051       "", cmStateEnums::RuntimeBinaryArtifact);
1052     return location;
1053   }
1054
1055   // Now handle the deprecated build-time configuration location.
1056   std::string const noConfig;
1057   location = this->GetDirectory(noConfig);
1058   const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
1059   if (cfgid && strcmp(cfgid, ".") != 0) {
1060     location += "/";
1061     location += cfgid;
1062   }
1063
1064   if (this->IsAppBundleOnApple()) {
1065     std::string macdir = this->BuildBundleDirectory("", "", FullLevel);
1066     if (!macdir.empty()) {
1067       location += "/";
1068       location += macdir;
1069     }
1070   }
1071   location += "/";
1072   location += this->GetFullName("", cmStateEnums::RuntimeBinaryArtifact);
1073   return location;
1074 }
1075
1076 bool cmGeneratorTarget::IsSystemIncludeDirectory(
1077   const std::string& dir, const std::string& config,
1078   const std::string& language) const
1079 {
1080   assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
1081   std::string config_upper;
1082   if (!config.empty()) {
1083     config_upper = cmSystemTools::UpperCase(config);
1084   }
1085
1086   using IncludeCacheType = std::map<std::string, std::vector<std::string>>;
1087   auto iter = this->SystemIncludesCache.find(config_upper);
1088
1089   if (iter == this->SystemIncludesCache.end()) {
1090     cmGeneratorExpressionDAGChecker dagChecker(
1091       this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
1092
1093     bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
1094
1095     std::vector<std::string> result;
1096     for (std::string const& it : this->Target->GetSystemIncludeDirectories()) {
1097       cmExpandList(cmGeneratorExpression::Evaluate(it, this->LocalGenerator,
1098                                                    config, this, &dagChecker,
1099                                                    nullptr, language),
1100                    result);
1101     }
1102
1103     std::vector<cmGeneratorTarget const*> const& deps =
1104       this->GetLinkImplementationClosure(config);
1105     for (cmGeneratorTarget const* dep : deps) {
1106       handleSystemIncludesDep(this->LocalGenerator, dep, config, this,
1107                               &dagChecker, result, excludeImported, language);
1108     }
1109
1110     std::for_each(result.begin(), result.end(),
1111                   cmSystemTools::ConvertToUnixSlashes);
1112     std::sort(result.begin(), result.end());
1113     result.erase(std::unique(result.begin(), result.end()), result.end());
1114
1115     IncludeCacheType::value_type entry(config_upper, result);
1116     iter = this->SystemIncludesCache.insert(entry).first;
1117   }
1118
1119   return std::binary_search(iter->second.begin(), iter->second.end(), dir);
1120 }
1121
1122 bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
1123 {
1124   return this->Target->GetPropertyAsBool(prop);
1125 }
1126
1127 bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
1128   std::string const& prop, cmGeneratorExpressionContext* context,
1129   bool usage_requirements_only) const
1130 {
1131   std::string const key = prop + '@' + context->Config;
1132   auto i = this->MaybeInterfacePropertyExists.find(key);
1133   if (i == this->MaybeInterfacePropertyExists.end()) {
1134     // Insert an entry now in case there is a cycle.
1135     i = this->MaybeInterfacePropertyExists.emplace(key, false).first;
1136     bool& maybeInterfaceProp = i->second;
1137
1138     // If this target itself has a non-empty property value, we are done.
1139     cmProp p = this->GetProperty(prop);
1140     maybeInterfaceProp = p && !p->empty();
1141
1142     // Otherwise, recurse to interface dependencies.
1143     if (!maybeInterfaceProp) {
1144       cmGeneratorTarget const* headTarget =
1145         context->HeadTarget ? context->HeadTarget : this;
1146       if (cmLinkInterfaceLibraries const* iface =
1147             this->GetLinkInterfaceLibraries(context->Config, headTarget,
1148                                             usage_requirements_only)) {
1149         if (iface->HadHeadSensitiveCondition) {
1150           // With a different head target we may get to a library with
1151           // this interface property.
1152           maybeInterfaceProp = true;
1153         } else {
1154           // The transitive interface libraries do not depend on the
1155           // head target, so we can follow them.
1156           for (cmLinkItem const& lib : iface->Libraries) {
1157             if (lib.Target &&
1158                 lib.Target->MaybeHaveInterfaceProperty(
1159                   prop, context, usage_requirements_only)) {
1160               maybeInterfaceProp = true;
1161               break;
1162             }
1163           }
1164         }
1165       }
1166     }
1167   }
1168   return i->second;
1169 }
1170
1171 std::string cmGeneratorTarget::EvaluateInterfaceProperty(
1172   std::string const& prop, cmGeneratorExpressionContext* context,
1173   cmGeneratorExpressionDAGChecker* dagCheckerParent,
1174   bool usage_requirements_only) const
1175 {
1176   std::string result;
1177
1178   // If the property does not appear transitively at all, we are done.
1179   if (!this->MaybeHaveInterfaceProperty(prop, context,
1180                                         usage_requirements_only)) {
1181     return result;
1182   }
1183
1184   // Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled.  This is
1185   // a subset of TargetPropertyNode::Evaluate without stringify/parse steps
1186   // but sufficient for transitive interface properties.
1187   cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop,
1188                                              nullptr, dagCheckerParent);
1189   switch (dagChecker.Check()) {
1190     case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
1191       dagChecker.ReportError(
1192         context, "$<TARGET_PROPERTY:" + this->GetName() + "," + prop + ">");
1193       return result;
1194     case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
1195       // No error. We just skip cyclic references.
1196     case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
1197       // No error. We have already seen this transitive property.
1198       return result;
1199     case cmGeneratorExpressionDAGChecker::DAG:
1200       break;
1201   }
1202
1203   cmGeneratorTarget const* headTarget =
1204     context->HeadTarget ? context->HeadTarget : this;
1205
1206   if (cmProp p = this->GetProperty(prop)) {
1207     result = cmGeneratorExpressionNode::EvaluateDependentExpression(
1208       *p, context->LG, context, headTarget, &dagChecker, this);
1209   }
1210
1211   if (cmLinkInterfaceLibraries const* iface = this->GetLinkInterfaceLibraries(
1212         context->Config, headTarget, usage_requirements_only)) {
1213     context->HadContextSensitiveCondition =
1214       context->HadContextSensitiveCondition ||
1215       iface->HadContextSensitiveCondition;
1216     for (cmLinkItem const& lib : iface->Libraries) {
1217       // Broken code can have a target in its own link interface.
1218       // Don't follow such link interface entries so as not to create a
1219       // self-referencing loop.
1220       if (lib.Target && lib.Target != this) {
1221         // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in the
1222         // above property and hand-evaluate it as if it were compiled.
1223         // Create a context as cmCompiledGeneratorExpression::Evaluate does.
1224         cmGeneratorExpressionContext libContext(
1225           context->LG, context->Config, context->Quiet, headTarget, this,
1226           context->EvaluateForBuildsystem, context->Backtrace,
1227           context->Language);
1228         std::string libResult = cmGeneratorExpression::StripEmptyListElements(
1229           lib.Target->EvaluateInterfaceProperty(prop, &libContext, &dagChecker,
1230                                                 usage_requirements_only));
1231         if (!libResult.empty()) {
1232           if (result.empty()) {
1233             result = std::move(libResult);
1234           } else {
1235             result.reserve(result.size() + 1 + libResult.size());
1236             result += ";";
1237             result += libResult;
1238           }
1239         }
1240         context->HadContextSensitiveCondition =
1241           context->HadContextSensitiveCondition ||
1242           libContext.HadContextSensitiveCondition;
1243         context->HadHeadSensitiveCondition =
1244           context->HadHeadSensitiveCondition ||
1245           libContext.HadHeadSensitiveCondition;
1246       }
1247     }
1248   }
1249
1250   return result;
1251 }
1252
1253 namespace {
1254 std::string AddSwiftInterfaceIncludeDirectories(
1255   const cmGeneratorTarget* root, const cmGeneratorTarget* target,
1256   const std::string& config, cmGeneratorExpressionDAGChecker* context)
1257 {
1258   cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target,
1259                                        "Swift_MODULE_DIRECTORY", nullptr,
1260                                        context };
1261   switch (dag.Check()) {
1262     case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
1263       dag.ReportError(nullptr,
1264                       "$<TARGET_PROPERTY:" + target->GetName() +
1265                         ",Swift_MODULE_DIRECTORY>");
1266       CM_FALLTHROUGH;
1267     case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
1268       // No error. We just skip cyclic references.
1269     case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
1270       // No error. We have already seen this transitive property.
1271       return "";
1272     case cmGeneratorExpressionDAGChecker::DAG:
1273       break;
1274   }
1275
1276   std::string directories;
1277   if (const auto* interface =
1278         target->GetLinkInterfaceLibraries(config, root, true)) {
1279     for (const cmLinkItem& library : interface->Libraries) {
1280       if (const cmGeneratorTarget* dependency = library.Target) {
1281         if (cm::contains(dependency->GetAllConfigCompileLanguages(),
1282                          "Swift")) {
1283           std::string value =
1284             dependency->GetSafeProperty("Swift_MODULE_DIRECTORY");
1285           if (value.empty()) {
1286             value =
1287               dependency->GetLocalGenerator()->GetCurrentBinaryDirectory();
1288           }
1289
1290           if (!directories.empty()) {
1291             directories += ";";
1292           }
1293           directories += value;
1294         }
1295       }
1296     }
1297   }
1298   return directories;
1299 }
1300
1301 void AddSwiftImplicitIncludeDirectories(
1302   const cmGeneratorTarget* target, const std::string& config,
1303   EvaluatedTargetPropertyEntries& entries)
1304 {
1305   if (const auto* libraries = target->GetLinkImplementationLibraries(config)) {
1306     cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target,
1307                                          "Swift_MODULE_DIRECTORY", nullptr,
1308                                          nullptr };
1309
1310     for (const cmLinkImplItem& library : libraries->Libraries) {
1311       if (const cmGeneratorTarget* dependency = library.Target) {
1312         if (dependency->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
1313           continue;
1314         }
1315         if (cm::contains(dependency->GetAllConfigCompileLanguages(),
1316                          "Swift")) {
1317           EvaluatedTargetPropertyEntry entry{ library, library.Backtrace };
1318
1319           if (cmProp val = dependency->GetProperty("Swift_MODULE_DIRECTORY")) {
1320             entry.Values.emplace_back(*val);
1321           } else {
1322             entry.Values.emplace_back(
1323               dependency->GetLocalGenerator()->GetCurrentBinaryDirectory());
1324           }
1325
1326           cmExpandList(AddSwiftInterfaceIncludeDirectories(target, dependency,
1327                                                            config, &dag),
1328                        entry.Values);
1329
1330           entries.Entries.emplace_back(std::move(entry));
1331         }
1332       }
1333     }
1334   }
1335 }
1336
1337 void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
1338                          std::string const& config, std::string const& prop,
1339                          std::string const& lang,
1340                          cmGeneratorExpressionDAGChecker* dagChecker,
1341                          EvaluatedTargetPropertyEntries& entries,
1342                          bool usage_requirements_only = true)
1343 {
1344   if (cmLinkImplementationLibraries const* impl =
1345         headTarget->GetLinkImplementationLibraries(config)) {
1346     entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
1347     for (cmLinkImplItem const& lib : impl->Libraries) {
1348       if (lib.Target) {
1349         EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
1350         // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
1351         // caller's property and hand-evaluate it as if it were compiled.
1352         // Create a context as cmCompiledGeneratorExpression::Evaluate does.
1353         cmGeneratorExpressionContext context(
1354           headTarget->GetLocalGenerator(), config, false, headTarget,
1355           headTarget, true, lib.Backtrace, lang);
1356         cmExpandList(lib.Target->EvaluateInterfaceProperty(
1357                        prop, &context, dagChecker, usage_requirements_only),
1358                      ee.Values);
1359         ee.ContextDependent = context.HadContextSensitiveCondition;
1360         entries.Entries.emplace_back(std::move(ee));
1361       }
1362     }
1363   }
1364 }
1365
1366 void AddObjectEntries(cmGeneratorTarget const* headTarget,
1367                       std::string const& config,
1368                       cmGeneratorExpressionDAGChecker* dagChecker,
1369                       EvaluatedTargetPropertyEntries& entries)
1370 {
1371   if (cmLinkImplementationLibraries const* impl =
1372         headTarget->GetLinkImplementationLibraries(config)) {
1373     entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
1374     for (cmLinkImplItem const& lib : impl->Libraries) {
1375       if (lib.Target &&
1376           lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
1377         std::string uniqueName =
1378           headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
1379             lib.Target);
1380         std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">";
1381         cmGeneratorExpression ge(lib.Backtrace);
1382         std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
1383         cge->SetEvaluateForBuildsystem(true);
1384
1385         EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
1386         cmExpandList(cge->Evaluate(headTarget->GetLocalGenerator(), config,
1387                                    headTarget, dagChecker),
1388                      ee.Values);
1389         if (cge->GetHadContextSensitiveCondition()) {
1390           ee.ContextDependent = true;
1391         }
1392         entries.Entries.emplace_back(std::move(ee));
1393       }
1394     }
1395   }
1396 }
1397
1398 bool processSources(cmGeneratorTarget const* tgt,
1399                     EvaluatedTargetPropertyEntries& entries,
1400                     std::vector<BT<std::string>>& srcs,
1401                     std::unordered_set<std::string>& uniqueSrcs,
1402                     bool debugSources)
1403 {
1404   cmMakefile* mf = tgt->Target->GetMakefile();
1405
1406   bool contextDependent = entries.HadContextSensitiveCondition;
1407
1408   for (EvaluatedTargetPropertyEntry& entry : entries.Entries) {
1409     if (entry.ContextDependent) {
1410       contextDependent = true;
1411     }
1412
1413     cmLinkImplItem const& item = entry.LinkImplItem;
1414     std::string const& targetName = item.AsStr();
1415
1416     for (std::string& src : entry.Values) {
1417       cmSourceFile* sf = mf->GetOrCreateSource(src);
1418       std::string e;
1419       std::string fullPath = sf->ResolveFullPath(&e);
1420       if (fullPath.empty()) {
1421         if (!e.empty()) {
1422           cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
1423           cm->IssueMessage(MessageType::FATAL_ERROR, e, tgt->GetBacktrace());
1424         }
1425         return contextDependent;
1426       }
1427
1428       if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src)) {
1429         std::ostringstream err;
1430         if (!targetName.empty()) {
1431           err << "Target \"" << targetName
1432               << "\" contains relative path in its INTERFACE_SOURCES:\n  \""
1433               << src << "\"";
1434         } else {
1435           err << "Found relative path while evaluating sources of \""
1436               << tgt->GetName() << "\":\n  \"" << src << "\"\n";
1437         }
1438         tgt->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
1439                                                err.str());
1440         return contextDependent;
1441       }
1442       src = fullPath;
1443     }
1444     std::string usedSources;
1445     for (std::string const& src : entry.Values) {
1446       if (uniqueSrcs.insert(src).second) {
1447         srcs.emplace_back(src, entry.Backtrace);
1448         if (debugSources) {
1449           usedSources += " * " + src + "\n";
1450         }
1451       }
1452     }
1453     if (!usedSources.empty()) {
1454       tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
1455         MessageType::LOG,
1456         std::string("Used sources for target ") + tgt->GetName() + ":\n" +
1457           usedSources,
1458         entry.Backtrace);
1459     }
1460   }
1461   return contextDependent;
1462 }
1463 }
1464
1465 std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
1466   std::string const& config) const
1467 {
1468   std::vector<BT<std::string>> files;
1469   assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
1470
1471   if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
1472     // At configure-time, this method can be called as part of getting the
1473     // LOCATION property or to export() a file to be include()d.  However
1474     // there is no cmGeneratorTarget at configure-time, so search the SOURCES
1475     // for TARGET_OBJECTS instead for backwards compatibility with OLD
1476     // behavior of CMP0024 and CMP0026 only.
1477
1478     cmStringRange sourceEntries = this->Target->GetSourceEntries();
1479     for (std::string const& entry : sourceEntries) {
1480       std::vector<std::string> items = cmExpandedList(entry);
1481       for (std::string const& item : items) {
1482         if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") &&
1483             item.back() == '>') {
1484           continue;
1485         }
1486         files.emplace_back(item);
1487       }
1488     }
1489     return files;
1490   }
1491
1492   std::vector<std::string> debugProperties;
1493   this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES",
1494                                    debugProperties);
1495
1496   bool debugSources =
1497     !this->DebugSourcesDone && cm::contains(debugProperties, "SOURCES");
1498
1499   if (this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
1500     this->DebugSourcesDone = true;
1501   }
1502
1503   cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr,
1504                                              nullptr);
1505
1506   EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
1507     this, config, std::string(), &dagChecker, this->SourceEntries);
1508
1509   std::unordered_set<std::string> uniqueSrcs;
1510   bool contextDependentDirectSources =
1511     processSources(this, entries, files, uniqueSrcs, debugSources);
1512
1513   // Collect INTERFACE_SOURCES of all direct link-dependencies.
1514   EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
1515   AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(),
1516                       &dagChecker, linkInterfaceSourcesEntries);
1517   std::vector<std::string>::size_type numFilesBefore = files.size();
1518   bool contextDependentInterfaceSources = processSources(
1519     this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources);
1520
1521   // Collect TARGET_OBJECTS of direct object link-dependencies.
1522   bool contextDependentObjects = false;
1523   std::vector<std::string>::size_type numFilesBefore2 = files.size();
1524   if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
1525     EvaluatedTargetPropertyEntries linkObjectsEntries;
1526     AddObjectEntries(this, config, &dagChecker, linkObjectsEntries);
1527     contextDependentObjects = processSources(this, linkObjectsEntries, files,
1528                                              uniqueSrcs, debugSources);
1529   }
1530
1531   if (!contextDependentDirectSources &&
1532       !(contextDependentInterfaceSources && numFilesBefore < files.size()) &&
1533       !(contextDependentObjects && numFilesBefore2 < files.size())) {
1534     this->LinkImplementationLanguageIsContextDependent = false;
1535   }
1536
1537   return files;
1538 }
1539
1540 void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
1541                                        const std::string& config) const
1542 {
1543   std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config);
1544   files.reserve(tmp.size());
1545   for (BT<cmSourceFile*>& v : tmp) {
1546     files.push_back(v.Value);
1547   }
1548 }
1549
1550 std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles(
1551   std::string const& config) const
1552 {
1553   std::vector<BT<cmSourceFile*>> files;
1554   if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
1555     // Since we are still configuring not all sources may exist yet,
1556     // so we need to avoid full source classification because that
1557     // requires the absolute paths to all sources to be determined.
1558     // Since this is only for compatibility with old policies that
1559     // projects should not depend on anymore, just compute the files
1560     // without memoizing them.
1561     std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
1562     std::set<cmSourceFile*> emitted;
1563     for (BT<std::string> const& s : srcs) {
1564       cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
1565       if (emitted.insert(sf).second) {
1566         files.emplace_back(sf, s.Backtrace);
1567       }
1568     }
1569     return files;
1570   }
1571
1572   KindedSources const& kinded = this->GetKindedSources(config);
1573   files.reserve(kinded.Sources.size());
1574   for (SourceAndKind const& si : kinded.Sources) {
1575     files.push_back(si.Source);
1576   }
1577   return files;
1578 }
1579
1580 void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
1581   std::vector<cmSourceFile*>& files, const std::string& config) const
1582 {
1583   std::vector<BT<cmSourceFile*>> tmp =
1584     this->GetSourceFilesWithoutObjectLibraries(config);
1585   files.reserve(tmp.size());
1586   for (BT<cmSourceFile*>& v : tmp) {
1587     files.push_back(v.Value);
1588   }
1589 }
1590
1591 std::vector<BT<cmSourceFile*>>
1592 cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
1593   std::string const& config) const
1594 {
1595   std::vector<BT<cmSourceFile*>> files;
1596   KindedSources const& kinded = this->GetKindedSources(config);
1597   files.reserve(kinded.Sources.size());
1598   for (SourceAndKind const& si : kinded.Sources) {
1599     if (si.Source.Value->GetObjectLibrary().empty()) {
1600       files.push_back(si.Source);
1601     }
1602   }
1603   return files;
1604 }
1605
1606 cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
1607   std::string const& config) const
1608 {
1609   // If we already processed one configuration and found no dependenc
1610   // on configuration then always use the one result.
1611   if (!this->LinkImplementationLanguageIsContextDependent) {
1612     return this->KindedSourcesMap.begin()->second;
1613   }
1614
1615   // Lookup any existing link implementation for this configuration.
1616   std::string const key = cmSystemTools::UpperCase(config);
1617   auto it = this->KindedSourcesMap.find(key);
1618   if (it != this->KindedSourcesMap.end()) {
1619     if (!it->second.Initialized) {
1620       std::ostringstream e;
1621       e << "The SOURCES of \"" << this->GetName()
1622         << "\" use a generator expression that depends on the "
1623            "SOURCES themselves.";
1624       this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
1625         MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
1626       static KindedSources empty;
1627       return empty;
1628     }
1629     return it->second;
1630   }
1631
1632   // Add an entry to the map for this configuration.
1633   KindedSources& files = this->KindedSourcesMap[key];
1634   this->ComputeKindedSources(files, config);
1635   files.Initialized = true;
1636   return files;
1637 }
1638
1639 void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
1640                                              std::string const& config) const
1641 {
1642   // Get the source file paths by string.
1643   std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
1644
1645   cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
1646   std::vector<cmSourceFile*> badObjLib;
1647
1648   std::set<cmSourceFile*> emitted;
1649   for (BT<std::string> const& s : srcs) {
1650     // Create each source at most once.
1651     cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
1652     if (!emitted.insert(sf).second) {
1653       continue;
1654     }
1655
1656     // Compute the kind (classification) of this source file.
1657     SourceKind kind;
1658     std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
1659     if (sf->GetCustomCommand()) {
1660       kind = SourceKindCustomCommand;
1661       // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
1662       // NOLINTNEXTLINE(bugprone-branch-clone)
1663     } else if (this->Target->GetType() == cmStateEnums::UTILITY) {
1664       kind = SourceKindExtra;
1665     } else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
1666       kind = SourceKindUnityBatched;
1667       // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
1668       // NOLINTNEXTLINE(bugprone-branch-clone)
1669     } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
1670       kind = SourceKindHeader;
1671     } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
1672       kind = SourceKindExternalObject;
1673     } else if (!sf->GetOrDetermineLanguage().empty()) {
1674       kind = SourceKindObjectSource;
1675     } else if (ext == "def") {
1676       kind = SourceKindModuleDefinition;
1677       if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
1678         badObjLib.push_back(sf);
1679       }
1680     } else if (ext == "idl") {
1681       kind = SourceKindIDL;
1682       if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
1683         badObjLib.push_back(sf);
1684       }
1685     } else if (ext == "resx") {
1686       kind = SourceKindResx;
1687     } else if (ext == "appxmanifest") {
1688       kind = SourceKindAppManifest;
1689     } else if (ext == "manifest") {
1690       kind = SourceKindManifest;
1691     } else if (ext == "pfx") {
1692       kind = SourceKindCertificate;
1693     } else if (ext == "xaml") {
1694       kind = SourceKindXaml;
1695     } else if (header_regex.find(sf->ResolveFullPath())) {
1696       kind = SourceKindHeader;
1697     } else {
1698       kind = SourceKindExtra;
1699     }
1700
1701     // Save this classified source file in the result vector.
1702     files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind });
1703   }
1704
1705   if (!badObjLib.empty()) {
1706     std::ostringstream e;
1707     e << "OBJECT library \"" << this->GetName() << "\" contains:\n";
1708     for (cmSourceFile* i : badObjLib) {
1709       e << "  " << i->GetLocation().GetName() << "\n";
1710     }
1711     e << "but may contain only sources that compile, header files, and "
1712          "other files that would not affect linking of a normal library.";
1713     this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
1714       MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
1715   }
1716 }
1717
1718 std::vector<cmGeneratorTarget::AllConfigSource> const&
1719 cmGeneratorTarget::GetAllConfigSources() const
1720 {
1721   if (this->AllConfigSources.empty()) {
1722     this->ComputeAllConfigSources();
1723   }
1724   return this->AllConfigSources;
1725 }
1726
1727 void cmGeneratorTarget::ComputeAllConfigSources() const
1728 {
1729   std::vector<std::string> configs;
1730   this->Makefile->GetConfigurations(configs);
1731
1732   std::map<cmSourceFile const*, size_t> index;
1733
1734   for (size_t ci = 0; ci < configs.size(); ++ci) {
1735     KindedSources const& sources = this->GetKindedSources(configs[ci]);
1736     for (SourceAndKind const& src : sources.Sources) {
1737       auto mi = index.find(src.Source.Value);
1738       if (mi == index.end()) {
1739         AllConfigSource acs;
1740         acs.Source = src.Source.Value;
1741         acs.Kind = src.Kind;
1742         this->AllConfigSources.push_back(std::move(acs));
1743         std::map<cmSourceFile const*, size_t>::value_type entry(
1744           src.Source.Value, this->AllConfigSources.size() - 1);
1745         mi = index.insert(entry).first;
1746       }
1747       this->AllConfigSources[mi->second].Configs.push_back(ci);
1748     }
1749   }
1750 }
1751
1752 std::vector<cmGeneratorTarget::AllConfigSource>
1753 cmGeneratorTarget::GetAllConfigSources(SourceKind kind) const
1754 {
1755   std::vector<AllConfigSource> result;
1756   for (AllConfigSource const& source : this->GetAllConfigSources()) {
1757     if (source.Kind == kind) {
1758       result.push_back(source);
1759     }
1760   }
1761   return result;
1762 }
1763
1764 std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const
1765 {
1766   std::set<std::string> languages;
1767   std::vector<AllConfigSource> const& sources = this->GetAllConfigSources();
1768   for (AllConfigSource const& si : sources) {
1769     std::string const& lang = si.Source->GetOrDetermineLanguage();
1770     if (!lang.empty()) {
1771       languages.emplace(lang);
1772     }
1773   }
1774   return languages;
1775 }
1776
1777 std::string cmGeneratorTarget::GetCompilePDBName(
1778   const std::string& config) const
1779 {
1780   std::string prefix;
1781   std::string base;
1782   std::string suffix;
1783   this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
1784                             prefix, base, suffix);
1785
1786   // Check for a per-configuration output directory target property.
1787   std::string configUpper = cmSystemTools::UpperCase(config);
1788   std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper);
1789   cmProp config_name = this->GetProperty(configProp);
1790   if (config_name && !config_name->empty()) {
1791     return prefix + *config_name + ".pdb";
1792   }
1793
1794   cmProp name = this->GetProperty("COMPILE_PDB_NAME");
1795   if (name && !name->empty()) {
1796     return prefix + *name + ".pdb";
1797   }
1798
1799   return "";
1800 }
1801
1802 std::string cmGeneratorTarget::GetCompilePDBPath(
1803   const std::string& config) const
1804 {
1805   std::string dir = this->GetCompilePDBDirectory(config);
1806   std::string name = this->GetCompilePDBName(config);
1807   if (dir.empty() && !name.empty() && this->HaveWellDefinedOutputFiles()) {
1808     dir = this->GetPDBDirectory(config);
1809   }
1810   if (!dir.empty()) {
1811     dir += "/";
1812   }
1813   return dir + name;
1814 }
1815
1816 bool cmGeneratorTarget::HasSOName(const std::string& config) const
1817 {
1818   // soname is supported only for shared libraries and modules,
1819   // and then only when the platform supports an soname flag.
1820   return ((this->GetType() == cmStateEnums::SHARED_LIBRARY) &&
1821           !this->GetPropertyAsBool("NO_SONAME") &&
1822           this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config)));
1823 }
1824
1825 bool cmGeneratorTarget::NeedRelinkBeforeInstall(
1826   const std::string& config) const
1827 {
1828   // Only executables and shared libraries can have an rpath and may
1829   // need relinking.
1830   if (this->GetType() != cmStateEnums::EXECUTABLE &&
1831       this->GetType() != cmStateEnums::SHARED_LIBRARY &&
1832       this->GetType() != cmStateEnums::MODULE_LIBRARY) {
1833     return false;
1834   }
1835
1836   // If there is no install location this target will not be installed
1837   // and therefore does not need relinking.
1838   if (!this->Target->GetHaveInstallRule()) {
1839     return false;
1840   }
1841
1842   // If skipping all rpaths completely then no relinking is needed.
1843   if (this->Makefile->IsOn("CMAKE_SKIP_RPATH")) {
1844     return false;
1845   }
1846
1847   // If building with the install-tree rpath no relinking is needed.
1848   if (this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) {
1849     return false;
1850   }
1851
1852   // If chrpath is going to be used no relinking is needed.
1853   if (this->IsChrpathUsed(config)) {
1854     return false;
1855   }
1856
1857   // Check for rpath support on this platform.
1858   std::string ll = this->GetLinkerLanguage(config);
1859   if (!ll.empty()) {
1860     std::string flagVar =
1861       cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG");
1862     if (!this->Makefile->IsSet(flagVar)) {
1863       // There is no rpath support on this platform so nothing needs
1864       // relinking.
1865       return false;
1866     }
1867   } else {
1868     // No linker language is known.  This error will be reported by
1869     // other code.
1870     return false;
1871   }
1872
1873   // If either a build or install tree rpath is set then the rpath
1874   // will likely change between the build tree and install tree and
1875   // this target must be relinked.
1876   bool have_rpath =
1877     this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(config);
1878   bool is_ninja =
1879     this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja";
1880
1881   if (have_rpath && is_ninja) {
1882     std::ostringstream w;
1883     /* clang-format off */
1884     w <<
1885       "The install of the " << this->GetName() << " target requires "
1886       "changing an RPATH from the build tree, but this is not supported "
1887       "with the Ninja generator unless on an ELF-based platform.  The "
1888       "CMAKE_BUILD_WITH_INSTALL_RPATH variable may be set to avoid this "
1889       "relinking step."
1890       ;
1891     /* clang-format on */
1892
1893     cmake* cm = this->LocalGenerator->GetCMakeInstance();
1894     cm->IssueMessage(MessageType::FATAL_ERROR, w.str(), this->GetBacktrace());
1895   }
1896
1897   return have_rpath;
1898 }
1899
1900 bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
1901 {
1902   // Only certain target types have an rpath.
1903   if (!(this->GetType() == cmStateEnums::SHARED_LIBRARY ||
1904         this->GetType() == cmStateEnums::MODULE_LIBRARY ||
1905         this->GetType() == cmStateEnums::EXECUTABLE)) {
1906     return false;
1907   }
1908
1909   // If the target will not be installed we do not need to change its
1910   // rpath.
1911   if (!this->Target->GetHaveInstallRule()) {
1912     return false;
1913   }
1914
1915   // Skip chrpath if skipping rpath altogether.
1916   if (this->Makefile->IsOn("CMAKE_SKIP_RPATH")) {
1917     return false;
1918   }
1919
1920   // Skip chrpath if it does not need to be changed at install time.
1921   if (this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) {
1922     return false;
1923   }
1924
1925   // Allow the user to disable builtin chrpath explicitly.
1926   if (this->Makefile->IsOn("CMAKE_NO_BUILTIN_CHRPATH")) {
1927     return false;
1928   }
1929
1930   if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
1931     return true;
1932   }
1933
1934 #if defined(CMAKE_USE_ELF_PARSER)
1935   // Enable if the rpath flag uses a separator and the target uses ELF
1936   // binaries.
1937   std::string ll = this->GetLinkerLanguage(config);
1938   if (!ll.empty()) {
1939     std::string sepVar =
1940       cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP");
1941     const char* sep = this->Makefile->GetDefinition(sepVar);
1942     if (sep && *sep) {
1943       // TODO: Add ELF check to ABI detection and get rid of
1944       // CMAKE_EXECUTABLE_FORMAT.
1945       if (const char* fmt =
1946             this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) {
1947         return strcmp(fmt, "ELF") == 0;
1948       }
1949     }
1950   }
1951 #endif
1952   static_cast<void>(config);
1953   return false;
1954 }
1955
1956 bool cmGeneratorTarget::IsImportedSharedLibWithoutSOName(
1957   const std::string& config) const
1958 {
1959   if (this->IsImported() && this->GetType() == cmStateEnums::SHARED_LIBRARY) {
1960     if (cmGeneratorTarget::ImportInfo const* info =
1961           this->GetImportInfo(config)) {
1962       return info->NoSOName;
1963     }
1964   }
1965   return false;
1966 }
1967
1968 bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir(
1969   const std::string& config) const
1970 {
1971   bool install_name_is_rpath = false;
1972   bool macosx_rpath = false;
1973
1974   if (!this->IsImported()) {
1975     if (this->GetType() != cmStateEnums::SHARED_LIBRARY) {
1976       return false;
1977     }
1978     cmProp install_name = this->GetProperty("INSTALL_NAME_DIR");
1979     bool use_install_name = this->MacOSXUseInstallNameDir();
1980     if (install_name && use_install_name && *install_name == "@rpath") {
1981       install_name_is_rpath = true;
1982     } else if (install_name && use_install_name) {
1983       return false;
1984     }
1985     if (!install_name_is_rpath) {
1986       macosx_rpath = this->MacOSXRpathInstallNameDirDefault();
1987     }
1988   } else {
1989     // Lookup the imported soname.
1990     if (cmGeneratorTarget::ImportInfo const* info =
1991           this->GetImportInfo(config)) {
1992       if (!info->NoSOName && !info->SOName.empty()) {
1993         if (cmHasLiteralPrefix(info->SOName, "@rpath/")) {
1994           install_name_is_rpath = true;
1995         }
1996       } else {
1997         std::string install_name;
1998         cmSystemTools::GuessLibraryInstallName(info->Location, install_name);
1999         if (install_name.find("@rpath") != std::string::npos) {
2000           install_name_is_rpath = true;
2001         }
2002       }
2003     }
2004   }
2005
2006   if (!install_name_is_rpath && !macosx_rpath) {
2007     return false;
2008   }
2009
2010   if (!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG")) {
2011     std::ostringstream w;
2012     w << "Attempting to use ";
2013     if (macosx_rpath) {
2014       w << "MACOSX_RPATH";
2015     } else {
2016       w << "@rpath";
2017     }
2018     w << " without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being set.";
2019     w << "  This could be because you are using a Mac OS X version";
2020     w << " less than 10.5 or because CMake's platform configuration is";
2021     w << " corrupt.";
2022     cmake* cm = this->LocalGenerator->GetCMakeInstance();
2023     cm->IssueMessage(MessageType::FATAL_ERROR, w.str(), this->GetBacktrace());
2024   }
2025
2026   return true;
2027 }
2028
2029 bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const
2030 {
2031   // we can't do rpaths when unsupported
2032   if (!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG")) {
2033     return false;
2034   }
2035
2036   cmProp macosx_rpath_str = this->GetProperty("MACOSX_RPATH");
2037   if (macosx_rpath_str) {
2038     return this->GetPropertyAsBool("MACOSX_RPATH");
2039   }
2040
2041   cmPolicies::PolicyStatus cmp0042 = this->GetPolicyStatusCMP0042();
2042
2043   if (cmp0042 == cmPolicies::WARN) {
2044     this->LocalGenerator->GetGlobalGenerator()->AddCMP0042WarnTarget(
2045       this->GetName());
2046   }
2047
2048   return cmp0042 == cmPolicies::NEW;
2049 }
2050
2051 bool cmGeneratorTarget::MacOSXUseInstallNameDir() const
2052 {
2053   cmProp build_with_install_name =
2054     this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR");
2055   if (build_with_install_name) {
2056     return cmIsOn(*build_with_install_name);
2057   }
2058
2059   cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
2060   if (cmp0068 == cmPolicies::NEW) {
2061     return false;
2062   }
2063
2064   bool use_install_name = this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
2065
2066   if (use_install_name && cmp0068 == cmPolicies::WARN) {
2067     this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
2068       this->GetName());
2069   }
2070
2071   return use_install_name;
2072 }
2073
2074 bool cmGeneratorTarget::CanGenerateInstallNameDir(
2075   InstallNameType name_type) const
2076 {
2077   cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
2078
2079   if (cmp0068 == cmPolicies::NEW) {
2080     return true;
2081   }
2082
2083   bool skip = this->Makefile->IsOn("CMAKE_SKIP_RPATH");
2084   if (name_type == INSTALL_NAME_FOR_INSTALL) {
2085     skip |= this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
2086   } else {
2087     skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH");
2088   }
2089
2090   if (skip && cmp0068 == cmPolicies::WARN) {
2091     this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
2092       this->GetName());
2093   }
2094
2095   return !skip;
2096 }
2097
2098 std::string cmGeneratorTarget::GetSOName(const std::string& config) const
2099 {
2100   if (this->IsImported()) {
2101     // Lookup the imported soname.
2102     if (cmGeneratorTarget::ImportInfo const* info =
2103           this->GetImportInfo(config)) {
2104       if (info->NoSOName) {
2105         // The imported library has no builtin soname so the name
2106         // searched at runtime will be just the filename.
2107         return cmSystemTools::GetFilenameName(info->Location);
2108       }
2109       // Use the soname given if any.
2110       if (cmHasLiteralPrefix(info->SOName, "@rpath/")) {
2111         return info->SOName.substr(6);
2112       }
2113       return info->SOName;
2114     }
2115     return "";
2116   }
2117   // Compute the soname that will be built.
2118   return this->GetLibraryNames(config).SharedObject;
2119 }
2120
2121 namespace {
2122 bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level)
2123 {
2124   return level == cmGeneratorTarget::FullLevel;
2125 }
2126
2127 bool shouldAddContentLevel(cmGeneratorTarget::BundleDirectoryLevel level)
2128 {
2129   return level == cmGeneratorTarget::ContentLevel || shouldAddFullLevel(level);
2130 }
2131 }
2132
2133 std::string cmGeneratorTarget::GetAppBundleDirectory(
2134   const std::string& config, BundleDirectoryLevel level) const
2135 {
2136   std::string fpath = cmStrCat(
2137     this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
2138   cmProp ext = this->GetProperty("BUNDLE_EXTENSION");
2139   fpath += (ext ? *ext : "app");
2140   if (shouldAddContentLevel(level) &&
2141       !this->Makefile->PlatformIsAppleEmbedded()) {
2142     fpath += "/Contents";
2143     if (shouldAddFullLevel(level)) {
2144       fpath += "/MacOS";
2145     }
2146   }
2147   return fpath;
2148 }
2149
2150 bool cmGeneratorTarget::IsBundleOnApple() const
2151 {
2152   return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
2153     this->IsCFBundleOnApple();
2154 }
2155
2156 std::string cmGeneratorTarget::GetCFBundleDirectory(
2157   const std::string& config, BundleDirectoryLevel level) const
2158 {
2159   std::string fpath = cmStrCat(
2160     this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
2161   std::string ext;
2162   if (cmProp p = this->GetProperty("BUNDLE_EXTENSION")) {
2163     ext = *p;
2164   } else {
2165     if (this->IsXCTestOnApple()) {
2166       ext = "xctest";
2167     } else {
2168       ext = "bundle";
2169     }
2170   }
2171   fpath += ext;
2172   if (shouldAddContentLevel(level) &&
2173       !this->Makefile->PlatformIsAppleEmbedded()) {
2174     fpath += "/Contents";
2175     if (shouldAddFullLevel(level)) {
2176       fpath += "/MacOS";
2177     }
2178   }
2179   return fpath;
2180 }
2181
2182 std::string cmGeneratorTarget::GetFrameworkDirectory(
2183   const std::string& config, BundleDirectoryLevel level) const
2184 {
2185   std::string fpath = cmStrCat(
2186     this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
2187   cmProp ext = this->GetProperty("BUNDLE_EXTENSION");
2188   fpath += (ext ? *ext : "framework");
2189   if (shouldAddFullLevel(level) &&
2190       !this->Makefile->PlatformIsAppleEmbedded()) {
2191     fpath += "/Versions/";
2192     fpath += this->GetFrameworkVersion();
2193   }
2194   return fpath;
2195 }
2196
2197 std::string cmGeneratorTarget::GetFullName(
2198   const std::string& config, cmStateEnums::ArtifactType artifact) const
2199 {
2200   if (this->IsImported()) {
2201     return this->GetFullNameImported(config, artifact);
2202   }
2203   return this->GetFullNameInternal(config, artifact);
2204 }
2205
2206 std::string cmGeneratorTarget::GetInstallNameDirForBuildTree(
2207   const std::string& config) const
2208 {
2209   if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
2210
2211     // If building directly for installation then the build tree install_name
2212     // is the same as the install tree.
2213     if (this->MacOSXUseInstallNameDir()) {
2214       std::string installPrefix =
2215         this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
2216       return this->GetInstallNameDirForInstallTree(config, installPrefix);
2217     }
2218
2219     // Use the build tree directory for the target.
2220     if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_BUILD)) {
2221       std::string dir;
2222       if (this->MacOSXRpathInstallNameDirDefault()) {
2223         dir = "@rpath";
2224       } else {
2225         dir = this->GetDirectory(config);
2226       }
2227       dir += "/";
2228       return dir;
2229     }
2230   }
2231   return "";
2232 }
2233
2234 std::string cmGeneratorTarget::GetInstallNameDirForInstallTree(
2235   const std::string& config, const std::string& installPrefix) const
2236 {
2237   if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
2238     std::string dir;
2239     cmProp install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
2240
2241     if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
2242       if (install_name_dir && !install_name_dir->empty()) {
2243         dir = *install_name_dir;
2244         cmGeneratorExpression::ReplaceInstallPrefix(dir, installPrefix);
2245         dir =
2246           cmGeneratorExpression::Evaluate(dir, this->LocalGenerator, config);
2247         if (!dir.empty()) {
2248           dir = cmStrCat(dir, '/');
2249         }
2250       }
2251     }
2252     if (!install_name_dir) {
2253       if (this->MacOSXRpathInstallNameDirDefault()) {
2254         dir = "@rpath/";
2255       }
2256     }
2257     return dir;
2258   }
2259   return "";
2260 }
2261
2262 cmListFileBacktrace cmGeneratorTarget::GetBacktrace() const
2263 {
2264   return this->Target->GetBacktrace();
2265 }
2266
2267 const std::set<BT<std::pair<std::string, bool>>>&
2268 cmGeneratorTarget::GetUtilities() const
2269 {
2270   return this->Target->GetUtilities();
2271 }
2272
2273 bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const
2274 {
2275   return this->GetType() == cmStateEnums::STATIC_LIBRARY ||
2276     this->GetType() == cmStateEnums::SHARED_LIBRARY ||
2277     this->GetType() == cmStateEnums::MODULE_LIBRARY ||
2278     this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
2279     this->GetType() == cmStateEnums::EXECUTABLE;
2280 }
2281
2282 const std::string* cmGeneratorTarget::GetExportMacro() const
2283 {
2284   // Define the symbol for targets that export symbols.
2285   if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
2286       this->GetType() == cmStateEnums::MODULE_LIBRARY ||
2287       this->IsExecutableWithExports()) {
2288     if (cmProp custom_export_name = this->GetProperty("DEFINE_SYMBOL")) {
2289       this->ExportMacro = *custom_export_name;
2290     } else {
2291       std::string in = cmStrCat(this->GetName(), "_EXPORTS");
2292       this->ExportMacro = cmSystemTools::MakeCidentifier(in);
2293     }
2294     return &this->ExportMacro;
2295   }
2296   return nullptr;
2297 }
2298
2299 class cmTargetCollectLinkLanguages
2300 {
2301 public:
2302   cmTargetCollectLinkLanguages(cmGeneratorTarget const* target,
2303                                std::string config,
2304                                std::unordered_set<std::string>& languages,
2305                                cmGeneratorTarget const* head, bool secondPass)
2306     : Config(std::move(config))
2307     , Languages(languages)
2308     , HeadTarget(head)
2309     , Target(target)
2310     , SecondPass(secondPass)
2311   {
2312     this->Visited.insert(target);
2313   }
2314
2315   void Visit(cmLinkItem const& item)
2316   {
2317     if (!item.Target) {
2318       if (item.AsStr().find("::") != std::string::npos) {
2319         bool noMessage = false;
2320         MessageType messageType = MessageType::FATAL_ERROR;
2321         std::ostringstream e;
2322         switch (this->Target->GetLocalGenerator()->GetPolicyStatus(
2323           cmPolicies::CMP0028)) {
2324           case cmPolicies::WARN: {
2325             e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n";
2326             messageType = MessageType::AUTHOR_WARNING;
2327           } break;
2328           case cmPolicies::OLD:
2329             noMessage = true;
2330           case cmPolicies::REQUIRED_IF_USED:
2331           case cmPolicies::REQUIRED_ALWAYS:
2332           case cmPolicies::NEW:
2333             // Issue the fatal message.
2334             break;
2335         }
2336
2337         if (!noMessage) {
2338           e << "Target \"" << this->Target->GetName()
2339             << "\" links to target \"" << item.AsStr()
2340             << "\" but the target was not found.  Perhaps a find_package() "
2341                "call is missing for an IMPORTED target, or an ALIAS target is "
2342                "missing?";
2343           this->Target->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
2344             messageType, e.str(), this->Target->GetBacktrace());
2345         }
2346       }
2347       return;
2348     }
2349     if (!this->Visited.insert(item.Target).second) {
2350       return;
2351     }
2352     cmLinkInterface const* iface = item.Target->GetLinkInterface(
2353       this->Config, this->HeadTarget, this->SecondPass);
2354     if (!iface) {
2355       return;
2356     }
2357     if (iface->HadLinkLanguageSensitiveCondition) {
2358       this->HadLinkLanguageSensitiveCondition = true;
2359     }
2360
2361     for (std::string const& language : iface->Languages) {
2362       this->Languages.insert(language);
2363     }
2364
2365     for (cmLinkItem const& lib : iface->Libraries) {
2366       this->Visit(lib);
2367     }
2368   }
2369
2370   bool GetHadLinkLanguageSensitiveCondition()
2371   {
2372     return HadLinkLanguageSensitiveCondition;
2373   }
2374
2375 private:
2376   std::string Config;
2377   std::unordered_set<std::string>& Languages;
2378   cmGeneratorTarget const* HeadTarget;
2379   const cmGeneratorTarget* Target;
2380   std::set<cmGeneratorTarget const*> Visited;
2381   bool SecondPass;
2382   bool HadLinkLanguageSensitiveCondition = false;
2383 };
2384
2385 cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure(
2386   const std::string& config) const
2387 {
2388   std::string key(cmSystemTools::UpperCase(config));
2389   auto i = this->LinkClosureMap.find(key);
2390   if (i == this->LinkClosureMap.end()) {
2391     LinkClosure lc;
2392     this->ComputeLinkClosure(config, lc);
2393     LinkClosureMapType::value_type entry(key, lc);
2394     i = this->LinkClosureMap.insert(entry).first;
2395   }
2396   return &i->second;
2397 }
2398
2399 class cmTargetSelectLinker
2400 {
2401   int Preference;
2402   cmGeneratorTarget const* Target;
2403   cmGlobalGenerator* GG;
2404   std::set<std::string> Preferred;
2405
2406 public:
2407   cmTargetSelectLinker(cmGeneratorTarget const* target)
2408     : Preference(0)
2409     , Target(target)
2410   {
2411     this->GG = this->Target->GetLocalGenerator()->GetGlobalGenerator();
2412   }
2413   void Consider(const std::string& lang)
2414   {
2415     int preference = this->GG->GetLinkerPreference(lang);
2416     if (preference > this->Preference) {
2417       this->Preference = preference;
2418       this->Preferred.clear();
2419     }
2420     if (preference == this->Preference) {
2421       this->Preferred.insert(lang);
2422     }
2423   }
2424   std::string Choose()
2425   {
2426     if (this->Preferred.empty()) {
2427       return "";
2428     }
2429     if (this->Preferred.size() > 1) {
2430       std::ostringstream e;
2431       e << "Target " << this->Target->GetName()
2432         << " contains multiple languages with the highest linker preference"
2433         << " (" << this->Preference << "):\n";
2434       for (std::string const& li : this->Preferred) {
2435         e << "  " << li << "\n";
2436       }
2437       e << "Set the LINKER_LANGUAGE property for this target.";
2438       cmake* cm = this->Target->GetLocalGenerator()->GetCMakeInstance();
2439       cm->IssueMessage(MessageType::FATAL_ERROR, e.str(),
2440                        this->Target->GetBacktrace());
2441     }
2442     return *this->Preferred.begin();
2443   }
2444 };
2445
2446 bool cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
2447                                            LinkClosure& lc,
2448                                            bool secondPass) const
2449 {
2450   // Get languages built in this target.
2451   std::unordered_set<std::string> languages;
2452   cmLinkImplementation const* impl =
2453     this->GetLinkImplementation(config, secondPass);
2454   assert(impl);
2455   languages.insert(impl->Languages.cbegin(), impl->Languages.cend());
2456
2457   // Add interface languages from linked targets.
2458   // cmTargetCollectLinkLanguages cll(this, config, languages, this,
2459   // secondPass);
2460   cmTargetCollectLinkLanguages cll(this, config, languages, this, secondPass);
2461   for (cmLinkImplItem const& lib : impl->Libraries) {
2462     cll.Visit(lib);
2463   }
2464
2465   // Store the transitive closure of languages.
2466   cm::append(lc.Languages, languages);
2467
2468   // Choose the language whose linker should be used.
2469   if (secondPass || lc.LinkerLanguage.empty()) {
2470     // Find the language with the highest preference value.
2471     cmTargetSelectLinker tsl(this);
2472
2473     // First select from the languages compiled directly in this target.
2474     for (std::string const& l : impl->Languages) {
2475       tsl.Consider(l);
2476     }
2477
2478     // Now consider languages that propagate from linked targets.
2479     for (std::string const& lang : languages) {
2480       std::string propagates =
2481         "CMAKE_" + lang + "_LINKER_PREFERENCE_PROPAGATES";
2482       if (this->Makefile->IsOn(propagates)) {
2483         tsl.Consider(lang);
2484       }
2485     }
2486
2487     lc.LinkerLanguage = tsl.Choose();
2488   }
2489
2490   return impl->HadLinkLanguageSensitiveCondition ||
2491     cll.GetHadLinkLanguageSensitiveCondition();
2492 }
2493
2494 void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
2495                                            LinkClosure& lc) const
2496 {
2497   bool secondPass = false;
2498
2499   {
2500     LinkClosure linkClosure;
2501     linkClosure.LinkerLanguage = this->LinkerLanguage;
2502
2503     // Get languages built in this target.
2504     secondPass = this->ComputeLinkClosure(config, linkClosure, false);
2505     this->LinkerLanguage = linkClosure.LinkerLanguage;
2506     if (!secondPass) {
2507       lc = std::move(linkClosure);
2508     }
2509   }
2510
2511   if (secondPass) {
2512     LinkClosure linkClosure;
2513
2514     this->ComputeLinkClosure(config, linkClosure, secondPass);
2515     lc = std::move(linkClosure);
2516
2517     // linker language must not be changed between the two passes
2518     if (this->LinkerLanguage != lc.LinkerLanguage) {
2519       std::ostringstream e;
2520       e << "Evaluation of $<LINK_LANGUAGE:...> or $<LINK_LAND_AND_ID:...> "
2521            "changes\nthe linker language for target \""
2522         << this->GetName() << "\" (from '" << this->LinkerLanguage << "' to '"
2523         << lc.LinkerLanguage << "') which is invalid.";
2524       cmSystemTools::Error(e.str());
2525     }
2526   }
2527 }
2528
2529 void cmGeneratorTarget::GetFullNameComponents(
2530   std::string& prefix, std::string& base, std::string& suffix,
2531   const std::string& config, cmStateEnums::ArtifactType artifact) const
2532 {
2533   this->GetFullNameInternal(config, artifact, prefix, base, suffix);
2534 }
2535
2536 std::string cmGeneratorTarget::BuildBundleDirectory(
2537   const std::string& base, const std::string& config,
2538   BundleDirectoryLevel level) const
2539 {
2540   std::string fpath = base;
2541   if (this->IsAppBundleOnApple()) {
2542     fpath += this->GetAppBundleDirectory(config, level);
2543   }
2544   if (this->IsFrameworkOnApple()) {
2545     fpath += this->GetFrameworkDirectory(config, level);
2546   }
2547   if (this->IsCFBundleOnApple()) {
2548     fpath += this->GetCFBundleDirectory(config, level);
2549   }
2550   return fpath;
2551 }
2552
2553 std::string cmGeneratorTarget::GetMacContentDirectory(
2554   const std::string& config, cmStateEnums::ArtifactType artifact) const
2555 {
2556   // Start with the output directory for the target.
2557   std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/');
2558   BundleDirectoryLevel level = ContentLevel;
2559   if (this->IsFrameworkOnApple()) {
2560     // additional files with a framework go into the version specific
2561     // directory
2562     level = FullLevel;
2563   }
2564   fpath = this->BuildBundleDirectory(fpath, config, level);
2565   return fpath;
2566 }
2567
2568 std::string cmGeneratorTarget::GetEffectiveFolderName() const
2569 {
2570   std::string effectiveFolder;
2571
2572   if (!this->GlobalGenerator->UseFolderProperty()) {
2573     return effectiveFolder;
2574   }
2575
2576   cmProp targetFolder = this->GetProperty("FOLDER");
2577   if (targetFolder) {
2578     effectiveFolder += *targetFolder;
2579   }
2580
2581   return effectiveFolder;
2582 }
2583
2584 cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
2585   const std::string& config) const
2586 {
2587   // There is no compile information for imported targets.
2588   if (this->IsImported()) {
2589     return nullptr;
2590   }
2591
2592   if (this->GetType() > cmStateEnums::OBJECT_LIBRARY) {
2593     std::string msg = cmStrCat("cmTarget::GetCompileInfo called for ",
2594                                this->GetName(), " which has type ",
2595                                cmState::GetTargetTypeName(this->GetType()));
2596     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
2597     return nullptr;
2598   }
2599
2600   // Lookup/compute/cache the compile information for this configuration.
2601   std::string config_upper;
2602   if (!config.empty()) {
2603     config_upper = cmSystemTools::UpperCase(config);
2604   }
2605   auto i = this->CompileInfoMap.find(config_upper);
2606   if (i == this->CompileInfoMap.end()) {
2607     CompileInfo info;
2608     this->ComputePDBOutputDir("COMPILE_PDB", config, info.CompilePdbDir);
2609     CompileInfoMapType::value_type entry(config_upper, info);
2610     i = this->CompileInfoMap.insert(entry).first;
2611   }
2612   return &i->second;
2613 }
2614
2615 cmGeneratorTarget::ModuleDefinitionInfo const*
2616 cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const
2617 {
2618   // A module definition file only makes sense on certain target types.
2619   if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
2620       this->GetType() != cmStateEnums::MODULE_LIBRARY &&
2621       !this->IsExecutableWithExports()) {
2622     return nullptr;
2623   }
2624
2625   // Lookup/compute/cache the compile information for this configuration.
2626   std::string config_upper;
2627   if (!config.empty()) {
2628     config_upper = cmSystemTools::UpperCase(config);
2629   }
2630   auto i = this->ModuleDefinitionInfoMap.find(config_upper);
2631   if (i == this->ModuleDefinitionInfoMap.end()) {
2632     ModuleDefinitionInfo info;
2633     this->ComputeModuleDefinitionInfo(config, info);
2634     ModuleDefinitionInfoMapType::value_type entry(config_upper, info);
2635     i = this->ModuleDefinitionInfoMap.insert(entry).first;
2636   }
2637   return &i->second;
2638 }
2639
2640 void cmGeneratorTarget::ComputeModuleDefinitionInfo(
2641   std::string const& config, ModuleDefinitionInfo& info) const
2642 {
2643   this->GetModuleDefinitionSources(info.Sources, config);
2644   info.WindowsExportAllSymbols =
2645     this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
2646     this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
2647 #if !defined(CMAKE_BOOTSTRAP)
2648   info.DefFileGenerated =
2649     info.WindowsExportAllSymbols || info.Sources.size() > 1;
2650 #else
2651   // Our __create_def helper is not available during CMake bootstrap.
2652   info.DefFileGenerated = false;
2653 #endif
2654   if (info.DefFileGenerated) {
2655     info.DefFile =
2656       this->GetObjectDirectory(config) /* has slash */ + "exports.def";
2657   } else if (!info.Sources.empty()) {
2658     info.DefFile = info.Sources.front()->GetFullPath();
2659   }
2660 }
2661
2662 bool cmGeneratorTarget::IsDLLPlatform() const
2663 {
2664   return this->Target->IsDLLPlatform();
2665 }
2666
2667 void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
2668                                           const std::string& config) const
2669 {
2670   const char* prop =
2671     this->GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS", config);
2672   if (!prop) {
2673     return;
2674   }
2675
2676   cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr,
2677                                              nullptr);
2678   cmExpandList(cmGeneratorExpression::Evaluate(prop, this->LocalGenerator,
2679                                                config, this, &dagChecker),
2680                result);
2681 }
2682
2683 void processILibs(const std::string& config,
2684                   cmGeneratorTarget const* headTarget, cmLinkItem const& item,
2685                   cmGlobalGenerator* gg,
2686                   std::vector<cmGeneratorTarget const*>& tgts,
2687                   std::set<cmGeneratorTarget const*>& emitted)
2688 {
2689   if (item.Target && emitted.insert(item.Target).second) {
2690     tgts.push_back(item.Target);
2691     if (cmLinkInterfaceLibraries const* iface =
2692           item.Target->GetLinkInterfaceLibraries(config, headTarget, true)) {
2693       for (cmLinkItem const& lib : iface->Libraries) {
2694         processILibs(config, headTarget, lib, gg, tgts, emitted);
2695       }
2696     }
2697   }
2698 }
2699
2700 const std::vector<const cmGeneratorTarget*>&
2701 cmGeneratorTarget::GetLinkImplementationClosure(
2702   const std::string& config) const
2703 {
2704   LinkImplClosure& tgts = this->LinkImplClosureMap[config];
2705   if (!tgts.Done) {
2706     tgts.Done = true;
2707     std::set<cmGeneratorTarget const*> emitted;
2708
2709     cmLinkImplementationLibraries const* impl =
2710       this->GetLinkImplementationLibraries(config);
2711
2712     for (cmLinkImplItem const& lib : impl->Libraries) {
2713       processILibs(config, this, lib,
2714                    this->LocalGenerator->GetGlobalGenerator(), tgts, emitted);
2715     }
2716   }
2717   return tgts;
2718 }
2719
2720 class cmTargetTraceDependencies
2721 {
2722 public:
2723   cmTargetTraceDependencies(cmGeneratorTarget* target);
2724   void Trace();
2725
2726 private:
2727   cmGeneratorTarget* GeneratorTarget;
2728   cmMakefile* Makefile;
2729   cmLocalGenerator* LocalGenerator;
2730   cmGlobalGenerator const* GlobalGenerator;
2731   using SourceEntry = cmGeneratorTarget::SourceEntry;
2732   SourceEntry* CurrentEntry;
2733   std::queue<cmSourceFile*> SourceQueue;
2734   std::set<cmSourceFile*> SourcesQueued;
2735   using NameMapType = std::map<std::string, cmSourcesWithOutput>;
2736   NameMapType NameMap;
2737   std::vector<std::string> NewSources;
2738
2739   void QueueSource(cmSourceFile* sf);
2740   void FollowName(std::string const& name);
2741   void FollowNames(std::vector<std::string> const& names);
2742   bool IsUtility(std::string const& dep);
2743   void CheckCustomCommand(cmCustomCommand const& cc);
2744   void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
2745   void FollowCommandDepends(cmCustomCommand const& cc,
2746                             const std::string& config,
2747                             std::set<std::string>& emitted);
2748 };
2749
2750 cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target)
2751   : GeneratorTarget(target)
2752 {
2753   // Convenience.
2754   this->Makefile = target->Target->GetMakefile();
2755   this->LocalGenerator = target->GetLocalGenerator();
2756   this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
2757   this->CurrentEntry = nullptr;
2758
2759   // Queue all the source files already specified for the target.
2760   if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
2761     std::set<cmSourceFile*> emitted;
2762     std::vector<std::string> const& configs =
2763       this->Makefile->GetGeneratorConfigs();
2764     for (std::string const& c : configs) {
2765       std::vector<cmSourceFile*> sources;
2766       this->GeneratorTarget->GetSourceFiles(sources, c);
2767       for (cmSourceFile* sf : sources) {
2768         const std::set<cmGeneratorTarget const*> tgts =
2769           this->GlobalGenerator->GetFilenameTargetDepends(sf);
2770         if (cm::contains(tgts, this->GeneratorTarget)) {
2771           std::ostringstream e;
2772           e << "Evaluation output file\n  \"" << sf->ResolveFullPath()
2773             << "\"\ndepends on the sources of a target it is used in.  This "
2774                "is a dependency loop and is not allowed.";
2775           this->GeneratorTarget->LocalGenerator->IssueMessage(
2776             MessageType::FATAL_ERROR, e.str());
2777           return;
2778         }
2779         if (emitted.insert(sf).second &&
2780             this->SourcesQueued.insert(sf).second) {
2781           this->SourceQueue.push(sf);
2782         }
2783       }
2784     }
2785   }
2786
2787   // Queue pre-build, pre-link, and post-build rule dependencies.
2788   this->CheckCustomCommands(this->GeneratorTarget->GetPreBuildCommands());
2789   this->CheckCustomCommands(this->GeneratorTarget->GetPreLinkCommands());
2790   this->CheckCustomCommands(this->GeneratorTarget->GetPostBuildCommands());
2791 }
2792
2793 void cmTargetTraceDependencies::Trace()
2794 {
2795   // Process one dependency at a time until the queue is empty.
2796   while (!this->SourceQueue.empty()) {
2797     // Get the next source from the queue.
2798     cmSourceFile* sf = this->SourceQueue.front();
2799     this->SourceQueue.pop();
2800     this->CurrentEntry = &this->GeneratorTarget->SourceDepends[sf];
2801
2802     // Queue dependencies added explicitly by the user.
2803     if (cmProp additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) {
2804       std::vector<std::string> objDeps = cmExpandedList(*additionalDeps);
2805       for (std::string& objDep : objDeps) {
2806         if (cmSystemTools::FileIsFullPath(objDep)) {
2807           objDep = cmSystemTools::CollapseFullPath(objDep);
2808         }
2809       }
2810       this->FollowNames(objDeps);
2811     }
2812
2813     // Queue the source needed to generate this file, if any.
2814     this->FollowName(sf->ResolveFullPath());
2815
2816     // Queue dependencies added programmatically by commands.
2817     this->FollowNames(sf->GetDepends());
2818
2819     // Queue custom command dependencies.
2820     if (cmCustomCommand const* cc = sf->GetCustomCommand()) {
2821       this->CheckCustomCommand(*cc);
2822     }
2823   }
2824   this->CurrentEntry = nullptr;
2825
2826   this->GeneratorTarget->AddTracedSources(this->NewSources);
2827 }
2828
2829 void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
2830 {
2831   if (this->SourcesQueued.insert(sf).second) {
2832     this->SourceQueue.push(sf);
2833
2834     // Make sure this file is in the target at the end.
2835     this->NewSources.push_back(sf->ResolveFullPath());
2836   }
2837 }
2838
2839 void cmTargetTraceDependencies::FollowName(std::string const& name)
2840 {
2841   // Use lower bound with key comparison to not repeat the search for the
2842   // insert position if the name could not be found (which is the common case).
2843   auto i = this->NameMap.lower_bound(name);
2844   if (i == this->NameMap.end() || i->first != name) {
2845     // Check if we know how to generate this file.
2846     cmSourcesWithOutput sources = this->Makefile->GetSourcesWithOutput(name);
2847     // If we failed to find a target or source and we have a relative path, it
2848     // might be a valid source if made relative to the current binary
2849     // directory.
2850     if (!sources.Target && !sources.Source &&
2851         !cmSystemTools::FileIsFullPath(name)) {
2852       auto fullname =
2853         cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', name);
2854       fullname = cmSystemTools::CollapseFullPath(
2855         fullname, this->Makefile->GetHomeOutputDirectory());
2856       sources = this->Makefile->GetSourcesWithOutput(fullname);
2857     }
2858     i = this->NameMap.emplace_hint(i, name, sources);
2859   }
2860   if (cmTarget* t = i->second.Target) {
2861     // The name is a byproduct of a utility target or a PRE_BUILD, PRE_LINK, or
2862     // POST_BUILD command.
2863     this->GeneratorTarget->Target->AddUtility(t->GetName(), false);
2864   }
2865   if (cmSourceFile* sf = i->second.Source) {
2866     // For now only follow the dependency if the source file is not a
2867     // byproduct.  Semantics of byproducts in a non-Ninja context will have to
2868     // be defined first.
2869     if (!i->second.SourceIsByproduct) {
2870       // Record the dependency we just followed.
2871       if (this->CurrentEntry) {
2872         this->CurrentEntry->Depends.push_back(sf);
2873       }
2874       this->QueueSource(sf);
2875     }
2876   }
2877 }
2878
2879 void cmTargetTraceDependencies::FollowNames(
2880   std::vector<std::string> const& names)
2881 {
2882   for (std::string const& name : names) {
2883     this->FollowName(name);
2884   }
2885 }
2886
2887 bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
2888 {
2889   // Dependencies on targets (utilities) are supposed to be named by
2890   // just the target name.  However for compatibility we support
2891   // naming the output file generated by the target (assuming there is
2892   // no output-name property which old code would not have set).  In
2893   // that case the target name will be the file basename of the
2894   // dependency.
2895   std::string util = cmSystemTools::GetFilenameName(dep);
2896   if (cmSystemTools::GetFilenameLastExtension(util) == ".exe") {
2897     util = cmSystemTools::GetFilenameWithoutLastExtension(util);
2898   }
2899
2900   // Check for a target with this name.
2901   if (cmGeneratorTarget* t =
2902         this->GeneratorTarget->GetLocalGenerator()->FindGeneratorTargetToUse(
2903           util)) {
2904     // If we find the target and the dep was given as a full path,
2905     // then make sure it was not a full path to something else, and
2906     // the fact that the name matched a target was just a coincidence.
2907     if (cmSystemTools::FileIsFullPath(dep)) {
2908       if (t->GetType() >= cmStateEnums::EXECUTABLE &&
2909           t->GetType() <= cmStateEnums::MODULE_LIBRARY) {
2910         // This is really only for compatibility so we do not need to
2911         // worry about configuration names and output names.
2912         std::string tLocation = t->GetLocationForBuild();
2913         tLocation = cmSystemTools::GetFilenamePath(tLocation);
2914         std::string depLocation = cmSystemTools::GetFilenamePath(dep);
2915         depLocation = cmSystemTools::CollapseFullPath(depLocation);
2916         tLocation = cmSystemTools::CollapseFullPath(tLocation);
2917         if (depLocation == tLocation) {
2918           this->GeneratorTarget->Target->AddUtility(util, false);
2919           return true;
2920         }
2921       }
2922     } else {
2923       // The original name of the dependency was not a full path.  It
2924       // must name a target, so add the target-level dependency.
2925       this->GeneratorTarget->Target->AddUtility(util, false);
2926       return true;
2927     }
2928   }
2929
2930   // The dependency does not name a target built in this project.
2931   return false;
2932 }
2933
2934 void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
2935 {
2936   // Transform command names that reference targets built in this
2937   // project to corresponding target-level dependencies.
2938   cmGeneratorExpression ge(cc.GetBacktrace());
2939
2940   // Add target-level dependencies referenced by generator expressions.
2941   std::set<cmGeneratorTarget*> targets;
2942
2943   for (cmCustomCommandLine const& cCmdLine : cc.GetCommandLines()) {
2944     std::string const& command = cCmdLine.front();
2945     // Check for a target with this name.
2946     if (cmGeneratorTarget* t =
2947           this->LocalGenerator->FindGeneratorTargetToUse(command)) {
2948       if (t->GetType() == cmStateEnums::EXECUTABLE) {
2949         // The command refers to an executable target built in
2950         // this project.  Add the target-level dependency to make
2951         // sure the executable is up to date before this custom
2952         // command possibly runs.
2953         this->GeneratorTarget->Target->AddUtility(command, true);
2954       }
2955     }
2956
2957     // Check for target references in generator expressions.
2958     for (std::string const& cl : cCmdLine) {
2959       const std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cl);
2960       cge->SetQuiet(true);
2961       cge->Evaluate(this->GeneratorTarget->GetLocalGenerator(), "");
2962       std::set<cmGeneratorTarget*> geTargets = cge->GetTargets();
2963       targets.insert(geTargets.begin(), geTargets.end());
2964     }
2965   }
2966
2967   for (cmGeneratorTarget* target : targets) {
2968     this->GeneratorTarget->Target->AddUtility(target->GetName(), true);
2969   }
2970
2971   // Queue the custom command dependencies.
2972   std::set<std::string> emitted;
2973   std::vector<std::string> const& configs =
2974     this->Makefile->GetGeneratorConfigs();
2975   for (std::string const& conf : configs) {
2976     this->FollowCommandDepends(cc, conf, emitted);
2977   }
2978 }
2979
2980 void cmTargetTraceDependencies::FollowCommandDepends(
2981   cmCustomCommand const& cc, const std::string& config,
2982   std::set<std::string>& emitted)
2983 {
2984   cmCustomCommandGenerator ccg(cc, config,
2985                                this->GeneratorTarget->LocalGenerator);
2986
2987   const std::vector<std::string>& depends = ccg.GetDepends();
2988
2989   for (std::string const& dep : depends) {
2990     if (emitted.insert(dep).second) {
2991       if (!this->IsUtility(dep)) {
2992         // The dependency does not name a target and may be a file we
2993         // know how to generate.  Queue it.
2994         this->FollowName(dep);
2995       }
2996     }
2997   }
2998 }
2999
3000 void cmTargetTraceDependencies::CheckCustomCommands(
3001   const std::vector<cmCustomCommand>& commands)
3002 {
3003   for (cmCustomCommand const& command : commands) {
3004     this->CheckCustomCommand(command);
3005   }
3006 }
3007
3008 void cmGeneratorTarget::TraceDependencies()
3009 {
3010   // CMake-generated targets have no dependencies to trace.  Normally tracing
3011   // would find nothing anyway, but when building CMake itself the "install"
3012   // target command ends up referencing the "cmake" target but we do not
3013   // really want the dependency because "install" depend on "all" anyway.
3014   if (this->GetType() == cmStateEnums::GLOBAL_TARGET) {
3015     return;
3016   }
3017
3018   // Use a helper object to trace the dependencies.
3019   cmTargetTraceDependencies tracer(this);
3020   tracer.Trace();
3021 }
3022
3023 std::string cmGeneratorTarget::GetCompilePDBDirectory(
3024   const std::string& config) const
3025 {
3026   if (CompileInfo const* info = this->GetCompileInfo(config)) {
3027     return info->CompilePdbDir;
3028   }
3029   return "";
3030 }
3031
3032 void cmGeneratorTarget::GetAppleArchs(const std::string& config,
3033                                       std::vector<std::string>& archVec) const
3034 {
3035   if (!this->Makefile->IsOn("APPLE")) {
3036     return;
3037   }
3038   cmProp archs = nullptr;
3039   if (!config.empty()) {
3040     std::string defVarName =
3041       cmStrCat("OSX_ARCHITECTURES_", cmSystemTools::UpperCase(config));
3042     archs = this->GetProperty(defVarName);
3043   }
3044   if (!archs) {
3045     archs = this->GetProperty("OSX_ARCHITECTURES");
3046   }
3047   if (archs) {
3048     cmExpandList(*archs, archVec);
3049   }
3050 }
3051
3052 void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
3053 {
3054   const std::string& property = this->GetSafeProperty("CUDA_ARCHITECTURES");
3055
3056   if (property.empty()) {
3057     switch (this->GetPolicyStatusCMP0104()) {
3058       case cmPolicies::WARN:
3059         if (!this->LocalGenerator->GetCMakeInstance()->GetIsInTryCompile()) {
3060           this->Makefile->IssueMessage(
3061             MessageType::AUTHOR_WARNING,
3062             cmPolicies::GetPolicyWarning(cmPolicies::CMP0104) +
3063               "\nCUDA_ARCHITECTURES is empty for target \"" + this->GetName() +
3064               "\".");
3065         }
3066         CM_FALLTHROUGH;
3067       case cmPolicies::OLD:
3068         break;
3069       default:
3070         this->Makefile->IssueMessage(
3071           MessageType::FATAL_ERROR,
3072           "CUDA_ARCHITECTURES is empty for target \"" + this->GetName() +
3073             "\".");
3074     }
3075   }
3076
3077   // If CUDA_ARCHITECTURES is false we don't add any architectures.
3078   if (cmIsOff(property)) {
3079     return;
3080   }
3081
3082   struct CudaArchitecture
3083   {
3084     std::string name;
3085     bool real{ true };
3086     bool virtual_{ true };
3087   };
3088   std::vector<CudaArchitecture> architectures;
3089
3090   {
3091     std::vector<std::string> options;
3092     cmExpandList(property, options);
3093
3094     for (std::string& option : options) {
3095       CudaArchitecture architecture;
3096
3097       // Architecture name is up to the first specifier.
3098       std::size_t pos = option.find_first_of('-');
3099       architecture.name = option.substr(0, pos);
3100
3101       if (pos != std::string::npos) {
3102         cm::string_view specifier{ option.c_str() + pos + 1,
3103                                    option.length() - pos - 1 };
3104
3105         if (specifier == "real") {
3106           architecture.real = true;
3107           architecture.virtual_ = false;
3108         } else if (specifier == "virtual") {
3109           architecture.real = false;
3110           architecture.virtual_ = true;
3111         } else {
3112           this->Makefile->IssueMessage(
3113             MessageType::FATAL_ERROR,
3114             "Uknown CUDA architecture specifier \"" + std::string(specifier) +
3115               "\".");
3116         }
3117       }
3118
3119       architectures.emplace_back(architecture);
3120     }
3121   }
3122
3123   std::string const& compiler =
3124     this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID");
3125
3126   if (compiler == "NVIDIA") {
3127     for (CudaArchitecture& architecture : architectures) {
3128       flags +=
3129         " --generate-code=arch=compute_" + architecture.name + ",code=[";
3130
3131       if (architecture.virtual_) {
3132         flags += "compute_" + architecture.name;
3133
3134         if (architecture.real) {
3135           flags += ",";
3136         }
3137       }
3138
3139       if (architecture.real) {
3140         flags += "sm_" + architecture.name;
3141       }
3142
3143       flags += "]";
3144     }
3145   } else if (compiler == "Clang") {
3146     for (CudaArchitecture& architecture : architectures) {
3147       flags += " --cuda-gpu-arch=sm_" + architecture.name;
3148
3149       if (!architecture.real) {
3150         Makefile->IssueMessage(
3151           MessageType::WARNING,
3152           "Clang doesn't support disabling CUDA real code generation.");
3153       }
3154
3155       if (!architecture.virtual_) {
3156         flags += " --no-cuda-include-ptx=sm_" + architecture.name;
3157       }
3158     }
3159   }
3160 }
3161
3162 void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const
3163 {
3164   std::string const& compiler =
3165     this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID");
3166
3167   if (compiler == "Clang") {
3168     // Pass CUDA toolkit explicitly to Clang.
3169     // Clang's searching for the system CUDA toolkit isn't very good and it's
3170     // expected the user will explicitly pass the toolkit path.
3171     // This also avoids Clang having to search for the toolkit on every
3172     // invocation.
3173     std::string toolkitRoot =
3174       this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_LIBRARY_ROOT");
3175
3176     if (!toolkitRoot.empty()) {
3177       flags += " --cuda-path=" +
3178         this->LocalGenerator->ConvertToOutputFormat(toolkitRoot,
3179                                                     cmOutputConverter::SHELL);
3180     }
3181   }
3182 }
3183
3184 //----------------------------------------------------------------------------
3185 std::string cmGeneratorTarget::GetFeatureSpecificLinkRuleVariable(
3186   std::string const& var, std::string const& lang,
3187   std::string const& config) const
3188 {
3189   if (this->IsIPOEnabled(lang, config)) {
3190     std::string varIPO = var + "_IPO";
3191     if (this->Makefile->IsDefinitionSet(varIPO)) {
3192       return varIPO;
3193     }
3194   }
3195
3196   return var;
3197 }
3198
3199 //----------------------------------------------------------------------------
3200 std::string cmGeneratorTarget::GetCreateRuleVariable(
3201   std::string const& lang, std::string const& config) const
3202 {
3203   switch (this->GetType()) {
3204     case cmStateEnums::STATIC_LIBRARY: {
3205       std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY";
3206       return this->GetFeatureSpecificLinkRuleVariable(var, lang, config);
3207     }
3208     case cmStateEnums::SHARED_LIBRARY:
3209       return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY";
3210     case cmStateEnums::MODULE_LIBRARY:
3211       return "CMAKE_" + lang + "_CREATE_SHARED_MODULE";
3212     case cmStateEnums::EXECUTABLE:
3213       if (this->IsExecutableWithExports()) {
3214         std::string linkExeWithExports =
3215           "CMAKE_" + lang + "_LINK_EXECUTABLE_WITH_EXPORTS";
3216         if (this->Makefile->IsDefinitionSet(linkExeWithExports)) {
3217           return linkExeWithExports;
3218         }
3219       }
3220       return "CMAKE_" + lang + "_LINK_EXECUTABLE";
3221     default:
3222       break;
3223   }
3224   return "";
3225 }
3226
3227 namespace {
3228 void processIncludeDirectories(cmGeneratorTarget const* tgt,
3229                                EvaluatedTargetPropertyEntries& entries,
3230                                std::vector<BT<std::string>>& includes,
3231                                std::unordered_set<std::string>& uniqueIncludes,
3232                                bool debugIncludes)
3233 {
3234   for (EvaluatedTargetPropertyEntry& entry : entries.Entries) {
3235     cmLinkImplItem const& item = entry.LinkImplItem;
3236     std::string const& targetName = item.AsStr();
3237     bool const fromImported = item.Target && item.Target->IsImported();
3238     bool const checkCMP0027 = item.FromGenex;
3239
3240     std::string usedIncludes;
3241     for (std::string& entryInclude : entry.Values) {
3242       if (fromImported && !cmSystemTools::FileExists(entryInclude)) {
3243         std::ostringstream e;
3244         MessageType messageType = MessageType::FATAL_ERROR;
3245         if (checkCMP0027) {
3246           switch (tgt->GetPolicyStatusCMP0027()) {
3247             case cmPolicies::WARN:
3248               e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n";
3249               CM_FALLTHROUGH;
3250             case cmPolicies::OLD:
3251               messageType = MessageType::AUTHOR_WARNING;
3252               break;
3253             case cmPolicies::REQUIRED_ALWAYS:
3254             case cmPolicies::REQUIRED_IF_USED:
3255             case cmPolicies::NEW:
3256               break;
3257           }
3258         }
3259         /* clang-format off */
3260         e << "Imported target \"" << targetName << "\" includes "
3261              "non-existent path\n  \"" << entryInclude << "\"\nin its "
3262              "INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n"
3263              "* The path was deleted, renamed, or moved to another "
3264              "location.\n"
3265              "* An install or uninstall procedure did not complete "
3266              "successfully.\n"
3267              "* The installation package was faulty and references files it "
3268              "does not provide.\n";
3269         /* clang-format on */
3270         tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
3271         return;
3272       }
3273
3274       if (!cmSystemTools::FileIsFullPath(entryInclude)) {
3275         std::ostringstream e;
3276         bool noMessage = false;
3277         MessageType messageType = MessageType::FATAL_ERROR;
3278         if (!targetName.empty()) {
3279           /* clang-format off */
3280           e << "Target \"" << targetName << "\" contains relative "
3281             "path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
3282             "  \"" << entryInclude << "\"";
3283           /* clang-format on */
3284         } else {
3285           switch (tgt->GetPolicyStatusCMP0021()) {
3286             case cmPolicies::WARN: {
3287               e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n";
3288               messageType = MessageType::AUTHOR_WARNING;
3289             } break;
3290             case cmPolicies::OLD:
3291               noMessage = true;
3292             case cmPolicies::REQUIRED_IF_USED:
3293             case cmPolicies::REQUIRED_ALWAYS:
3294             case cmPolicies::NEW:
3295               // Issue the fatal message.
3296               break;
3297           }
3298           e << "Found relative path while evaluating include directories of "
3299                "\""
3300             << tgt->GetName() << "\":\n  \"" << entryInclude << "\"\n";
3301         }
3302         if (!noMessage) {
3303           tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
3304           if (messageType == MessageType::FATAL_ERROR) {
3305             return;
3306           }
3307         }
3308       }
3309
3310       if (!cmIsOff(entryInclude)) {
3311         cmSystemTools::ConvertToUnixSlashes(entryInclude);
3312       }
3313
3314       if (uniqueIncludes.insert(entryInclude).second) {
3315         includes.emplace_back(entryInclude, entry.Backtrace);
3316         if (debugIncludes) {
3317           usedIncludes += " * " + entryInclude + "\n";
3318         }
3319       }
3320     }
3321     if (!usedIncludes.empty()) {
3322       tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
3323         MessageType::LOG,
3324         std::string("Used includes for target ") + tgt->GetName() + ":\n" +
3325           usedIncludes,
3326         entry.Backtrace);
3327     }
3328   }
3329 }
3330 }
3331
3332 std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
3333   const std::string& config, const std::string& lang) const
3334 {
3335   std::vector<BT<std::string>> includes;
3336   std::unordered_set<std::string> uniqueIncludes;
3337
3338   cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES",
3339                                              nullptr, nullptr);
3340
3341   std::vector<std::string> debugProperties;
3342   this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES",
3343                                    debugProperties);
3344
3345   bool debugIncludes = !this->DebugIncludesDone &&
3346     cm::contains(debugProperties, "INCLUDE_DIRECTORIES");
3347
3348   if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
3349     this->DebugIncludesDone = true;
3350   }
3351
3352   EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
3353     this, config, lang, &dagChecker, this->IncludeDirectoriesEntries);
3354
3355   if (lang == "Swift") {
3356     AddSwiftImplicitIncludeDirectories(this, config, entries);
3357   }
3358
3359   AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang,
3360                       &dagChecker, entries);
3361
3362   if (this->Makefile->IsOn("APPLE")) {
3363     cmLinkImplementationLibraries const* impl =
3364       this->GetLinkImplementationLibraries(config);
3365     for (cmLinkImplItem const& lib : impl->Libraries) {
3366       std::string libDir = cmSystemTools::CollapseFullPath(
3367         lib.AsStr(), this->Makefile->GetHomeOutputDirectory());
3368
3369       static cmsys::RegularExpression frameworkCheck(
3370         "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
3371       if (!frameworkCheck.find(libDir)) {
3372         continue;
3373       }
3374
3375       libDir = frameworkCheck.match(1);
3376
3377       EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace());
3378       ee.Values.emplace_back(std::move(libDir));
3379       entries.Entries.emplace_back(std::move(ee));
3380     }
3381   }
3382
3383   processIncludeDirectories(this, entries, includes, uniqueIncludes,
3384                             debugIncludes);
3385
3386   return includes;
3387 }
3388
3389 enum class OptionsParse
3390 {
3391   None,
3392   Shell
3393 };
3394
3395 namespace {
3396 const auto DL_BEGIN = "<DEVICE_LINK>"_s;
3397 const auto DL_END = "</DEVICE_LINK>"_s;
3398
3399 void processOptions(cmGeneratorTarget const* tgt,
3400                     EvaluatedTargetPropertyEntries const& entries,
3401                     std::vector<BT<std::string>>& options,
3402                     std::unordered_set<std::string>& uniqueOptions,
3403                     bool debugOptions, const char* logName, OptionsParse parse,
3404                     bool processDeviceOptions = false)
3405 {
3406   bool splitOption = !processDeviceOptions;
3407   for (EvaluatedTargetPropertyEntry const& entry : entries.Entries) {
3408     std::string usedOptions;
3409     for (std::string const& opt : entry.Values) {
3410       if (processDeviceOptions && (opt == DL_BEGIN || opt == DL_END)) {
3411         options.emplace_back(opt, entry.Backtrace);
3412         splitOption = opt == DL_BEGIN;
3413         continue;
3414       }
3415
3416       if (uniqueOptions.insert(opt).second) {
3417         if (parse == OptionsParse::Shell &&
3418             cmHasLiteralPrefix(opt, "SHELL:")) {
3419           if (splitOption) {
3420             std::vector<std::string> tmp;
3421             cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp);
3422             for (std::string& o : tmp) {
3423               options.emplace_back(std::move(o), entry.Backtrace);
3424             }
3425           } else {
3426             options.emplace_back(std::string(opt.c_str() + 6),
3427                                  entry.Backtrace);
3428           }
3429         } else {
3430           options.emplace_back(opt, entry.Backtrace);
3431         }
3432         if (debugOptions) {
3433           usedOptions += " * " + opt + "\n";
3434         }
3435       }
3436     }
3437     if (!usedOptions.empty()) {
3438       tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
3439         MessageType::LOG,
3440         std::string("Used ") + logName + std::string(" for target ") +
3441           tgt->GetName() + ":\n" + usedOptions,
3442         entry.Backtrace);
3443     }
3444   }
3445 }
3446
3447 std::vector<BT<std::string>> wrapOptions(
3448   std::vector<std::string>& options, const cmListFileBacktrace& bt,
3449   const std::vector<std::string>& wrapperFlag, const std::string& wrapperSep,
3450   bool concatFlagAndArgs)
3451 {
3452   std::vector<BT<std::string>> result;
3453
3454   if (options.empty()) {
3455     return result;
3456   }
3457
3458   if (wrapperFlag.empty() || cmHasLiteralPrefix(options.front(), "LINKER:")) {
3459     // nothing specified or LINKER wrapper, insert elements as is
3460     result.reserve(options.size());
3461     for (std::string& o : options) {
3462       result.emplace_back(std::move(o), bt);
3463     }
3464   } else {
3465     if (!wrapperSep.empty()) {
3466       if (concatFlagAndArgs) {
3467         // insert flag elements except last one
3468         for (auto i = wrapperFlag.begin(); i != wrapperFlag.end() - 1; ++i) {
3469           result.emplace_back(*i, bt);
3470         }
3471         // concatenate last flag element and all list values
3472         // in one option
3473         result.emplace_back(wrapperFlag.back() + cmJoin(options, wrapperSep),
3474                             bt);
3475       } else {
3476         for (std::string const& i : wrapperFlag) {
3477           result.emplace_back(i, bt);
3478         }
3479         // concatenate all list values in one option
3480         result.emplace_back(cmJoin(options, wrapperSep), bt);
3481       }
3482     } else {
3483       // prefix each element of list with wrapper
3484       if (concatFlagAndArgs) {
3485         std::transform(options.begin(), options.end(), options.begin(),
3486                        [&wrapperFlag](std::string const& o) -> std::string {
3487                          return wrapperFlag.back() + o;
3488                        });
3489       }
3490       for (std::string& o : options) {
3491         for (auto i = wrapperFlag.begin(),
3492                   e = concatFlagAndArgs ? wrapperFlag.end() - 1
3493                                         : wrapperFlag.end();
3494              i != e; ++i) {
3495           result.emplace_back(*i, bt);
3496         }
3497         result.emplace_back(std::move(o), bt);
3498       }
3499     }
3500   }
3501   return result;
3502 }
3503 }
3504
3505 void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
3506                                           const std::string& config,
3507                                           const std::string& language) const
3508 {
3509   std::vector<BT<std::string>> tmp = this->GetCompileOptions(config, language);
3510   result.reserve(tmp.size());
3511   for (BT<std::string>& v : tmp) {
3512     result.emplace_back(std::move(v.Value));
3513   }
3514 }
3515
3516 std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions(
3517   std::string const& config, std::string const& language) const
3518 {
3519   std::vector<BT<std::string>> result;
3520   std::unordered_set<std::string> uniqueOptions;
3521
3522   cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr,
3523                                              nullptr);
3524
3525   std::vector<std::string> debugProperties;
3526   this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES",
3527                                    debugProperties);
3528
3529   bool debugOptions = !this->DebugCompileOptionsDone &&
3530     cm::contains(debugProperties, "COMPILE_OPTIONS");
3531
3532   if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
3533     this->DebugCompileOptionsDone = true;
3534   }
3535
3536   EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
3537     this, config, language, &dagChecker, this->CompileOptionsEntries);
3538
3539   AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", language,
3540                       &dagChecker, entries);
3541
3542   processOptions(this, entries, result, uniqueOptions, debugOptions,
3543                  "compile options", OptionsParse::Shell);
3544
3545   return result;
3546 }
3547
3548 void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
3549                                            const std::string& config) const
3550 {
3551   std::vector<BT<std::string>> tmp = this->GetCompileFeatures(config);
3552   result.reserve(tmp.size());
3553   for (BT<std::string>& v : tmp) {
3554     result.emplace_back(std::move(v.Value));
3555   }
3556 }
3557
3558 std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures(
3559   std::string const& config) const
3560 {
3561   std::vector<BT<std::string>> result;
3562   std::unordered_set<std::string> uniqueFeatures;
3563
3564   cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr,
3565                                              nullptr);
3566
3567   std::vector<std::string> debugProperties;
3568   this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES",
3569                                    debugProperties);
3570
3571   bool debugFeatures = !this->DebugCompileFeaturesDone &&
3572     cm::contains(debugProperties, "COMPILE_FEATURES");
3573
3574   if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
3575     this->DebugCompileFeaturesDone = true;
3576   }
3577
3578   EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
3579     this, config, std::string(), &dagChecker, this->CompileFeaturesEntries);
3580
3581   AddInterfaceEntries(this, config, "INTERFACE_COMPILE_FEATURES",
3582                       std::string(), &dagChecker, entries);
3583
3584   processOptions(this, entries, result, uniqueFeatures, debugFeatures,
3585                  "compile features", OptionsParse::None);
3586
3587   return result;
3588 }
3589
3590 void cmGeneratorTarget::GetCompileDefinitions(
3591   std::vector<std::string>& result, const std::string& config,
3592   const std::string& language) const
3593 {
3594   std::vector<BT<std::string>> tmp =
3595     this->GetCompileDefinitions(config, language);
3596   result.reserve(tmp.size());
3597   for (BT<std::string>& v : tmp) {
3598     result.emplace_back(std::move(v.Value));
3599   }
3600 }
3601
3602 std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions(
3603   std::string const& config, std::string const& language) const
3604 {
3605   std::vector<BT<std::string>> list;
3606   std::unordered_set<std::string> uniqueOptions;
3607
3608   cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS",
3609                                              nullptr, nullptr);
3610
3611   std::vector<std::string> debugProperties;
3612   this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES",
3613                                    debugProperties);
3614
3615   bool debugDefines = !this->DebugCompileDefinitionsDone &&
3616     cm::contains(debugProperties, "COMPILE_DEFINITIONS");
3617
3618   if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
3619     this->DebugCompileDefinitionsDone = true;
3620   }
3621
3622   EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
3623     this, config, language, &dagChecker, this->CompileDefinitionsEntries);
3624
3625   AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", language,
3626                       &dagChecker, entries);
3627
3628   if (!config.empty()) {
3629     std::string configPropName =
3630       "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
3631     cmProp configProp = this->GetProperty(configPropName);
3632     if (configProp) {
3633       switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) {
3634         case cmPolicies::WARN: {
3635           this->LocalGenerator->IssueMessage(
3636             MessageType::AUTHOR_WARNING,
3637             cmPolicies::GetPolicyWarning(cmPolicies::CMP0043));
3638           CM_FALLTHROUGH;
3639         }
3640         case cmPolicies::OLD: {
3641           std::unique_ptr<TargetPropertyEntry> entry =
3642             CreateTargetPropertyEntry(*configProp);
3643           entries.Entries.emplace_back(EvaluateTargetPropertyEntry(
3644             this, config, language, &dagChecker, *entry));
3645         } break;
3646         case cmPolicies::NEW:
3647         case cmPolicies::REQUIRED_ALWAYS:
3648         case cmPolicies::REQUIRED_IF_USED:
3649           break;
3650       }
3651     }
3652   }
3653
3654   processOptions(this, entries, list, uniqueOptions, debugDefines,
3655                  "compile definitions", OptionsParse::None);
3656
3657   return list;
3658 }
3659
3660 std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders(
3661   const std::string& config, const std::string& language) const
3662 {
3663   std::unordered_set<std::string> uniqueOptions;
3664
3665   cmGeneratorExpressionDAGChecker dagChecker(this, "PRECOMPILE_HEADERS",
3666                                              nullptr, nullptr);
3667
3668   std::vector<std::string> debugProperties;
3669   this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES",
3670                                    debugProperties);
3671
3672   bool debugDefines = !this->DebugPrecompileHeadersDone &&
3673     std::find(debugProperties.begin(), debugProperties.end(),
3674               "PRECOMPILE_HEADERS") != debugProperties.end();
3675
3676   if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
3677     this->DebugPrecompileHeadersDone = true;
3678   }
3679
3680   EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
3681     this, config, language, &dagChecker, this->PrecompileHeadersEntries);
3682
3683   AddInterfaceEntries(this, config, "INTERFACE_PRECOMPILE_HEADERS", language,
3684                       &dagChecker, entries);
3685
3686   std::vector<BT<std::string>> list;
3687   processOptions(this, entries, list, uniqueOptions, debugDefines,
3688                  "precompile headers", OptionsParse::None);
3689
3690   return list;
3691 }
3692
3693 std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
3694                                             const std::string& language,
3695                                             const std::string& arch) const
3696 {
3697   if (language != "C" && language != "CXX" && language != "OBJC" &&
3698       language != "OBJCXX") {
3699     return std::string();
3700   }
3701
3702   if (this->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) {
3703     return std::string();
3704   }
3705   const cmGeneratorTarget* generatorTarget = this;
3706   cmProp pchReuseFrom =
3707     generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
3708
3709   const auto inserted =
3710     this->PchHeaders.insert(std::make_pair(language + config + arch, ""));
3711   if (inserted.second) {
3712     const std::vector<BT<std::string>> headers =
3713       this->GetPrecompileHeaders(config, language);
3714     if (headers.empty() && !pchReuseFrom) {
3715       return std::string();
3716     }
3717     std::string& filename = inserted.first->second;
3718
3719     if (pchReuseFrom) {
3720       generatorTarget =
3721         this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom);
3722     }
3723
3724     filename = cmStrCat(
3725       generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(), "/");
3726
3727     const std::map<std::string, std::string> languageToExtension = {
3728       { "C", ".h" },
3729       { "CXX", ".hxx" },
3730       { "OBJC", ".objc.h" },
3731       { "OBJCXX", ".objcxx.hxx" }
3732     };
3733
3734     filename =
3735       cmStrCat(filename, "CMakeFiles/", generatorTarget->GetName(), ".dir");
3736
3737     if (this->GetGlobalGenerator()->IsMultiConfig()) {
3738       filename = cmStrCat(filename, "/", config);
3739     }
3740
3741     filename =
3742       cmStrCat(filename, "/cmake_pch", arch.empty() ? "" : cmStrCat("_", arch),
3743                languageToExtension.at(language));
3744
3745     const std::string filename_tmp = cmStrCat(filename, ".tmp");
3746     if (!pchReuseFrom) {
3747       auto pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE");
3748       auto pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE");
3749
3750       std::string firstHeaderOnDisk;
3751       {
3752         cmGeneratedFileStream file(
3753           filename_tmp, false,
3754           this->GetGlobalGenerator()->GetMakefileEncoding());
3755         file << "/* generated by CMake */\n\n";
3756         if (pchPrologue) {
3757           file << pchPrologue << "\n";
3758         }
3759         if (this->GetGlobalGenerator()->IsXcode()) {
3760           file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n";
3761         }
3762         if (language == "CXX") {
3763           file << "#ifdef __cplusplus\n";
3764         }
3765         for (auto const& header_bt : headers) {
3766           if (header_bt.Value.empty()) {
3767             continue;
3768           }
3769           if (header_bt.Value[0] == '<' || header_bt.Value[0] == '\"') {
3770             file << "#include " << header_bt.Value << "\n";
3771           } else {
3772             file << "#include \"" << header_bt.Value << "\"\n";
3773           }
3774
3775           if (cmSystemTools::FileExists(header_bt.Value) &&
3776               firstHeaderOnDisk.empty()) {
3777             firstHeaderOnDisk = header_bt.Value;
3778           }
3779         }
3780         if (language == "CXX") {
3781           file << "#endif // __cplusplus\n";
3782         }
3783         if (this->GetGlobalGenerator()->IsXcode()) {
3784           file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n";
3785         }
3786         if (pchEpilogue) {
3787           file << pchEpilogue << "\n";
3788         }
3789       }
3790
3791       if (!firstHeaderOnDisk.empty()) {
3792         cmFileTimes::Copy(firstHeaderOnDisk, filename_tmp);
3793       }
3794
3795       cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
3796     }
3797   }
3798   return inserted.first->second;
3799 }
3800
3801 std::string cmGeneratorTarget::GetPchSource(const std::string& config,
3802                                             const std::string& language,
3803                                             const std::string& arch) const
3804 {
3805   if (language != "C" && language != "CXX" && language != "OBJC" &&
3806       language != "OBJCXX") {
3807     return std::string();
3808   }
3809   const auto inserted =
3810     this->PchSources.insert(std::make_pair(language + config + arch, ""));
3811   if (inserted.second) {
3812     const std::string pchHeader = this->GetPchHeader(config, language, arch);
3813     if (pchHeader.empty()) {
3814       return std::string();
3815     }
3816     std::string& filename = inserted.first->second;
3817
3818     const cmGeneratorTarget* generatorTarget = this;
3819     cmProp pchReuseFrom =
3820       generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
3821     if (pchReuseFrom) {
3822       generatorTarget =
3823         this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom);
3824     }
3825
3826     filename =
3827       cmStrCat(generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(),
3828                "/CMakeFiles/", generatorTarget->GetName(), ".dir/cmake_pch");
3829
3830     // For GCC the source extension will be tranformed into .h[xx].gch
3831     if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) {
3832       const std::map<std::string, std::string> languageToExtension = {
3833         { "C", ".h.c" },
3834         { "CXX", ".hxx.cxx" },
3835         { "OBJC", ".objc.h.m" },
3836         { "OBJCXX", ".objcxx.hxx.mm" }
3837       };
3838
3839       filename = cmStrCat(filename, arch.empty() ? "" : cmStrCat("_", arch),
3840                           languageToExtension.at(language));
3841     } else {
3842       const std::map<std::string, std::string> languageToExtension = {
3843         { "C", ".c" }, { "CXX", ".cxx" }, { "OBJC", ".m" }, { "OBJCXX", ".mm" }
3844       };
3845
3846       filename = cmStrCat(filename, arch.empty() ? "" : cmStrCat("_", arch),
3847                           languageToExtension.at(language));
3848     }
3849
3850     const std::string filename_tmp = cmStrCat(filename, ".tmp");
3851     if (!pchReuseFrom) {
3852       {
3853         cmGeneratedFileStream file(filename_tmp);
3854         file << "/* generated by CMake */\n";
3855       }
3856       cmFileTimes::Copy(pchHeader, filename_tmp);
3857       cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
3858     }
3859   }
3860   return inserted.first->second;
3861 }
3862
3863 std::string cmGeneratorTarget::GetPchFileObject(const std::string& config,
3864                                                 const std::string& language,
3865                                                 const std::string& arch)
3866 {
3867   if (language != "C" && language != "CXX" && language != "OBJC" &&
3868       language != "OBJCXX") {
3869     return std::string();
3870   }
3871   const auto inserted =
3872     this->PchObjectFiles.insert(std::make_pair(language + config + arch, ""));
3873   if (inserted.second) {
3874     const std::string pchSource = this->GetPchSource(config, language, arch);
3875     if (pchSource.empty()) {
3876       return std::string();
3877     }
3878     std::string& filename = inserted.first->second;
3879
3880     auto pchSf = this->Makefile->GetOrCreateSource(
3881       pchSource, false, cmSourceFileLocationKind::Known);
3882
3883     filename = cmStrCat(this->ObjectDirectory, this->GetObjectName(pchSf));
3884     if (this->GetGlobalGenerator()->IsMultiConfig()) {
3885       cmSystemTools::ReplaceString(
3886         filename, this->GetGlobalGenerator()->GetCMakeCFGIntDir(), config);
3887     }
3888   }
3889   return inserted.first->second;
3890 }
3891
3892 std::string cmGeneratorTarget::GetPchFile(const std::string& config,
3893                                           const std::string& language,
3894                                           const std::string& arch)
3895 {
3896   const auto inserted =
3897     this->PchFiles.insert(std::make_pair(language + config + arch, ""));
3898   if (inserted.second) {
3899     std::string& pchFile = inserted.first->second;
3900
3901     const std::string pchExtension =
3902       this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION");
3903
3904     if (this->Makefile->IsOn("CMAKE_LINK_PCH")) {
3905       auto replaceExtension = [](const std::string& str,
3906                                  const std::string& ext) -> std::string {
3907         auto dot_pos = str.rfind('.');
3908         std::string result;
3909         if (dot_pos != std::string::npos) {
3910           result = str.substr(0, dot_pos);
3911         }
3912         result += ext;
3913         return result;
3914       };
3915
3916       cmGeneratorTarget* generatorTarget = this;
3917       cmProp pchReuseFrom =
3918         generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
3919       if (pchReuseFrom) {
3920         generatorTarget =
3921           this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom);
3922       }
3923
3924       const std::string pchFileObject =
3925         generatorTarget->GetPchFileObject(config, language, arch);
3926       if (!pchExtension.empty()) {
3927         pchFile = replaceExtension(pchFileObject, pchExtension);
3928       }
3929     } else {
3930       pchFile = this->GetPchHeader(config, language, arch);
3931       pchFile += pchExtension;
3932     }
3933   }
3934   return inserted.first->second;
3935 }
3936
3937 std::string cmGeneratorTarget::GetPchCreateCompileOptions(
3938   const std::string& config, const std::string& language,
3939   const std::string& arch)
3940 {
3941   const auto inserted = this->PchCreateCompileOptions.insert(
3942     std::make_pair(language + config + arch, ""));
3943   if (inserted.second) {
3944     std::string& createOptionList = inserted.first->second;
3945
3946     if (this->GetPropertyAsBool("PCH_WARN_INVALID")) {
3947       createOptionList = this->Makefile->GetSafeDefinition(
3948         cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_INVALID_PCH"));
3949     }
3950
3951     const std::string createOptVar =
3952       cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_CREATE_PCH");
3953
3954     createOptionList = cmStrCat(
3955       createOptionList, ";", this->Makefile->GetSafeDefinition(createOptVar));
3956
3957     const std::string pchHeader = this->GetPchHeader(config, language, arch);
3958     const std::string pchFile = this->GetPchFile(config, language, arch);
3959
3960     cmSystemTools::ReplaceString(createOptionList, "<PCH_HEADER>", pchHeader);
3961     cmSystemTools::ReplaceString(createOptionList, "<PCH_FILE>", pchFile);
3962   }
3963   return inserted.first->second;
3964 }
3965
3966 std::string cmGeneratorTarget::GetPchUseCompileOptions(
3967   const std::string& config, const std::string& language,
3968   const std::string& arch)
3969 {
3970   const auto inserted = this->PchUseCompileOptions.insert(
3971     std::make_pair(language + config + arch, ""));
3972   if (inserted.second) {
3973     std::string& useOptionList = inserted.first->second;
3974
3975     if (this->GetPropertyAsBool("PCH_WARN_INVALID")) {
3976       useOptionList = this->Makefile->GetSafeDefinition(
3977         cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_INVALID_PCH"));
3978     }
3979
3980     const std::string useOptVar =
3981       cmStrCat(language, "_COMPILE_OPTIONS_USE_PCH");
3982
3983     std::string const& useOptionListProperty =
3984       this->GetSafeProperty(useOptVar);
3985
3986     useOptionList = cmStrCat(
3987       useOptionList, ";",
3988       useOptionListProperty.empty()
3989         ? this->Makefile->GetSafeDefinition(cmStrCat("CMAKE_", useOptVar))
3990         : useOptionListProperty);
3991
3992     const std::string pchHeader = this->GetPchHeader(config, language, arch);
3993     const std::string pchFile = this->GetPchFile(config, language, arch);
3994
3995     cmSystemTools::ReplaceString(useOptionList, "<PCH_HEADER>", pchHeader);
3996     cmSystemTools::ReplaceString(useOptionList, "<PCH_FILE>", pchFile);
3997   }
3998   return inserted.first->second;
3999 }
4000
4001 void cmGeneratorTarget::AddSourceFileToUnityBatch(
4002   const std::string& sourceFilename)
4003 {
4004   this->UnityBatchedSourceFiles.insert(sourceFilename);
4005 }
4006
4007 bool cmGeneratorTarget::IsSourceFilePartOfUnityBatch(
4008   const std::string& sourceFilename) const
4009 {
4010   if (!this->GetPropertyAsBool("UNITY_BUILD")) {
4011     return false;
4012   }
4013
4014   return this->UnityBatchedSourceFiles.find(sourceFilename) !=
4015     this->UnityBatchedSourceFiles.end();
4016 }
4017
4018 void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
4019                                        const std::string& config,
4020                                        const std::string& language) const
4021 {
4022   if (this->IsDeviceLink() &&
4023       this->GetPolicyStatusCMP0105() != cmPolicies::NEW) {
4024     // link options are not propagated to the device link step
4025     return;
4026   }
4027
4028   std::vector<BT<std::string>> tmp = this->GetLinkOptions(config, language);
4029   result.reserve(tmp.size());
4030   for (BT<std::string>& v : tmp) {
4031     result.emplace_back(std::move(v.Value));
4032   }
4033 }
4034
4035 std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
4036   std::string const& config, std::string const& language) const
4037 {
4038   std::vector<BT<std::string>> result;
4039   std::unordered_set<std::string> uniqueOptions;
4040
4041   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr,
4042                                              nullptr);
4043
4044   std::vector<std::string> debugProperties;
4045   this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES",
4046                                    debugProperties);
4047
4048   bool debugOptions = !this->DebugLinkOptionsDone &&
4049     cm::contains(debugProperties, "LINK_OPTIONS");
4050
4051   if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
4052     this->DebugLinkOptionsDone = true;
4053   }
4054
4055   EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
4056     this, config, language, &dagChecker, this->LinkOptionsEntries);
4057
4058   AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language,
4059                       &dagChecker, entries,
4060                       this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
4061
4062   processOptions(this, entries, result, uniqueOptions, debugOptions,
4063                  "link options", OptionsParse::Shell, this->IsDeviceLink());
4064
4065   if (this->IsDeviceLink()) {
4066     // wrap host link options
4067     const std::string wrapper(this->Makefile->GetSafeDefinition(
4068       "CMAKE_" + language + "_DEVICE_COMPILER_WRAPPER_FLAG"));
4069     std::vector<std::string> wrapperFlag = cmExpandedList(wrapper);
4070     const std::string wrapperSep(this->Makefile->GetSafeDefinition(
4071       "CMAKE_" + language + "_DEVICE_COMPILER_WRAPPER_FLAG_SEP"));
4072     bool concatFlagAndArgs = true;
4073     if (!wrapperFlag.empty() && wrapperFlag.back() == " ") {
4074       concatFlagAndArgs = false;
4075       wrapperFlag.pop_back();
4076     }
4077
4078     auto it = result.begin();
4079     while (it != result.end()) {
4080       if (it->Value == DL_BEGIN) {
4081         // device link options, no treatment
4082         it = result.erase(it);
4083         it = std::find_if(it, result.end(), [](const BT<std::string>& item) {
4084           return item.Value == DL_END;
4085         });
4086         if (it != result.end()) {
4087           it = result.erase(it);
4088         }
4089       } else {
4090         // host link options must be wrapped
4091         std::vector<std::string> options;
4092         cmSystemTools::ParseUnixCommandLine(it->Value.c_str(), options);
4093         auto hostOptions = wrapOptions(options, it->Backtrace, wrapperFlag,
4094                                        wrapperSep, concatFlagAndArgs);
4095         it = result.erase(it);
4096         // some compilers (like gcc 4.8 or Intel 19.0 or XLC 16) do not respect
4097         // C++11 standard: 'std::vector::insert()' do not returns an iterator,
4098         // so need to recompute the iterator after insertion.
4099         if (it == result.end()) {
4100           cm::append(result, hostOptions);
4101           it = result.end();
4102         } else {
4103           auto index = it - result.begin();
4104           result.insert(it, hostOptions.begin(), hostOptions.end());
4105           it = result.begin() + index + hostOptions.size();
4106         }
4107       }
4108     }
4109   }
4110
4111   // Last step: replace "LINKER:" prefixed elements by
4112   // actual linker wrapper
4113   const std::string wrapper(this->Makefile->GetSafeDefinition(
4114     "CMAKE_" + language +
4115     (this->IsDeviceLink() ? "_DEVICE_LINKER_WRAPPER_FLAG"
4116                           : "_LINKER_WRAPPER_FLAG")));
4117   std::vector<std::string> wrapperFlag = cmExpandedList(wrapper);
4118   const std::string wrapperSep(this->Makefile->GetSafeDefinition(
4119     "CMAKE_" + language +
4120     (this->IsDeviceLink() ? "_DEVICE_LINKER_WRAPPER_FLAG_SEP"
4121                           : "_LINKER_WRAPPER_FLAG_SEP")));
4122   bool concatFlagAndArgs = true;
4123   if (!wrapperFlag.empty() && wrapperFlag.back() == " ") {
4124     concatFlagAndArgs = false;
4125     wrapperFlag.pop_back();
4126   }
4127
4128   const std::string LINKER{ "LINKER:" };
4129   const std::string SHELL{ "SHELL:" };
4130   const std::string LINKER_SHELL = LINKER + SHELL;
4131
4132   std::vector<BT<std::string>>::iterator entry;
4133   while ((entry = std::find_if(result.begin(), result.end(),
4134                                [&LINKER](BT<std::string> const& item) -> bool {
4135                                  return item.Value.compare(0, LINKER.length(),
4136                                                            LINKER) == 0;
4137                                })) != result.end()) {
4138     std::string value = std::move(entry->Value);
4139     cmListFileBacktrace bt = std::move(entry->Backtrace);
4140     entry = result.erase(entry);
4141
4142     std::vector<std::string> linkerOptions;
4143     if (value.compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) {
4144       cmSystemTools::ParseUnixCommandLine(
4145         value.c_str() + LINKER_SHELL.length(), linkerOptions);
4146     } else {
4147       linkerOptions = cmTokenize(value.substr(LINKER.length()), ",");
4148     }
4149
4150     if (linkerOptions.empty() ||
4151         (linkerOptions.size() == 1 && linkerOptions.front().empty())) {
4152       continue;
4153     }
4154
4155     // for now, raise an error if prefix SHELL: is part of arguments
4156     if (std::find_if(linkerOptions.begin(), linkerOptions.end(),
4157                      [&SHELL](const std::string& item) -> bool {
4158                        return item.find(SHELL) != std::string::npos;
4159                      }) != linkerOptions.end()) {
4160       this->LocalGenerator->GetCMakeInstance()->IssueMessage(
4161         MessageType::FATAL_ERROR,
4162         "'SHELL:' prefix is not supported as part of 'LINKER:' arguments.",
4163         this->GetBacktrace());
4164       return result;
4165     }
4166
4167     std::vector<BT<std::string>> options = wrapOptions(
4168       linkerOptions, bt, wrapperFlag, wrapperSep, concatFlagAndArgs);
4169     result.insert(entry, options.begin(), options.end());
4170   }
4171   return result;
4172 }
4173
4174 void cmGeneratorTarget::GetStaticLibraryLinkOptions(
4175   std::vector<std::string>& result, const std::string& config,
4176   const std::string& language) const
4177 {
4178   std::vector<BT<std::string>> tmp =
4179     this->GetStaticLibraryLinkOptions(config, language);
4180   result.reserve(tmp.size());
4181   for (BT<std::string>& v : tmp) {
4182     result.emplace_back(std::move(v.Value));
4183   }
4184 }
4185
4186 std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions(
4187   std::string const& config, std::string const& language) const
4188 {
4189   std::vector<BT<std::string>> result;
4190   std::unordered_set<std::string> uniqueOptions;
4191
4192   cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS",
4193                                              nullptr, nullptr);
4194
4195   EvaluatedTargetPropertyEntries entries;
4196   if (cmProp linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
4197     std::vector<std::string> options = cmExpandedList(*linkOptions);
4198     for (const auto& option : options) {
4199       std::unique_ptr<TargetPropertyEntry> entry =
4200         CreateTargetPropertyEntry(option);
4201       entries.Entries.emplace_back(EvaluateTargetPropertyEntry(
4202         this, config, language, &dagChecker, *entry));
4203     }
4204   }
4205   processOptions(this, entries, result, uniqueOptions, false,
4206                  "static library link options", OptionsParse::Shell);
4207
4208   return result;
4209 }
4210
4211 namespace {
4212 void processLinkDirectories(cmGeneratorTarget const* tgt,
4213                             EvaluatedTargetPropertyEntries& entries,
4214                             std::vector<BT<std::string>>& directories,
4215                             std::unordered_set<std::string>& uniqueDirectories,
4216                             bool debugDirectories)
4217 {
4218   for (EvaluatedTargetPropertyEntry& entry : entries.Entries) {
4219     cmLinkImplItem const& item = entry.LinkImplItem;
4220     std::string const& targetName = item.AsStr();
4221
4222     std::string usedDirectories;
4223     for (std::string& entryDirectory : entry.Values) {
4224       if (!cmSystemTools::FileIsFullPath(entryDirectory)) {
4225         std::ostringstream e;
4226         bool noMessage = false;
4227         MessageType messageType = MessageType::FATAL_ERROR;
4228         if (!targetName.empty()) {
4229           /* clang-format off */
4230           e << "Target \"" << targetName << "\" contains relative "
4231             "path in its INTERFACE_LINK_DIRECTORIES:\n"
4232             "  \"" << entryDirectory << "\"";
4233           /* clang-format on */
4234         } else {
4235           switch (tgt->GetPolicyStatusCMP0081()) {
4236             case cmPolicies::WARN: {
4237               e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0081) << "\n";
4238               messageType = MessageType::AUTHOR_WARNING;
4239             } break;
4240             case cmPolicies::OLD:
4241               noMessage = true;
4242               break;
4243             case cmPolicies::REQUIRED_IF_USED:
4244             case cmPolicies::REQUIRED_ALWAYS:
4245             case cmPolicies::NEW:
4246               // Issue the fatal message.
4247               break;
4248           }
4249           e << "Found relative path while evaluating link directories of "
4250                "\""
4251             << tgt->GetName() << "\":\n  \"" << entryDirectory << "\"\n";
4252         }
4253         if (!noMessage) {
4254           tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
4255           if (messageType == MessageType::FATAL_ERROR) {
4256             return;
4257           }
4258         }
4259       }
4260
4261       // Sanitize the path the same way the link_directories command does
4262       // in case projects set the LINK_DIRECTORIES property directly.
4263       cmSystemTools::ConvertToUnixSlashes(entryDirectory);
4264       if (uniqueDirectories.insert(entryDirectory).second) {
4265         directories.emplace_back(entryDirectory, entry.Backtrace);
4266         if (debugDirectories) {
4267           usedDirectories += " * " + entryDirectory + "\n";
4268         }
4269       }
4270     }
4271     if (!usedDirectories.empty()) {
4272       tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
4273         MessageType::LOG,
4274         std::string("Used link directories for target ") + tgt->GetName() +
4275           ":\n" + usedDirectories,
4276         entry.Backtrace);
4277     }
4278   }
4279 }
4280 }
4281
4282 void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result,
4283                                            const std::string& config,
4284                                            const std::string& language) const
4285 {
4286   std::vector<BT<std::string>> tmp =
4287     this->GetLinkDirectories(config, language);
4288   result.reserve(tmp.size());
4289   for (BT<std::string>& v : tmp) {
4290     result.emplace_back(std::move(v.Value));
4291   }
4292 }
4293
4294 std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories(
4295   std::string const& config, std::string const& language) const
4296 {
4297   std::vector<BT<std::string>> result;
4298   std::unordered_set<std::string> uniqueDirectories;
4299
4300   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr,
4301                                              nullptr);
4302
4303   std::vector<std::string> debugProperties;
4304   this->Makefile->GetDefExpandList("CMAKE_DEBUG_TARGET_PROPERTIES",
4305                                    debugProperties);
4306
4307   bool debugDirectories = !this->DebugLinkDirectoriesDone &&
4308     cm::contains(debugProperties, "LINK_DIRECTORIES");
4309
4310   if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
4311     this->DebugLinkDirectoriesDone = true;
4312   }
4313
4314   EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
4315     this, config, language, &dagChecker, this->LinkDirectoriesEntries);
4316
4317   AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language,
4318                       &dagChecker, entries,
4319                       this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
4320
4321   processLinkDirectories(this, entries, result, uniqueDirectories,
4322                          debugDirectories);
4323
4324   return result;
4325 }
4326
4327 void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
4328                                        const std::string& config,
4329                                        const std::string& language) const
4330 {
4331   std::vector<BT<std::string>> tmp = this->GetLinkDepends(config, language);
4332   result.reserve(tmp.size());
4333   for (BT<std::string>& v : tmp) {
4334     result.emplace_back(std::move(v.Value));
4335   }
4336 }
4337
4338 std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends(
4339   std::string const& config, std::string const& language) const
4340 {
4341   std::vector<BT<std::string>> result;
4342   std::unordered_set<std::string> uniqueOptions;
4343   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
4344                                              nullptr);
4345
4346   EvaluatedTargetPropertyEntries entries;
4347   if (cmProp linkDepends = this->GetProperty("LINK_DEPENDS")) {
4348     std::vector<std::string> depends = cmExpandedList(*linkDepends);
4349     for (const auto& depend : depends) {
4350       std::unique_ptr<TargetPropertyEntry> entry =
4351         CreateTargetPropertyEntry(depend);
4352       entries.Entries.emplace_back(EvaluateTargetPropertyEntry(
4353         this, config, language, &dagChecker, *entry));
4354     }
4355   }
4356   AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language,
4357                       &dagChecker, entries,
4358                       this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
4359
4360   processOptions(this, entries, result, uniqueOptions, false, "link depends",
4361                  OptionsParse::None);
4362
4363   return result;
4364 }
4365
4366 void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
4367 {
4368   if (this->IsImported()) {
4369     return;
4370   }
4371   cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
4372
4373   // Get the names.
4374   cmGeneratorTarget::Names targetNames;
4375   if (this->GetType() == cmStateEnums::EXECUTABLE) {
4376     targetNames = this->GetExecutableNames(config);
4377   } else if (this->GetType() == cmStateEnums::STATIC_LIBRARY ||
4378              this->GetType() == cmStateEnums::SHARED_LIBRARY ||
4379              this->GetType() == cmStateEnums::MODULE_LIBRARY) {
4380     targetNames = this->GetLibraryNames(config);
4381   } else {
4382     return;
4383   }
4384
4385   // Get the directory.
4386   std::string dir =
4387     this->GetDirectory(config, cmStateEnums::RuntimeBinaryArtifact);
4388
4389   // Add each name.
4390   std::string f;
4391   if (!targetNames.Output.empty()) {
4392     f = cmStrCat(dir, '/', targetNames.Output);
4393     gg->AddToManifest(f);
4394   }
4395   if (!targetNames.SharedObject.empty()) {
4396     f = cmStrCat(dir, '/', targetNames.SharedObject);
4397     gg->AddToManifest(f);
4398   }
4399   if (!targetNames.Real.empty()) {
4400     f = cmStrCat(dir, '/', targetNames.Real);
4401     gg->AddToManifest(f);
4402   }
4403   if (!targetNames.PDB.empty()) {
4404     f = cmStrCat(dir, '/', targetNames.PDB);
4405     gg->AddToManifest(f);
4406   }
4407   if (!targetNames.ImportLibrary.empty()) {
4408     f =
4409       cmStrCat(this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact),
4410                '/', targetNames.ImportLibrary);
4411     gg->AddToManifest(f);
4412   }
4413 }
4414
4415 bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
4416 {
4417   std::vector<BT<std::string>> features = this->GetCompileFeatures(config);
4418   for (BT<std::string> const& f : features) {
4419     if (!this->Makefile->AddRequiredTargetFeature(this->Target, f.Value)) {
4420       return false;
4421     }
4422   }
4423   return true;
4424 }
4425
4426 std::string cmGeneratorTarget::GetImportedLibName(
4427   std::string const& config) const
4428 {
4429   if (cmGeneratorTarget::ImportInfo const* info =
4430         this->GetImportInfo(config)) {
4431     return info->LibName;
4432   }
4433   return std::string();
4434 }
4435
4436 std::string cmGeneratorTarget::GetFullPath(const std::string& config,
4437                                            cmStateEnums::ArtifactType artifact,
4438                                            bool realname) const
4439 {
4440   if (this->IsImported()) {
4441     return this->Target->ImportedGetFullPath(config, artifact);
4442   }
4443   return this->NormalGetFullPath(config, artifact, realname);
4444 }
4445
4446 std::string cmGeneratorTarget::NormalGetFullPath(
4447   const std::string& config, cmStateEnums::ArtifactType artifact,
4448   bool realname) const
4449 {
4450   std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/');
4451   if (this->IsAppBundleOnApple()) {
4452     fpath =
4453       cmStrCat(this->BuildBundleDirectory(fpath, config, FullLevel), '/');
4454   }
4455
4456   // Add the full name of the target.
4457   switch (artifact) {
4458     case cmStateEnums::RuntimeBinaryArtifact:
4459       if (realname) {
4460         fpath += this->NormalGetRealName(config);
4461       } else {
4462         fpath +=
4463           this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact);
4464       }
4465       break;
4466     case cmStateEnums::ImportLibraryArtifact:
4467       fpath += this->GetFullName(config, cmStateEnums::ImportLibraryArtifact);
4468       break;
4469   }
4470   return fpath;
4471 }
4472
4473 std::string cmGeneratorTarget::NormalGetRealName(
4474   const std::string& config) const
4475 {
4476   // This should not be called for imported targets.
4477   // TODO: Split cmTarget into a class hierarchy to get compile-time
4478   // enforcement of the limited imported target API.
4479   if (this->IsImported()) {
4480     std::string msg = cmStrCat("NormalGetRealName called on imported target: ",
4481                                this->GetName());
4482     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
4483   }
4484
4485   if (this->GetType() == cmStateEnums::EXECUTABLE) {
4486     // Compute the real name that will be built.
4487     return this->GetExecutableNames(config).Real;
4488   }
4489   // Compute the real name that will be built.
4490   return this->GetLibraryNames(config).Real;
4491 }
4492
4493 cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
4494   const std::string& config) const
4495 {
4496   cmGeneratorTarget::Names targetNames;
4497
4498   // This should not be called for imported targets.
4499   // TODO: Split cmTarget into a class hierarchy to get compile-time
4500   // enforcement of the limited imported target API.
4501   if (this->IsImported()) {
4502     std::string msg =
4503       cmStrCat("GetLibraryNames called on imported target: ", this->GetName());
4504     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
4505   }
4506
4507   // Check for library version properties.
4508   cmProp version = this->GetProperty("VERSION");
4509   cmProp soversion = this->GetProperty("SOVERSION");
4510   if (!this->HasSOName(config) ||
4511       this->Makefile->IsOn("CMAKE_PLATFORM_NO_VERSIONED_SONAME") ||
4512       this->IsFrameworkOnApple()) {
4513     // Versioning is supported only for shared libraries and modules,
4514     // and then only when the platform supports an soname flag.
4515     version = nullptr;
4516     soversion = nullptr;
4517   }
4518   if (version && !soversion) {
4519     // The soversion must be set if the library version is set.  Use
4520     // the library version as the soversion.
4521     soversion = version;
4522   }
4523   if (!version && soversion) {
4524     // Use the soversion as the library version.
4525     version = soversion;
4526   }
4527
4528   // Get the components of the library name.
4529   std::string prefix;
4530   std::string suffix;
4531   this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
4532                             prefix, targetNames.Base, suffix);
4533
4534   // The library name.
4535   targetNames.Output = prefix + targetNames.Base + suffix;
4536
4537   if (this->IsFrameworkOnApple()) {
4538     targetNames.Real = prefix;
4539     if (!this->Makefile->PlatformIsAppleEmbedded()) {
4540       targetNames.Real += "Versions/";
4541       targetNames.Real += this->GetFrameworkVersion();
4542       targetNames.Real += "/";
4543     }
4544     targetNames.Real += targetNames.Base + suffix;
4545     targetNames.SharedObject = targetNames.Real + suffix;
4546   } else {
4547     // The library's soname.
4548     this->ComputeVersionedName(targetNames.SharedObject, prefix,
4549                                targetNames.Base, suffix, targetNames.Output,
4550                                (soversion ? soversion->c_str() : nullptr));
4551
4552     // The library's real name on disk.
4553     this->ComputeVersionedName(targetNames.Real, prefix, targetNames.Base,
4554                                suffix, targetNames.Output,
4555                                (version ? version->c_str() : nullptr));
4556   }
4557
4558   // The import library name.
4559   if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
4560       this->GetType() == cmStateEnums::MODULE_LIBRARY) {
4561     targetNames.ImportLibrary =
4562       this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
4563   }
4564
4565   // The program database file name.
4566   targetNames.PDB = this->GetPDBName(config);
4567
4568   return targetNames;
4569 }
4570
4571 cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
4572   const std::string& config) const
4573 {
4574   cmGeneratorTarget::Names targetNames;
4575
4576   // This should not be called for imported targets.
4577   // TODO: Split cmTarget into a class hierarchy to get compile-time
4578   // enforcement of the limited imported target API.
4579   if (this->IsImported()) {
4580     std::string msg = cmStrCat(
4581       "GetExecutableNames called on imported target: ", this->GetName());
4582     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
4583   }
4584
4585 // This versioning is supported only for executables and then only
4586 // when the platform supports symbolic links.
4587 #if defined(_WIN32) && !defined(__CYGWIN__)
4588   const char* version = nullptr;
4589 #else
4590   // Check for executable version properties.
4591   const char* version = nullptr;
4592   if (cmProp p = this->GetProperty("VERSION")) {
4593     version = p->c_str();
4594   }
4595   if (this->GetType() != cmStateEnums::EXECUTABLE ||
4596       this->Makefile->IsOn("XCODE")) {
4597     version = nullptr;
4598   }
4599 #endif
4600
4601   // Get the components of the executable name.
4602   std::string prefix;
4603   std::string suffix;
4604   this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
4605                             prefix, targetNames.Base, suffix);
4606
4607   // The executable name.
4608   targetNames.Output = prefix + targetNames.Base + suffix;
4609
4610 // The executable's real name on disk.
4611 #if defined(__CYGWIN__)
4612   targetNames.Real = prefix + targetNames.Base;
4613 #else
4614   targetNames.Real = targetNames.Output;
4615 #endif
4616   if (version) {
4617     targetNames.Real += "-";
4618     targetNames.Real += version;
4619   }
4620 #if defined(__CYGWIN__)
4621   targetNames.Real += suffix;
4622 #endif
4623
4624   // The import library name.
4625   targetNames.ImportLibrary =
4626     this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
4627
4628   // The program database file name.
4629   targetNames.PDB = this->GetPDBName(config);
4630
4631   return targetNames;
4632 }
4633
4634 std::string cmGeneratorTarget::GetFullNameInternal(
4635   const std::string& config, cmStateEnums::ArtifactType artifact) const
4636 {
4637   std::string prefix;
4638   std::string base;
4639   std::string suffix;
4640   this->GetFullNameInternal(config, artifact, prefix, base, suffix);
4641   return prefix + base + suffix;
4642 }
4643
4644 std::string cmGeneratorTarget::ImportedGetLocation(
4645   const std::string& config) const
4646 {
4647   assert(this->IsImported());
4648   return this->Target->ImportedGetFullPath(
4649     config, cmStateEnums::RuntimeBinaryArtifact);
4650 }
4651
4652 std::string cmGeneratorTarget::GetFullNameImported(
4653   const std::string& config, cmStateEnums::ArtifactType artifact) const
4654 {
4655   return cmSystemTools::GetFilenameName(
4656     this->Target->ImportedGetFullPath(config, artifact));
4657 }
4658
4659 void cmGeneratorTarget::GetFullNameInternal(
4660   const std::string& config, cmStateEnums::ArtifactType artifact,
4661   std::string& outPrefix, std::string& outBase, std::string& outSuffix) const
4662 {
4663   // Use just the target name for non-main target types.
4664   if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
4665       this->GetType() != cmStateEnums::SHARED_LIBRARY &&
4666       this->GetType() != cmStateEnums::MODULE_LIBRARY &&
4667       this->GetType() != cmStateEnums::EXECUTABLE) {
4668     outPrefix.clear();
4669     outBase = this->GetName();
4670     outSuffix.clear();
4671     return;
4672   }
4673
4674   const bool isImportedLibraryArtifact =
4675     (artifact == cmStateEnums::ImportLibraryArtifact);
4676
4677   // Return an empty name for the import library if this platform
4678   // does not support import libraries.
4679   if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) {
4680     outPrefix.clear();
4681     outBase.clear();
4682     outSuffix.clear();
4683     return;
4684   }
4685
4686   // retrieve prefix and suffix
4687   std::string ll = this->GetLinkerLanguage(config);
4688   const char* targetPrefix = this->GetFilePrefixInternal(config, artifact, ll);
4689   const char* targetSuffix = this->GetFileSuffixInternal(config, artifact, ll);
4690
4691   // The implib option is only allowed for shared libraries, module
4692   // libraries, and executables.
4693   if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
4694       this->GetType() != cmStateEnums::MODULE_LIBRARY &&
4695       this->GetType() != cmStateEnums::EXECUTABLE) {
4696     artifact = cmStateEnums::RuntimeBinaryArtifact;
4697   }
4698
4699   // Compute the full name for main target types.
4700   const std::string configPostfix = this->GetFilePostfix(config);
4701
4702   // frameworks have directory prefix but no suffix
4703   std::string fw_prefix;
4704   if (this->IsFrameworkOnApple()) {
4705     fw_prefix =
4706       cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/');
4707     targetPrefix = fw_prefix.c_str();
4708     targetSuffix = nullptr;
4709   }
4710
4711   if (this->IsCFBundleOnApple()) {
4712     fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/');
4713     targetPrefix = fw_prefix.c_str();
4714     targetSuffix = nullptr;
4715   }
4716
4717   // Begin the final name with the prefix.
4718   outPrefix = targetPrefix ? targetPrefix : "";
4719
4720   // Append the target name or property-specified name.
4721   outBase += this->GetOutputName(config, artifact);
4722
4723   // Append the per-configuration postfix.
4724   // When using Xcode, the postfix should be part of the suffix rather than
4725   // the base, because the suffix ends up being used in Xcode's
4726   // EXECUTABLE_SUFFIX attribute.
4727   if (this->IsFrameworkOnApple() &&
4728       GetGlobalGenerator()->GetName() == "Xcode") {
4729     targetSuffix = configPostfix.c_str();
4730   } else {
4731     outBase += configPostfix;
4732   }
4733
4734   // Name shared libraries with their version number on some platforms.
4735   if (cmProp soversion = this->GetProperty("SOVERSION")) {
4736     if (this->GetType() == cmStateEnums::SHARED_LIBRARY &&
4737         !isImportedLibraryArtifact &&
4738         this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) {
4739       outBase += "-";
4740       outBase += *soversion;
4741     }
4742   }
4743
4744   // Append the suffix.
4745   outSuffix = targetSuffix ? targetSuffix : "";
4746 }
4747
4748 std::string cmGeneratorTarget::GetLinkerLanguage(
4749   const std::string& config) const
4750 {
4751   return this->GetLinkClosure(config)->LinkerLanguage;
4752 }
4753
4754 std::string cmGeneratorTarget::GetPDBOutputName(
4755   const std::string& config) const
4756 {
4757   std::string base =
4758     this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
4759
4760   std::vector<std::string> props;
4761   std::string configUpper = cmSystemTools::UpperCase(config);
4762   if (!configUpper.empty()) {
4763     // PDB_NAME_<CONFIG>
4764     props.push_back("PDB_NAME_" + configUpper);
4765   }
4766
4767   // PDB_NAME
4768   props.emplace_back("PDB_NAME");
4769
4770   for (std::string const& p : props) {
4771     if (cmProp outName = this->GetProperty(p)) {
4772       base = *outName;
4773       break;
4774     }
4775   }
4776   return base;
4777 }
4778
4779 std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
4780 {
4781   std::string prefix;
4782   std::string base;
4783   std::string suffix;
4784   this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
4785                             prefix, base, suffix);
4786
4787   std::vector<std::string> props;
4788   std::string configUpper = cmSystemTools::UpperCase(config);
4789   if (!configUpper.empty()) {
4790     // PDB_NAME_<CONFIG>
4791     props.push_back("PDB_NAME_" + configUpper);
4792   }
4793
4794   // PDB_NAME
4795   props.emplace_back("PDB_NAME");
4796
4797   for (std::string const& p : props) {
4798     if (cmProp outName = this->GetProperty(p)) {
4799       base = *outName;
4800       break;
4801     }
4802   }
4803   return prefix + base + ".pdb";
4804 }
4805
4806 std::string cmGeneratorTarget::GetObjectDirectory(
4807   std::string const& config) const
4808 {
4809   std::string obj_dir =
4810     this->GlobalGenerator->ExpandCFGIntDir(this->ObjectDirectory, config);
4811 #if defined(__APPLE__)
4812   // find and replace $(PROJECT_NAME) xcode placeholder
4813   const std::string projectName = this->LocalGenerator->GetProjectName();
4814   cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName);
4815   // Replace Xcode's placeholder for the object file directory since
4816   // installation and export scripts need to know the real directory.
4817   // Xcode has build-time settings (e.g. for sanitizers) that affect this,
4818   // but we use the default here.  Users that want to enable sanitizers
4819   // will do so at the cost of object library installation and export.
4820   cmSystemTools::ReplaceString(obj_dir, "$(OBJECT_FILE_DIR_normal:base)",
4821                                "Objects-normal");
4822 #endif
4823   return obj_dir;
4824 }
4825
4826 void cmGeneratorTarget::GetTargetObjectNames(
4827   std::string const& config, std::vector<std::string>& objects) const
4828 {
4829   std::vector<cmSourceFile const*> objectSources;
4830   this->GetObjectSources(objectSources, config);
4831   std::map<cmSourceFile const*, std::string> mapping;
4832
4833   for (cmSourceFile const* sf : objectSources) {
4834     mapping[sf];
4835   }
4836
4837   this->LocalGenerator->ComputeObjectFilenames(mapping, this);
4838
4839   for (cmSourceFile const* src : objectSources) {
4840     // Find the object file name corresponding to this source file.
4841     auto map_it = mapping.find(src);
4842     // It must exist because we populated the mapping just above.
4843     assert(!map_it->second.empty());
4844     objects.push_back(map_it->second);
4845   }
4846 }
4847
4848 bool cmGeneratorTarget::StrictTargetComparison::operator()(
4849   cmGeneratorTarget const* t1, cmGeneratorTarget const* t2) const
4850 {
4851   int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
4852   if (nameResult == 0) {
4853     return strcmp(
4854              t1->GetLocalGenerator()->GetCurrentBinaryDirectory().c_str(),
4855              t2->GetLocalGenerator()->GetCurrentBinaryDirectory().c_str()) < 0;
4856   }
4857   return nameResult < 0;
4858 }
4859
4860 struct cmGeneratorTarget::SourceFileFlags
4861 cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
4862 {
4863   struct SourceFileFlags flags;
4864   this->ConstructSourceFileFlags();
4865   auto si = this->SourceFlagsMap.find(sf);
4866   if (si != this->SourceFlagsMap.end()) {
4867     flags = si->second;
4868   } else {
4869     // Handle the MACOSX_PACKAGE_LOCATION property on source files that
4870     // were not listed in one of the other lists.
4871     if (cmProp location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) {
4872       flags.MacFolder = location->c_str();
4873       const bool stripResources =
4874         this->GlobalGenerator->ShouldStripResourcePath(this->Makefile);
4875       if (*location == "Resources") {
4876         flags.Type = cmGeneratorTarget::SourceFileTypeResource;
4877         if (stripResources) {
4878           flags.MacFolder = "";
4879         }
4880       } else if (cmHasLiteralPrefix(*location, "Resources/")) {
4881         flags.Type = cmGeneratorTarget::SourceFileTypeDeepResource;
4882         if (stripResources) {
4883           flags.MacFolder += strlen("Resources/");
4884         }
4885       } else {
4886         flags.Type = cmGeneratorTarget::SourceFileTypeMacContent;
4887       }
4888     }
4889   }
4890   return flags;
4891 }
4892
4893 void cmGeneratorTarget::ConstructSourceFileFlags() const
4894 {
4895   if (this->SourceFileFlagsConstructed) {
4896     return;
4897   }
4898   this->SourceFileFlagsConstructed = true;
4899
4900   // Process public headers to mark the source files.
4901   if (cmProp files = this->GetProperty("PUBLIC_HEADER")) {
4902     std::vector<std::string> relFiles = cmExpandedList(*files);
4903     for (std::string const& relFile : relFiles) {
4904       if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) {
4905         SourceFileFlags& flags = this->SourceFlagsMap[sf];
4906         flags.MacFolder = "Headers";
4907         flags.Type = cmGeneratorTarget::SourceFileTypePublicHeader;
4908       }
4909     }
4910   }
4911
4912   // Process private headers after public headers so that they take
4913   // precedence if a file is listed in both.
4914   if (cmProp files = this->GetProperty("PRIVATE_HEADER")) {
4915     std::vector<std::string> relFiles = cmExpandedList(*files);
4916     for (std::string const& relFile : relFiles) {
4917       if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) {
4918         SourceFileFlags& flags = this->SourceFlagsMap[sf];
4919         flags.MacFolder = "PrivateHeaders";
4920         flags.Type = cmGeneratorTarget::SourceFileTypePrivateHeader;
4921       }
4922     }
4923   }
4924
4925   // Mark sources listed as resources.
4926   if (cmProp files = this->GetProperty("RESOURCE")) {
4927     std::vector<std::string> relFiles = cmExpandedList(*files);
4928     for (std::string const& relFile : relFiles) {
4929       if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) {
4930         SourceFileFlags& flags = this->SourceFlagsMap[sf];
4931         flags.MacFolder = "";
4932         if (!this->GlobalGenerator->ShouldStripResourcePath(this->Makefile)) {
4933           flags.MacFolder = "Resources";
4934         }
4935         flags.Type = cmGeneratorTarget::SourceFileTypeResource;
4936       }
4937     }
4938   }
4939 }
4940
4941 const cmGeneratorTarget::CompatibleInterfacesBase&
4942 cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const
4943 {
4944   cmGeneratorTarget::CompatibleInterfaces& compat =
4945     this->CompatibleInterfacesMap[config];
4946   if (!compat.Done) {
4947     compat.Done = true;
4948     compat.PropsBool.insert("POSITION_INDEPENDENT_CODE");
4949     compat.PropsString.insert("AUTOUIC_OPTIONS");
4950     std::vector<cmGeneratorTarget const*> const& deps =
4951       this->GetLinkImplementationClosure(config);
4952     for (cmGeneratorTarget const* li : deps) {
4953 #define CM_READ_COMPATIBLE_INTERFACE(X, x)                                    \
4954   if (cmProp prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) {            \
4955     std::vector<std::string> props;                                           \
4956     cmExpandList(*prop, props);                                               \
4957     compat.Props##x.insert(props.begin(), props.end());                       \
4958   }
4959       CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool)
4960       CM_READ_COMPATIBLE_INTERFACE(STRING, String)
4961       CM_READ_COMPATIBLE_INTERFACE(NUMBER_MIN, NumberMin)
4962       CM_READ_COMPATIBLE_INTERFACE(NUMBER_MAX, NumberMax)
4963 #undef CM_READ_COMPATIBLE_INTERFACE
4964     }
4965   }
4966   return compat;
4967 }
4968
4969 bool cmGeneratorTarget::IsLinkInterfaceDependentBoolProperty(
4970   const std::string& p, const std::string& config) const
4971 {
4972   if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
4973       this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
4974     return false;
4975   }
4976   return this->GetCompatibleInterfaces(config).PropsBool.count(p) > 0;
4977 }
4978
4979 bool cmGeneratorTarget::IsLinkInterfaceDependentStringProperty(
4980   const std::string& p, const std::string& config) const
4981 {
4982   if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
4983       this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
4984     return false;
4985   }
4986   return this->GetCompatibleInterfaces(config).PropsString.count(p) > 0;
4987 }
4988
4989 bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMinProperty(
4990   const std::string& p, const std::string& config) const
4991 {
4992   if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
4993       this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
4994     return false;
4995   }
4996   return this->GetCompatibleInterfaces(config).PropsNumberMin.count(p) > 0;
4997 }
4998
4999 bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMaxProperty(
5000   const std::string& p, const std::string& config) const
5001 {
5002   if (this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
5003       this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
5004     return false;
5005   }
5006   return this->GetCompatibleInterfaces(config).PropsNumberMax.count(p) > 0;
5007 }
5008
5009 enum CompatibleType
5010 {
5011   BoolType,
5012   StringType,
5013   NumberMinType,
5014   NumberMaxType
5015 };
5016
5017 template <typename PropertyType>
5018 PropertyType getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
5019                                                const std::string& prop,
5020                                                const std::string& config,
5021                                                CompatibleType, PropertyType*);
5022
5023 template <>
5024 bool getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
5025                                        const std::string& prop,
5026                                        const std::string& config,
5027                                        CompatibleType /*unused*/,
5028                                        bool* /*unused*/)
5029 {
5030   return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
5031 }
5032
5033 template <>
5034 const char* getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
5035                                               const std::string& prop,
5036                                               const std::string& config,
5037                                               CompatibleType t,
5038                                               const char** /*unused*/)
5039 {
5040   switch (t) {
5041     case BoolType:
5042       assert(false &&
5043              "String compatibility check function called for boolean");
5044       return nullptr;
5045     case StringType:
5046       return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
5047     case NumberMinType:
5048       return tgt->GetLinkInterfaceDependentNumberMinProperty(prop, config);
5049     case NumberMaxType:
5050       return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config);
5051   }
5052   assert(false && "Unreachable!");
5053   return nullptr;
5054 }
5055
5056 template <typename PropertyType>
5057 void checkPropertyConsistency(cmGeneratorTarget const* depender,
5058                               cmGeneratorTarget const* dependee,
5059                               const std::string& propName,
5060                               std::set<std::string>& emitted,
5061                               const std::string& config, CompatibleType t,
5062                               PropertyType* /*unused*/)
5063 {
5064   cmProp prop = dependee->GetProperty(propName);
5065   if (!prop) {
5066     return;
5067   }
5068
5069   std::vector<std::string> props = cmExpandedList(*prop);
5070   std::string pdir =
5071     cmStrCat(cmSystemTools::GetCMakeRoot(), "/Help/prop_tgt/");
5072
5073   for (std::string const& p : props) {
5074     std::string pname = cmSystemTools::HelpFileName(p);
5075     std::string pfile = pdir + pname + ".rst";
5076     if (cmSystemTools::FileExists(pfile, true)) {
5077       std::ostringstream e;
5078       e << "Target \"" << dependee->GetName() << "\" has property \"" << p
5079         << "\" listed in its " << propName
5080         << " property.  "
5081            "This is not allowed.  Only user-defined properties may appear "
5082            "listed in the "
5083         << propName << " property.";
5084       depender->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
5085                                                   e.str());
5086       return;
5087     }
5088     if (emitted.insert(p).second) {
5089       getLinkInterfaceDependentProperty<PropertyType>(depender, p, config, t,
5090                                                       nullptr);
5091       if (cmSystemTools::GetErrorOccuredFlag()) {
5092         return;
5093       }
5094     }
5095   }
5096 }
5097
5098 namespace {
5099 std::string intersect(const std::set<std::string>& s1,
5100                       const std::set<std::string>& s2)
5101 {
5102   std::set<std::string> intersect;
5103   std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(),
5104                         std::inserter(intersect, intersect.begin()));
5105   if (!intersect.empty()) {
5106     return *intersect.begin();
5107   }
5108   return "";
5109 }
5110
5111 std::string intersect(const std::set<std::string>& s1,
5112                       const std::set<std::string>& s2,
5113                       const std::set<std::string>& s3)
5114 {
5115   std::string result;
5116   result = intersect(s1, s2);
5117   if (!result.empty()) {
5118     return result;
5119   }
5120   result = intersect(s1, s3);
5121   if (!result.empty()) {
5122     return result;
5123   }
5124   return intersect(s2, s3);
5125 }
5126
5127 std::string intersect(const std::set<std::string>& s1,
5128                       const std::set<std::string>& s2,
5129                       const std::set<std::string>& s3,
5130                       const std::set<std::string>& s4)
5131 {
5132   std::string result;
5133   result = intersect(s1, s2);
5134   if (!result.empty()) {
5135     return result;
5136   }
5137   result = intersect(s1, s3);
5138   if (!result.empty()) {
5139     return result;
5140   }
5141   result = intersect(s1, s4);
5142   if (!result.empty()) {
5143     return result;
5144   }
5145   return intersect(s2, s3, s4);
5146 }
5147 }
5148
5149 void cmGeneratorTarget::CheckPropertyCompatibility(
5150   cmComputeLinkInformation& info, const std::string& config) const
5151 {
5152   const cmComputeLinkInformation::ItemVector& deps = info.GetItems();
5153
5154   std::set<std::string> emittedBools;
5155   static const std::string strBool = "COMPATIBLE_INTERFACE_BOOL";
5156   std::set<std::string> emittedStrings;
5157   static const std::string strString = "COMPATIBLE_INTERFACE_STRING";
5158   std::set<std::string> emittedMinNumbers;
5159   static const std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN";
5160   std::set<std::string> emittedMaxNumbers;
5161   static const std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX";
5162
5163   for (auto const& dep : deps) {
5164     if (!dep.Target) {
5165       continue;
5166     }
5167
5168     checkPropertyConsistency<bool>(this, dep.Target, strBool, emittedBools,
5169                                    config, BoolType, nullptr);
5170     if (cmSystemTools::GetErrorOccuredFlag()) {
5171       return;
5172     }
5173     checkPropertyConsistency<const char*>(this, dep.Target, strString,
5174                                           emittedStrings, config, StringType,
5175                                           nullptr);
5176     if (cmSystemTools::GetErrorOccuredFlag()) {
5177       return;
5178     }
5179     checkPropertyConsistency<const char*>(this, dep.Target, strNumMin,
5180                                           emittedMinNumbers, config,
5181                                           NumberMinType, nullptr);
5182     if (cmSystemTools::GetErrorOccuredFlag()) {
5183       return;
5184     }
5185     checkPropertyConsistency<const char*>(this, dep.Target, strNumMax,
5186                                           emittedMaxNumbers, config,
5187                                           NumberMaxType, nullptr);
5188     if (cmSystemTools::GetErrorOccuredFlag()) {
5189       return;
5190     }
5191   }
5192
5193   std::string prop = intersect(emittedBools, emittedStrings, emittedMinNumbers,
5194                                emittedMaxNumbers);
5195
5196   if (!prop.empty()) {
5197     // Use a sorted std::vector to keep the error message sorted.
5198     std::vector<std::string> props;
5199     auto i = emittedBools.find(prop);
5200     if (i != emittedBools.end()) {
5201       props.push_back(strBool);
5202     }
5203     i = emittedStrings.find(prop);
5204     if (i != emittedStrings.end()) {
5205       props.push_back(strString);
5206     }
5207     i = emittedMinNumbers.find(prop);
5208     if (i != emittedMinNumbers.end()) {
5209       props.push_back(strNumMin);
5210     }
5211     i = emittedMaxNumbers.find(prop);
5212     if (i != emittedMaxNumbers.end()) {
5213       props.push_back(strNumMax);
5214     }
5215     std::sort(props.begin(), props.end());
5216
5217     std::string propsString = cmStrCat(
5218       cmJoin(cmMakeRange(props).retreat(1), ", "), " and the ", props.back());
5219
5220     std::ostringstream e;
5221     e << "Property \"" << prop << "\" appears in both the " << propsString
5222       << " property in the dependencies of target \"" << this->GetName()
5223       << "\".  This is not allowed. A property may only require "
5224          "compatibility "
5225          "in a boolean interpretation, a numeric minimum, a numeric maximum "
5226          "or a "
5227          "string interpretation, but not a mixture.";
5228     this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str());
5229   }
5230 }
5231
5232 template <typename PropertyType>
5233 std::string valueAsString(PropertyType);
5234 template <>
5235 std::string valueAsString<bool>(bool value)
5236 {
5237   return value ? "TRUE" : "FALSE";
5238 }
5239 template <>
5240 std::string valueAsString<const char*>(const char* value)
5241 {
5242   return value ? value : "(unset)";
5243 }
5244 template <>
5245 std::string valueAsString<std::string>(std::string value)
5246 {
5247   return value;
5248 }
5249 template <>
5250 std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/)
5251 {
5252   return "(unset)";
5253 }
5254
5255 std::string compatibilityType(CompatibleType t)
5256 {
5257   switch (t) {
5258     case BoolType:
5259       return "Boolean compatibility";
5260     case StringType:
5261       return "String compatibility";
5262     case NumberMaxType:
5263       return "Numeric maximum compatibility";
5264     case NumberMinType:
5265       return "Numeric minimum compatibility";
5266   }
5267   assert(false && "Unreachable!");
5268   return "";
5269 }
5270
5271 std::string compatibilityAgree(CompatibleType t, bool dominant)
5272 {
5273   switch (t) {
5274     case BoolType:
5275     case StringType:
5276       return dominant ? "(Disagree)\n" : "(Agree)\n";
5277     case NumberMaxType:
5278     case NumberMinType:
5279       return dominant ? "(Dominant)\n" : "(Ignored)\n";
5280   }
5281   assert(false && "Unreachable!");
5282   return "";
5283 }
5284
5285 template <typename PropertyType>
5286 PropertyType getTypedProperty(
5287   cmGeneratorTarget const* tgt, const std::string& prop,
5288   cmGeneratorExpressionInterpreter* genexInterpreter = nullptr);
5289
5290 template <>
5291 bool getTypedProperty<bool>(cmGeneratorTarget const* tgt,
5292                             const std::string& prop,
5293                             cmGeneratorExpressionInterpreter* genexInterpreter)
5294 {
5295   if (genexInterpreter == nullptr) {
5296     return tgt->GetPropertyAsBool(prop);
5297   }
5298
5299   cmProp value = tgt->GetProperty(prop);
5300   return cmIsOn(
5301     genexInterpreter->Evaluate(value ? value->c_str() : nullptr, prop));
5302 }
5303
5304 template <>
5305 const char* getTypedProperty<const char*>(
5306   cmGeneratorTarget const* tgt, const std::string& prop,
5307   cmGeneratorExpressionInterpreter* genexInterpreter)
5308 {
5309   cmProp value = tgt->GetProperty(prop);
5310
5311   if (genexInterpreter == nullptr) {
5312     return value ? value->c_str() : nullptr;
5313   }
5314
5315   return genexInterpreter->Evaluate(value ? value->c_str() : nullptr, prop)
5316     .c_str();
5317 }
5318
5319 template <>
5320 std::string getTypedProperty<std::string>(
5321   cmGeneratorTarget const* tgt, const std::string& prop,
5322   cmGeneratorExpressionInterpreter* genexInterpreter)
5323 {
5324   cmProp value = tgt->GetProperty(prop);
5325
5326   if (genexInterpreter == nullptr) {
5327     return valueAsString(value ? value->c_str() : nullptr);
5328   }
5329
5330   return genexInterpreter->Evaluate(value ? value->c_str() : nullptr, prop);
5331 }
5332
5333 template <typename PropertyType>
5334 PropertyType impliedValue(PropertyType);
5335 template <>
5336 bool impliedValue<bool>(bool /*unused*/)
5337 {
5338   return false;
5339 }
5340 template <>
5341 const char* impliedValue<const char*>(const char* /*unused*/)
5342 {
5343   return "";
5344 }
5345 template <>
5346 std::string impliedValue<std::string>(std::string /*unused*/) // NOLINT(*)
5347 {
5348   return std::string();
5349 }
5350
5351 template <typename PropertyType>
5352 std::pair<bool, PropertyType> consistentProperty(PropertyType lhs,
5353                                                  PropertyType rhs,
5354                                                  CompatibleType t);
5355
5356 template <>
5357 std::pair<bool, bool> consistentProperty(bool lhs, bool rhs,
5358                                          CompatibleType /*unused*/)
5359 {
5360   return { lhs == rhs, lhs };
5361 }
5362
5363 std::pair<bool, const char*> consistentStringProperty(const char* lhs,
5364                                                       const char* rhs)
5365 {
5366   const bool b = strcmp(lhs, rhs) == 0;
5367   return { b, b ? lhs : nullptr };
5368 }
5369
5370 std::pair<bool, std::string> consistentStringProperty(const std::string& lhs,
5371                                                       const std::string& rhs)
5372 {
5373   const bool b = lhs == rhs;
5374   return { b, b ? lhs : valueAsString(nullptr) };
5375 }
5376
5377 std::pair<bool, const char*> consistentNumberProperty(const char* lhs,
5378                                                       const char* rhs,
5379                                                       CompatibleType t)
5380 {
5381   char* pEnd;
5382
5383   long lnum = strtol(lhs, &pEnd, 0);
5384   if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) {
5385     return { false, nullptr };
5386   }
5387
5388   long rnum = strtol(rhs, &pEnd, 0);
5389   if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) {
5390     return { false, nullptr };
5391   }
5392
5393   if (t == NumberMaxType) {
5394     return { true, std::max(lnum, rnum) == lnum ? lhs : rhs };
5395   }
5396
5397   return { true, std::min(lnum, rnum) == lnum ? lhs : rhs };
5398 }
5399
5400 template <>
5401 std::pair<bool, const char*> consistentProperty(const char* lhs,
5402                                                 const char* rhs,
5403                                                 CompatibleType t)
5404 {
5405   if (!lhs && !rhs) {
5406     return { true, lhs };
5407   }
5408   if (!lhs) {
5409     return { true, rhs };
5410   }
5411   if (!rhs) {
5412     return { true, lhs };
5413   }
5414
5415   switch (t) {
5416     case BoolType: {
5417       bool same = cmIsOn(lhs) == cmIsOn(rhs);
5418       return { same, same ? lhs : nullptr };
5419     }
5420     case StringType:
5421       return consistentStringProperty(lhs, rhs);
5422     case NumberMinType:
5423     case NumberMaxType:
5424       return consistentNumberProperty(lhs, rhs, t);
5425   }
5426   assert(false && "Unreachable!");
5427   return { false, nullptr };
5428 }
5429
5430 std::pair<bool, std::string> consistentProperty(const std::string& lhs,
5431                                                 const std::string& rhs,
5432                                                 CompatibleType t)
5433 {
5434   const std::string null_ptr = valueAsString(nullptr);
5435
5436   if (lhs == null_ptr && rhs == null_ptr) {
5437     return { true, lhs };
5438   }
5439   if (lhs == null_ptr) {
5440     return { true, rhs };
5441   }
5442   if (rhs == null_ptr) {
5443     return { true, lhs };
5444   }
5445
5446   switch (t) {
5447     case BoolType: {
5448       bool same = cmIsOn(lhs) == cmIsOn(rhs);
5449       return { same, same ? lhs : null_ptr };
5450     }
5451     case StringType:
5452       return consistentStringProperty(lhs, rhs);
5453     case NumberMinType:
5454     case NumberMaxType: {
5455       auto value = consistentNumberProperty(lhs.c_str(), rhs.c_str(), t);
5456       return { value.first,
5457                value.first ? std::string(value.second) : null_ptr };
5458     }
5459   }
5460   assert(false && "Unreachable!");
5461   return { false, null_ptr };
5462 }
5463
5464 template <typename PropertyType>
5465 PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
5466                                                  const std::string& p,
5467                                                  const std::string& config,
5468                                                  const char* defaultValue,
5469                                                  CompatibleType t,
5470                                                  PropertyType* /*unused*/)
5471 {
5472   PropertyType propContent = getTypedProperty<PropertyType>(tgt, p);
5473
5474   std::vector<std::string> headPropKeys = tgt->GetPropertyKeys();
5475   const bool explicitlySet = cm::contains(headPropKeys, p);
5476
5477   const bool impliedByUse = tgt->IsNullImpliedByLinkLibraries(p);
5478   assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet));
5479
5480   std::vector<cmGeneratorTarget const*> const& deps =
5481     tgt->GetLinkImplementationClosure(config);
5482
5483   if (deps.empty()) {
5484     return propContent;
5485   }
5486   bool propInitialized = explicitlySet;
5487
5488   std::string report = cmStrCat(" * Target \"", tgt->GetName());
5489   if (explicitlySet) {
5490     report += "\" has property content \"";
5491     report += valueAsString<PropertyType>(propContent);
5492     report += "\"\n";
5493   } else if (impliedByUse) {
5494     report += "\" property is implied by use.\n";
5495   } else {
5496     report += "\" property not set.\n";
5497   }
5498
5499   std::string interfaceProperty = "INTERFACE_" + p;
5500   std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter;
5501   if (p == "POSITION_INDEPENDENT_CODE") {
5502     genexInterpreter = cm::make_unique<cmGeneratorExpressionInterpreter>(
5503       tgt->GetLocalGenerator(), config, tgt);
5504   }
5505
5506   for (cmGeneratorTarget const* theTarget : deps) {
5507     // An error should be reported if one dependency
5508     // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
5509     // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the
5510     // target itself has a POSITION_INDEPENDENT_CODE which disagrees
5511     // with a dependency.
5512
5513     std::vector<std::string> propKeys = theTarget->GetPropertyKeys();
5514
5515     const bool ifaceIsSet = cm::contains(propKeys, interfaceProperty);
5516     PropertyType ifacePropContent = getTypedProperty<PropertyType>(
5517       theTarget, interfaceProperty, genexInterpreter.get());
5518
5519     std::string reportEntry;
5520     if (ifaceIsSet) {
5521       reportEntry += " * Target \"";
5522       reportEntry += theTarget->GetName();
5523       reportEntry += "\" property value \"";
5524       reportEntry += valueAsString<PropertyType>(ifacePropContent);
5525       reportEntry += "\" ";
5526     }
5527
5528     if (explicitlySet) {
5529       if (ifaceIsSet) {
5530         std::pair<bool, PropertyType> consistent =
5531           consistentProperty(propContent, ifacePropContent, t);
5532         report += reportEntry;
5533         report += compatibilityAgree(t, propContent != consistent.second);
5534         if (!consistent.first) {
5535           std::ostringstream e;
5536           e << "Property " << p << " on target \"" << tgt->GetName()
5537             << "\" does\nnot match the "
5538                "INTERFACE_"
5539             << p
5540             << " property requirement\nof "
5541                "dependency \""
5542             << theTarget->GetName() << "\".\n";
5543           cmSystemTools::Error(e.str());
5544           break;
5545         }
5546         propContent = consistent.second;
5547         continue;
5548       }
5549       // Explicitly set on target and not set in iface. Can't disagree.
5550       continue;
5551     }
5552     if (impliedByUse) {
5553       propContent = impliedValue<PropertyType>(propContent);
5554
5555       if (ifaceIsSet) {
5556         std::pair<bool, PropertyType> consistent =
5557           consistentProperty(propContent, ifacePropContent, t);
5558         report += reportEntry;
5559         report += compatibilityAgree(t, propContent != consistent.second);
5560         if (!consistent.first) {
5561           std::ostringstream e;
5562           e << "Property " << p << " on target \"" << tgt->GetName()
5563             << "\" is\nimplied to be " << defaultValue
5564             << " because it was used to determine the link libraries\n"
5565                "already. The INTERFACE_"
5566             << p << " property on\ndependency \"" << theTarget->GetName()
5567             << "\" is in conflict.\n";
5568           cmSystemTools::Error(e.str());
5569           break;
5570         }
5571         propContent = consistent.second;
5572         continue;
5573       }
5574       // Implicitly set on target and not set in iface. Can't disagree.
5575       continue;
5576     }
5577     if (ifaceIsSet) {
5578       if (propInitialized) {
5579         std::pair<bool, PropertyType> consistent =
5580           consistentProperty(propContent, ifacePropContent, t);
5581         report += reportEntry;
5582         report += compatibilityAgree(t, propContent != consistent.second);
5583         if (!consistent.first) {
5584           std::ostringstream e;
5585           e << "The INTERFACE_" << p << " property of \""
5586             << theTarget->GetName() << "\" does\nnot agree with the value of "
5587             << p << " already determined\nfor \"" << tgt->GetName() << "\".\n";
5588           cmSystemTools::Error(e.str());
5589           break;
5590         }
5591         propContent = consistent.second;
5592         continue;
5593       }
5594       report += reportEntry + "(Interface set)\n";
5595       propContent = ifacePropContent;
5596       propInitialized = true;
5597     } else {
5598       // Not set. Nothing to agree on.
5599       continue;
5600     }
5601   }
5602
5603   tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent),
5604                             report, compatibilityType(t));
5605   return propContent;
5606 }
5607
5608 bool cmGeneratorTarget::SetDeviceLink(bool deviceLink)
5609 {
5610   bool previous = this->DeviceLink;
5611   this->DeviceLink = deviceLink;
5612   return previous;
5613 }
5614
5615 bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty(
5616   const std::string& p, const std::string& config) const
5617 {
5618   return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
5619                                                    BoolType, nullptr);
5620 }
5621
5622 std::string cmGeneratorTarget::GetLinkInterfaceDependentStringAsBoolProperty(
5623   const std::string& p, const std::string& config) const
5624 {
5625   return checkInterfacePropertyCompatibility<std::string>(
5626     this, p, config, "FALSE", BoolType, nullptr);
5627 }
5628
5629 const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty(
5630   const std::string& p, const std::string& config) const
5631 {
5632   return checkInterfacePropertyCompatibility<const char*>(
5633     this, p, config, "empty", StringType, nullptr);
5634 }
5635
5636 const char* cmGeneratorTarget::GetLinkInterfaceDependentNumberMinProperty(
5637   const std::string& p, const std::string& config) const
5638 {
5639   return checkInterfacePropertyCompatibility<const char*>(
5640     this, p, config, "empty", NumberMinType, nullptr);
5641 }
5642
5643 const char* cmGeneratorTarget::GetLinkInterfaceDependentNumberMaxProperty(
5644   const std::string& p, const std::string& config) const
5645 {
5646   return checkInterfacePropertyCompatibility<const char*>(
5647     this, p, config, "empty", NumberMaxType, nullptr);
5648 }
5649
5650 cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation(
5651   const std::string& config) const
5652 {
5653   // Lookup any existing information for this configuration.
5654   std::string key(cmSystemTools::UpperCase(config));
5655   auto i = this->LinkInformation.find(key);
5656   if (i == this->LinkInformation.end()) {
5657     // Compute information for this configuration.
5658     auto info = cm::make_unique<cmComputeLinkInformation>(this, config);
5659     if (info && !info->Compute()) {
5660       info.reset();
5661     }
5662
5663     // Store the information for this configuration.
5664     i = this->LinkInformation.emplace(key, std::move(info)).first;
5665
5666     if (i->second) {
5667       this->CheckPropertyCompatibility(*i->second, config);
5668     }
5669   }
5670   return i->second.get();
5671 }
5672
5673 void cmGeneratorTarget::GetTargetVersion(int& major, int& minor) const
5674 {
5675   int patch;
5676   this->GetTargetVersion("VERSION", major, minor, patch);
5677 }
5678
5679 void cmGeneratorTarget::GetTargetVersionFallback(
5680   const std::string& property, const std::string& fallback_property,
5681   int& major, int& minor, int& patch) const
5682 {
5683   if (this->GetProperty(property)) {
5684     this->GetTargetVersion(property, major, minor, patch);
5685   } else {
5686     this->GetTargetVersion(fallback_property, major, minor, patch);
5687   }
5688 }
5689
5690 void cmGeneratorTarget::GetTargetVersion(const std::string& property,
5691                                          int& major, int& minor,
5692                                          int& patch) const
5693 {
5694   // Set the default values.
5695   major = 0;
5696   minor = 0;
5697   patch = 0;
5698
5699   assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
5700
5701   if (cmProp version = this->GetProperty(property)) {
5702     // Try to parse the version number and store the results that were
5703     // successfully parsed.
5704     int parsed_major;
5705     int parsed_minor;
5706     int parsed_patch;
5707     switch (sscanf(version->c_str(), "%d.%d.%d", &parsed_major, &parsed_minor,
5708                    &parsed_patch)) {
5709       case 3:
5710         patch = parsed_patch;
5711         CM_FALLTHROUGH;
5712       case 2:
5713         minor = parsed_minor;
5714         CM_FALLTHROUGH;
5715       case 1:
5716         major = parsed_major;
5717         CM_FALLTHROUGH;
5718       default:
5719         break;
5720     }
5721   }
5722 }
5723
5724 std::string cmGeneratorTarget::GetRuntimeLinkLibrary(
5725   std::string const& lang, std::string const& config) const
5726 {
5727   // This is activated by the presence of a default selection whether or
5728   // not it is overridden by a property.
5729   cmProp runtimeLibraryDefault = this->Makefile->GetDef(
5730     cmStrCat("CMAKE_", lang, "_RUNTIME_LIBRARY_DEFAULT"));
5731   if (!runtimeLibraryDefault || runtimeLibraryDefault->empty()) {
5732     return std::string();
5733   }
5734   cmProp runtimeLibraryValue =
5735     this->Target->GetProperty(cmStrCat(lang, "_RUNTIME_LIBRARY"));
5736   if (!runtimeLibraryValue) {
5737     runtimeLibraryValue = runtimeLibraryDefault;
5738   }
5739   return cmSystemTools::UpperCase(cmGeneratorExpression::Evaluate(
5740     *runtimeLibraryValue, this->LocalGenerator, config, this));
5741 }
5742
5743 std::string cmGeneratorTarget::GetFortranModuleDirectory(
5744   std::string const& working_dir) const
5745 {
5746   if (!this->FortranModuleDirectoryCreated) {
5747     this->FortranModuleDirectory =
5748       this->CreateFortranModuleDirectory(working_dir);
5749     this->FortranModuleDirectoryCreated = true;
5750   }
5751
5752   return this->FortranModuleDirectory;
5753 }
5754
5755 std::string cmGeneratorTarget::CreateFortranModuleDirectory(
5756   std::string const& working_dir) const
5757 {
5758   std::string mod_dir;
5759   std::string target_mod_dir;
5760   if (cmProp prop = this->GetProperty("Fortran_MODULE_DIRECTORY")) {
5761     target_mod_dir = *prop;
5762   } else {
5763     std::string const& default_mod_dir =
5764       this->LocalGenerator->GetCurrentBinaryDirectory();
5765     if (default_mod_dir != working_dir) {
5766       target_mod_dir = default_mod_dir;
5767     }
5768   }
5769   const char* moddir_flag =
5770     this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
5771   if (!target_mod_dir.empty() && moddir_flag) {
5772     // Compute the full path to the module directory.
5773     if (cmSystemTools::FileIsFullPath(target_mod_dir)) {
5774       // Already a full path.
5775       mod_dir = target_mod_dir;
5776     } else {
5777       // Interpret relative to the current output directory.
5778       mod_dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
5779                          '/', target_mod_dir);
5780     }
5781
5782     // Make sure the module output directory exists.
5783     cmSystemTools::MakeDirectory(mod_dir);
5784   }
5785   return mod_dir;
5786 }
5787
5788 std::string cmGeneratorTarget::GetFrameworkVersion() const
5789 {
5790   assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
5791
5792   if (cmProp fversion = this->GetProperty("FRAMEWORK_VERSION")) {
5793     return *fversion;
5794   }
5795   if (cmProp tversion = this->GetProperty("VERSION")) {
5796     return *tversion;
5797   }
5798   return "A";
5799 }
5800
5801 void cmGeneratorTarget::ComputeVersionedName(std::string& vName,
5802                                              std::string const& prefix,
5803                                              std::string const& base,
5804                                              std::string const& suffix,
5805                                              std::string const& name,
5806                                              const char* version) const
5807 {
5808   vName = this->Makefile->IsOn("APPLE") ? (prefix + base) : name;
5809   if (version) {
5810     vName += ".";
5811     vName += version;
5812   }
5813   vName += this->Makefile->IsOn("APPLE") ? suffix : std::string();
5814 }
5815
5816 std::vector<std::string> cmGeneratorTarget::GetPropertyKeys() const
5817 {
5818   return this->Target->GetProperties().GetKeys();
5819 }
5820
5821 void cmGeneratorTarget::ReportPropertyOrigin(
5822   const std::string& p, const std::string& result, const std::string& report,
5823   const std::string& compatibilityType) const
5824 {
5825   std::vector<std::string> debugProperties;
5826   this->Target->GetMakefile()->GetDefExpandList(
5827     "CMAKE_DEBUG_TARGET_PROPERTIES", debugProperties);
5828
5829   bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] &&
5830     cm::contains(debugProperties, p);
5831
5832   if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
5833     this->DebugCompatiblePropertiesDone[p] = true;
5834   }
5835   if (!debugOrigin) {
5836     return;
5837   }
5838
5839   std::string areport =
5840     cmStrCat(compatibilityType, " of property \"", p, "\" for target \"",
5841              this->GetName(), "\" (result: \"", result, "\"):\n", report);
5842
5843   this->LocalGenerator->GetCMakeInstance()->IssueMessage(MessageType::LOG,
5844                                                          areport);
5845 }
5846
5847 bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n,
5848                                           cmLocalGenerator const*& lg) const
5849 {
5850   if (cmHasLiteralPrefix(n, CMAKE_DIRECTORY_ID_SEP)) {
5851     cmDirectoryId const dirId = n.substr(sizeof(CMAKE_DIRECTORY_ID_SEP) - 1);
5852     if (dirId.String.empty()) {
5853       lg = this->LocalGenerator;
5854       return true;
5855     }
5856     if (cmLocalGenerator const* otherLG =
5857           this->GlobalGenerator->FindLocalGenerator(dirId)) {
5858       lg = otherLG;
5859       return true;
5860     }
5861   }
5862   return false;
5863 }
5864
5865 void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
5866                                         cmListFileBacktrace const& bt,
5867                                         std::vector<cmLinkItem>& items) const
5868 {
5869   cmLocalGenerator const* lg = this->LocalGenerator;
5870   for (std::string const& n : names) {
5871     if (this->IsLinkLookupScope(n, lg)) {
5872       continue;
5873     }
5874
5875     std::string name = this->CheckCMP0004(n);
5876     if (name == this->GetName() || name.empty()) {
5877       continue;
5878     }
5879     items.push_back(this->ResolveLinkItem(name, bt, lg));
5880   }
5881 }
5882
5883 void cmGeneratorTarget::ExpandLinkItems(
5884   std::string const& prop, std::string const& value, std::string const& config,
5885   cmGeneratorTarget const* headTarget, bool usage_requirements_only,
5886   std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition,
5887   bool& hadContextSensitiveCondition,
5888   bool& hadLinkLanguageSensitiveCondition) const
5889 {
5890   // Keep this logic in sync with ComputeLinkImplementationLibraries.
5891   cmGeneratorExpression ge;
5892   cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr);
5893   // The $<LINK_ONLY> expression may be in a link interface to specify
5894   // private link dependencies that are otherwise excluded from usage
5895   // requirements.
5896   if (usage_requirements_only) {
5897     dagChecker.SetTransitivePropertiesOnly();
5898   }
5899   std::vector<std::string> libs;
5900   std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
5901   cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget,
5902                              &dagChecker, this, headTarget->LinkerLanguage),
5903                libs);
5904   this->LookupLinkItems(libs, cge->GetBacktrace(), items);
5905   hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
5906   hadContextSensitiveCondition = cge->GetHadContextSensitiveCondition();
5907   hadLinkLanguageSensitiveCondition =
5908     cge->GetHadLinkLanguageSensitiveCondition();
5909 }
5910
5911 cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
5912   const std::string& config, cmGeneratorTarget const* head) const
5913 {
5914   return this->GetLinkInterface(config, head, false);
5915 }
5916
5917 cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
5918   const std::string& config, cmGeneratorTarget const* head,
5919   bool secondPass) const
5920 {
5921   // Imported targets have their own link interface.
5922   if (this->IsImported()) {
5923     return this->GetImportLinkInterface(config, head, false, secondPass);
5924   }
5925
5926   // Link interfaces are not supported for executables that do not
5927   // export symbols.
5928   if (this->GetType() == cmStateEnums::EXECUTABLE &&
5929       !this->IsExecutableWithExports()) {
5930     return nullptr;
5931   }
5932
5933   // Lookup any existing link interface for this configuration.
5934   cmHeadToLinkInterfaceMap& hm = this->GetHeadToLinkInterfaceMap(config);
5935
5936   if (secondPass) {
5937     hm.erase(head);
5938   }
5939
5940   // If the link interface does not depend on the head target
5941   // then return the one we computed first.
5942   if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
5943     return &hm.begin()->second;
5944   }
5945
5946   cmOptionalLinkInterface& iface = hm[head];
5947   if (!iface.LibrariesDone) {
5948     iface.LibrariesDone = true;
5949     this->ComputeLinkInterfaceLibraries(config, iface, head, false);
5950   }
5951   if (!iface.AllDone) {
5952     iface.AllDone = true;
5953     if (iface.Exists) {
5954       this->ComputeLinkInterface(config, iface, head, secondPass);
5955     }
5956   }
5957
5958   return iface.Exists ? &iface : nullptr;
5959 }
5960
5961 void cmGeneratorTarget::ComputeLinkInterface(
5962   const std::string& config, cmOptionalLinkInterface& iface,
5963   cmGeneratorTarget const* headTarget) const
5964 {
5965   this->ComputeLinkInterface(config, iface, headTarget, false);
5966 }
5967
5968 void cmGeneratorTarget::ComputeLinkInterface(
5969   const std::string& config, cmOptionalLinkInterface& iface,
5970   cmGeneratorTarget const* headTarget, bool secondPass) const
5971 {
5972   if (iface.Explicit) {
5973     if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
5974         this->GetType() == cmStateEnums::STATIC_LIBRARY ||
5975         this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
5976       // Shared libraries may have runtime implementation dependencies
5977       // on other shared libraries that are not in the interface.
5978       std::set<cmLinkItem> emitted;
5979       for (cmLinkItem const& lib : iface.Libraries) {
5980         emitted.insert(lib);
5981       }
5982       if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
5983         cmLinkImplementation const* impl =
5984           this->GetLinkImplementation(config, secondPass);
5985         for (cmLinkImplItem const& lib : impl->Libraries) {
5986           if (emitted.insert(lib).second) {
5987             if (lib.Target) {
5988               // This is a runtime dependency on another shared library.
5989               if (lib.Target->GetType() == cmStateEnums::SHARED_LIBRARY) {
5990                 iface.SharedDeps.push_back(lib);
5991               }
5992             } else {
5993               // TODO: Recognize shared library file names.  Perhaps this
5994               // should be moved to cmComputeLinkInformation, but that
5995               // creates a chicken-and-egg problem since this list is needed
5996               // for its construction.
5997             }
5998           }
5999         }
6000       }
6001     }
6002   } else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN ||
6003              this->GetPolicyStatusCMP0022() == cmPolicies::OLD) {
6004     // The link implementation is the default link interface.
6005     cmLinkImplementationLibraries const* impl =
6006       this->GetLinkImplementationLibrariesInternal(config, headTarget);
6007     iface.ImplementationIsInterface = true;
6008     iface.WrongConfigLibraries = impl->WrongConfigLibraries;
6009   }
6010
6011   if (this->LinkLanguagePropagatesToDependents()) {
6012     // Targets using this archive need its language runtime libraries.
6013     if (cmLinkImplementation const* impl =
6014           this->GetLinkImplementation(config, secondPass)) {
6015       iface.Languages = impl->Languages;
6016     }
6017   }
6018
6019   if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
6020     // Construct the property name suffix for this configuration.
6021     std::string suffix = "_";
6022     if (!config.empty()) {
6023       suffix += cmSystemTools::UpperCase(config);
6024     } else {
6025       suffix += "NOCONFIG";
6026     }
6027
6028     // How many repetitions are needed if this library has cyclic
6029     // dependencies?
6030     std::string propName = cmStrCat("LINK_INTERFACE_MULTIPLICITY", suffix);
6031     if (cmProp config_reps = this->GetProperty(propName)) {
6032       sscanf(config_reps->c_str(), "%u", &iface.Multiplicity);
6033     } else if (cmProp reps =
6034                  this->GetProperty("LINK_INTERFACE_MULTIPLICITY")) {
6035       sscanf(reps->c_str(), "%u", &iface.Multiplicity);
6036     }
6037   }
6038 }
6039
6040 const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries(
6041   const std::string& config, cmGeneratorTarget const* head,
6042   bool usage_requirements_only) const
6043 {
6044   // Imported targets have their own link interface.
6045   if (this->IsImported()) {
6046     return this->GetImportLinkInterface(config, head, usage_requirements_only);
6047   }
6048
6049   // Link interfaces are not supported for executables that do not
6050   // export symbols.
6051   if (this->GetType() == cmStateEnums::EXECUTABLE &&
6052       !this->IsExecutableWithExports()) {
6053     return nullptr;
6054   }
6055
6056   // Lookup any existing link interface for this configuration.
6057   cmHeadToLinkInterfaceMap& hm =
6058     (usage_requirements_only
6059        ? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
6060        : this->GetHeadToLinkInterfaceMap(config));
6061
6062   // If the link interface does not depend on the head target
6063   // then return the one we computed first.
6064   if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
6065     return &hm.begin()->second;
6066   }
6067
6068   cmOptionalLinkInterface& iface = hm[head];
6069   if (!iface.LibrariesDone) {
6070     iface.LibrariesDone = true;
6071     this->ComputeLinkInterfaceLibraries(config, iface, head,
6072                                         usage_requirements_only);
6073   }
6074
6075   return iface.Exists ? &iface : nullptr;
6076 }
6077
6078 std::string cmGeneratorTarget::GetDirectory(
6079   const std::string& config, cmStateEnums::ArtifactType artifact) const
6080 {
6081   if (this->IsImported()) {
6082     // Return the directory from which the target is imported.
6083     return cmSystemTools::GetFilenamePath(
6084       this->Target->ImportedGetFullPath(config, artifact));
6085   }
6086   if (OutputInfo const* info = this->GetOutputInfo(config)) {
6087     // Return the directory in which the target will be built.
6088     switch (artifact) {
6089       case cmStateEnums::RuntimeBinaryArtifact:
6090         return info->OutDir;
6091       case cmStateEnums::ImportLibraryArtifact:
6092         return info->ImpDir;
6093     }
6094   }
6095   return "";
6096 }
6097
6098 bool cmGeneratorTarget::UsesDefaultOutputDir(
6099   const std::string& config, cmStateEnums::ArtifactType artifact) const
6100 {
6101   std::string dir;
6102   return this->ComputeOutputDir(config, artifact, dir);
6103 }
6104
6105 cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
6106   const std::string& config) const
6107 {
6108   // There is no output information for imported targets.
6109   if (this->IsImported()) {
6110     return nullptr;
6111   }
6112
6113   // Only libraries and executables have well-defined output files.
6114   if (!this->HaveWellDefinedOutputFiles()) {
6115     std::string msg = cmStrCat("cmGeneratorTarget::GetOutputInfo called for ",
6116                                this->GetName(), " which has type ",
6117                                cmState::GetTargetTypeName(this->GetType()));
6118     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
6119     return nullptr;
6120   }
6121
6122   // Lookup/compute/cache the output information for this configuration.
6123   std::string config_upper;
6124   if (!config.empty()) {
6125     config_upper = cmSystemTools::UpperCase(config);
6126   }
6127   auto i = this->OutputInfoMap.find(config_upper);
6128   if (i == this->OutputInfoMap.end()) {
6129     // Add empty info in map to detect potential recursion.
6130     OutputInfo info;
6131     OutputInfoMapType::value_type entry(config_upper, info);
6132     i = this->OutputInfoMap.insert(entry).first;
6133
6134     // Compute output directories.
6135     this->ComputeOutputDir(config, cmStateEnums::RuntimeBinaryArtifact,
6136                            info.OutDir);
6137     this->ComputeOutputDir(config, cmStateEnums::ImportLibraryArtifact,
6138                            info.ImpDir);
6139     if (!this->ComputePDBOutputDir("PDB", config, info.PdbDir)) {
6140       info.PdbDir = info.OutDir;
6141     }
6142
6143     // Now update the previously-prepared map entry.
6144     i->second = info;
6145   } else if (i->second.empty()) {
6146     // An empty map entry indicates we have been called recursively
6147     // from the above block.
6148     this->LocalGenerator->GetCMakeInstance()->IssueMessage(
6149       MessageType::FATAL_ERROR,
6150       "Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.",
6151       this->GetBacktrace());
6152     return nullptr;
6153   }
6154   return &i->second;
6155 }
6156
6157 bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
6158                                          cmStateEnums::ArtifactType artifact,
6159                                          std::string& out) const
6160 {
6161   bool usesDefaultOutputDir = false;
6162   std::string conf = config;
6163
6164   // Look for a target property defining the target output directory
6165   // based on the target type.
6166   std::string targetTypeName = this->GetOutputTargetType(artifact);
6167   const char* propertyName = nullptr;
6168   std::string propertyNameStr = targetTypeName;
6169   if (!propertyNameStr.empty()) {
6170     propertyNameStr += "_OUTPUT_DIRECTORY";
6171     propertyName = propertyNameStr.c_str();
6172   }
6173
6174   // Check for a per-configuration output directory target property.
6175   std::string configUpper = cmSystemTools::UpperCase(conf);
6176   const char* configProp = nullptr;
6177   std::string configPropStr = targetTypeName;
6178   if (!configPropStr.empty()) {
6179     configPropStr += "_OUTPUT_DIRECTORY_";
6180     configPropStr += configUpper;
6181     configProp = configPropStr.c_str();
6182   }
6183
6184   // Select an output directory.
6185   if (cmProp config_outdir = this->GetProperty(configProp)) {
6186     // Use the user-specified per-configuration output directory.
6187     out = cmGeneratorExpression::Evaluate(*config_outdir, this->LocalGenerator,
6188                                           config);
6189
6190     // Skip per-configuration subdirectory.
6191     conf.clear();
6192   } else if (cmProp outdir = this->GetProperty(propertyName)) {
6193     // Use the user-specified output directory.
6194     out =
6195       cmGeneratorExpression::Evaluate(*outdir, this->LocalGenerator, config);
6196
6197     // Skip per-configuration subdirectory if the value contained a
6198     // generator expression.
6199     if (out != *outdir) {
6200       conf.clear();
6201     }
6202   } else if (this->GetType() == cmStateEnums::EXECUTABLE) {
6203     // Lookup the output path for executables.
6204     out = this->Makefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
6205   } else if (this->GetType() == cmStateEnums::STATIC_LIBRARY ||
6206              this->GetType() == cmStateEnums::SHARED_LIBRARY ||
6207              this->GetType() == cmStateEnums::MODULE_LIBRARY) {
6208     // Lookup the output path for libraries.
6209     out = this->Makefile->GetSafeDefinition("LIBRARY_OUTPUT_PATH");
6210   }
6211   if (out.empty()) {
6212     // Default to the current output directory.
6213     usesDefaultOutputDir = true;
6214     out = ".";
6215   }
6216
6217   // Convert the output path to a full path in case it is
6218   // specified as a relative path.  Treat a relative path as
6219   // relative to the current output directory for this makefile.
6220   out = (cmSystemTools::CollapseFullPath(
6221     out, this->LocalGenerator->GetCurrentBinaryDirectory()));
6222
6223   // The generator may add the configuration's subdirectory.
6224   if (!conf.empty()) {
6225     bool useEPN =
6226       this->GlobalGenerator->UseEffectivePlatformName(this->Makefile);
6227     std::string suffix =
6228       usesDefaultOutputDir && useEPN ? "${EFFECTIVE_PLATFORM_NAME}" : "";
6229     this->LocalGenerator->GetGlobalGenerator()->AppendDirectoryForConfig(
6230       "/", conf, suffix, out);
6231   }
6232
6233   return usesDefaultOutputDir;
6234 }
6235
6236 bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
6237                                             const std::string& config,
6238                                             std::string& out) const
6239 {
6240   // Look for a target property defining the target output directory
6241   // based on the target type.
6242   const char* propertyName = nullptr;
6243   std::string propertyNameStr = kind;
6244   if (!propertyNameStr.empty()) {
6245     propertyNameStr += "_OUTPUT_DIRECTORY";
6246     propertyName = propertyNameStr.c_str();
6247   }
6248   std::string conf = config;
6249
6250   // Check for a per-configuration output directory target property.
6251   std::string configUpper = cmSystemTools::UpperCase(conf);
6252   const char* configProp = nullptr;
6253   std::string configPropStr = kind;
6254   if (!configPropStr.empty()) {
6255     configPropStr += "_OUTPUT_DIRECTORY_";
6256     configPropStr += configUpper;
6257     configProp = configPropStr.c_str();
6258   }
6259
6260   // Select an output directory.
6261   if (cmProp config_outdir = this->GetProperty(configProp)) {
6262     // Use the user-specified per-configuration output directory.
6263     out = cmGeneratorExpression::Evaluate(*config_outdir, this->LocalGenerator,
6264                                           config);
6265
6266     // Skip per-configuration subdirectory.
6267     conf.clear();
6268   } else if (cmProp outdir = this->GetProperty(propertyName)) {
6269     // Use the user-specified output directory.
6270     out =
6271       cmGeneratorExpression::Evaluate(*outdir, this->LocalGenerator, config);
6272
6273     // Skip per-configuration subdirectory if the value contained a
6274     // generator expression.
6275     if (out != *outdir) {
6276       conf.clear();
6277     }
6278   }
6279   if (out.empty()) {
6280     return false;
6281   }
6282
6283   // Convert the output path to a full path in case it is
6284   // specified as a relative path.  Treat a relative path as
6285   // relative to the current output directory for this makefile.
6286   out = (cmSystemTools::CollapseFullPath(
6287     out, this->LocalGenerator->GetCurrentBinaryDirectory()));
6288
6289   // The generator may add the configuration's subdirectory.
6290   if (!conf.empty()) {
6291     this->LocalGenerator->GetGlobalGenerator()->AppendDirectoryForConfig(
6292       "/", conf, "", out);
6293   }
6294   return true;
6295 }
6296
6297 bool cmGeneratorTarget::HaveInstallTreeRPATH(const std::string& config) const
6298 {
6299   std::string install_rpath;
6300   this->GetInstallRPATH(config, install_rpath);
6301   return !install_rpath.empty() &&
6302     !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
6303 }
6304
6305 bool cmGeneratorTarget::GetBuildRPATH(const std::string& config,
6306                                       std::string& rpath) const
6307 {
6308   return this->GetRPATH(config, "BUILD_RPATH", rpath);
6309 }
6310
6311 bool cmGeneratorTarget::GetInstallRPATH(const std::string& config,
6312                                         std::string& rpath) const
6313 {
6314   return this->GetRPATH(config, "INSTALL_RPATH", rpath);
6315 }
6316
6317 bool cmGeneratorTarget::GetRPATH(const std::string& config,
6318                                  const std::string& prop,
6319                                  std::string& rpath) const
6320 {
6321   cmProp value = this->GetProperty(prop);
6322   if (!value) {
6323     return false;
6324   }
6325
6326   rpath =
6327     cmGeneratorExpression::Evaluate(*value, this->LocalGenerator, config);
6328
6329   return true;
6330 }
6331
6332 void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
6333   const std::string& config, cmOptionalLinkInterface& iface,
6334   cmGeneratorTarget const* headTarget, bool usage_requirements_only) const
6335 {
6336   // Construct the property name suffix for this configuration.
6337   std::string suffix = "_";
6338   if (!config.empty()) {
6339     suffix += cmSystemTools::UpperCase(config);
6340   } else {
6341     suffix += "NOCONFIG";
6342   }
6343
6344   // An explicit list of interface libraries may be set for shared
6345   // libraries and executables that export symbols.
6346   cmProp explicitLibraries = nullptr;
6347   std::string linkIfaceProp;
6348   bool const cmp0022NEW = (this->GetPolicyStatusCMP0022() != cmPolicies::OLD &&
6349                            this->GetPolicyStatusCMP0022() != cmPolicies::WARN);
6350   if (cmp0022NEW) {
6351     // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
6352     linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
6353     explicitLibraries = this->GetProperty(linkIfaceProp);
6354   } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
6355              this->IsExecutableWithExports()) {
6356     // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a
6357     // shared lib or executable.
6358
6359     // Lookup the per-configuration property.
6360     linkIfaceProp = cmStrCat("LINK_INTERFACE_LIBRARIES", suffix);
6361     explicitLibraries = this->GetProperty(linkIfaceProp);
6362
6363     // If not set, try the generic property.
6364     if (!explicitLibraries) {
6365       linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
6366       explicitLibraries = this->GetProperty(linkIfaceProp);
6367     }
6368   }
6369
6370   if (explicitLibraries &&
6371       this->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
6372       !this->PolicyWarnedCMP0022) {
6373     // Compare the explicitly set old link interface properties to the
6374     // preferred new link interface property one and warn if different.
6375     cmProp newExplicitLibraries =
6376       this->GetProperty("INTERFACE_LINK_LIBRARIES");
6377     if (newExplicitLibraries &&
6378         (*newExplicitLibraries != *explicitLibraries)) {
6379       std::ostringstream w;
6380       /* clang-format off */
6381       w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n"
6382         "Target \"" << this->GetName() << "\" has an "
6383         "INTERFACE_LINK_LIBRARIES property which differs from its " <<
6384         linkIfaceProp << " properties."
6385         "\n"
6386         "INTERFACE_LINK_LIBRARIES:\n"
6387         "  " << *newExplicitLibraries << "\n" <<
6388         linkIfaceProp << ":\n"
6389         "  " << *explicitLibraries << "\n";
6390       /* clang-format on */
6391       this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
6392       this->PolicyWarnedCMP0022 = true;
6393     }
6394   }
6395
6396   // There is no implicit link interface for executables or modules
6397   // so if none was explicitly set then there is no link interface.
6398   if (!explicitLibraries &&
6399       (this->GetType() == cmStateEnums::EXECUTABLE ||
6400        (this->GetType() == cmStateEnums::MODULE_LIBRARY))) {
6401     return;
6402   }
6403   iface.Exists = true;
6404   iface.Explicit = cmp0022NEW || explicitLibraries != nullptr;
6405
6406   if (explicitLibraries) {
6407     // The interface libraries have been explicitly set.
6408     this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config,
6409                           headTarget, usage_requirements_only, iface.Libraries,
6410                           iface.HadHeadSensitiveCondition,
6411                           iface.HadContextSensitiveCondition,
6412                           iface.HadLinkLanguageSensitiveCondition);
6413   } else if (!cmp0022NEW)
6414   // If CMP0022 is NEW then the plain tll signature sets the
6415   // INTERFACE_LINK_LIBRARIES, so if we get here then the project
6416   // cleared the property explicitly and we should not fall back
6417   // to the link implementation.
6418   {
6419     // The link implementation is the default link interface.
6420     cmLinkImplementationLibraries const* impl =
6421       this->GetLinkImplementationLibrariesInternal(config, headTarget);
6422     iface.Libraries.insert(iface.Libraries.end(), impl->Libraries.begin(),
6423                            impl->Libraries.end());
6424     if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
6425         !this->PolicyWarnedCMP0022 && !usage_requirements_only) {
6426       // Compare the link implementation fallback link interface to the
6427       // preferred new link interface property and warn if different.
6428       std::vector<cmLinkItem> ifaceLibs;
6429       static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
6430       if (cmProp newExplicitLibraries = this->GetProperty(newProp)) {
6431         bool hadHeadSensitiveConditionDummy = false;
6432         bool hadContextSensitiveConditionDummy = false;
6433         bool hadLinkLanguageSensitiveConditionDummy = false;
6434         this->ExpandLinkItems(newProp, *newExplicitLibraries, config,
6435                               headTarget, usage_requirements_only, ifaceLibs,
6436                               hadHeadSensitiveConditionDummy,
6437                               hadContextSensitiveConditionDummy,
6438                               hadLinkLanguageSensitiveConditionDummy);
6439       }
6440       if (ifaceLibs != iface.Libraries) {
6441         std::string oldLibraries = cmJoin(impl->Libraries, ";");
6442         std::string newLibraries = cmJoin(ifaceLibs, ";");
6443         if (oldLibraries.empty()) {
6444           oldLibraries = "(empty)";
6445         }
6446         if (newLibraries.empty()) {
6447           newLibraries = "(empty)";
6448         }
6449
6450         std::ostringstream w;
6451         /* clang-format off */
6452         w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n"
6453           "Target \"" << this->GetName() << "\" has an "
6454           "INTERFACE_LINK_LIBRARIES property.  "
6455           "This should be preferred as the source of the link interface "
6456           "for this library but because CMP0022 is not set CMake is "
6457           "ignoring the property and using the link implementation "
6458           "as the link interface instead."
6459           "\n"
6460           "INTERFACE_LINK_LIBRARIES:\n"
6461           "  " << newLibraries << "\n"
6462           "Link implementation:\n"
6463           "  " << oldLibraries << "\n";
6464         /* clang-format on */
6465         this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING,
6466                                            w.str());
6467         this->PolicyWarnedCMP0022 = true;
6468       }
6469     }
6470   }
6471 }
6472
6473 const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
6474   const std::string& config, cmGeneratorTarget const* headTarget,
6475   bool usage_requirements_only, bool secondPass) const
6476 {
6477   cmGeneratorTarget::ImportInfo const* info = this->GetImportInfo(config);
6478   if (!info) {
6479     return nullptr;
6480   }
6481
6482   cmHeadToLinkInterfaceMap& hm =
6483     (usage_requirements_only
6484        ? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
6485        : this->GetHeadToLinkInterfaceMap(config));
6486
6487   if (secondPass) {
6488     hm.erase(headTarget);
6489   }
6490
6491   // If the link interface does not depend on the head target
6492   // then return the one we computed first.
6493   if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
6494     return &hm.begin()->second;
6495   }
6496
6497   cmOptionalLinkInterface& iface = hm[headTarget];
6498   if (!iface.AllDone) {
6499     iface.AllDone = true;
6500     iface.Multiplicity = info->Multiplicity;
6501     cmExpandList(info->Languages, iface.Languages);
6502     this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
6503                           headTarget, usage_requirements_only, iface.Libraries,
6504                           iface.HadHeadSensitiveCondition,
6505                           iface.HadContextSensitiveCondition,
6506                           iface.HadLinkLanguageSensitiveCondition);
6507     std::vector<std::string> deps = cmExpandedList(info->SharedDeps);
6508     this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps);
6509   }
6510
6511   return &iface;
6512 }
6513
6514 cmGeneratorTarget::ImportInfo const* cmGeneratorTarget::GetImportInfo(
6515   const std::string& config) const
6516 {
6517   // There is no imported information for non-imported targets.
6518   if (!this->IsImported()) {
6519     return nullptr;
6520   }
6521
6522   // Lookup/compute/cache the import information for this
6523   // configuration.
6524   std::string config_upper;
6525   if (!config.empty()) {
6526     config_upper = cmSystemTools::UpperCase(config);
6527   } else {
6528     config_upper = "NOCONFIG";
6529   }
6530
6531   auto i = this->ImportInfoMap.find(config_upper);
6532   if (i == this->ImportInfoMap.end()) {
6533     ImportInfo info;
6534     this->ComputeImportInfo(config_upper, info);
6535     ImportInfoMapType::value_type entry(config_upper, info);
6536     i = this->ImportInfoMap.insert(entry).first;
6537   }
6538
6539   if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
6540     return &i->second;
6541   }
6542   // If the location is empty then the target is not available for
6543   // this configuration.
6544   if (i->second.Location.empty() && i->second.ImportLibrary.empty()) {
6545     return nullptr;
6546   }
6547
6548   // Return the import information.
6549   return &i->second;
6550 }
6551
6552 void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
6553                                           ImportInfo& info) const
6554 {
6555   // This method finds information about an imported target from its
6556   // properties.  The "IMPORTED_" namespace is reserved for properties
6557   // defined by the project exporting the target.
6558
6559   // Initialize members.
6560   info.NoSOName = false;
6561
6562   cmProp loc = nullptr;
6563   cmProp imp = nullptr;
6564   std::string suffix;
6565   if (!this->Target->GetMappedConfig(desired_config, loc, imp, suffix)) {
6566     return;
6567   }
6568
6569   // Get the link interface.
6570   {
6571     std::string linkProp = "INTERFACE_LINK_LIBRARIES";
6572     cmProp propertyLibs = this->GetProperty(linkProp);
6573
6574     if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
6575       if (!propertyLibs) {
6576         linkProp = cmStrCat("IMPORTED_LINK_INTERFACE_LIBRARIES", suffix);
6577         propertyLibs = this->GetProperty(linkProp);
6578       }
6579
6580       if (!propertyLibs) {
6581         linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
6582         propertyLibs = this->GetProperty(linkProp);
6583       }
6584     }
6585     if (propertyLibs) {
6586       info.LibrariesProp = linkProp;
6587       info.Libraries = *propertyLibs;
6588     }
6589   }
6590   if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
6591     if (loc) {
6592       info.LibName = *loc;
6593     }
6594     return;
6595   }
6596
6597   // A provided configuration has been chosen.  Load the
6598   // configuration's properties.
6599
6600   // Get the location.
6601   if (loc) {
6602     info.Location = *loc;
6603   } else {
6604     std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
6605     if (cmProp config_location = this->GetProperty(impProp)) {
6606       info.Location = *config_location;
6607     } else if (cmProp location = this->GetProperty("IMPORTED_LOCATION")) {
6608       info.Location = *location;
6609     }
6610   }
6611
6612   // Get the soname.
6613   if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
6614     std::string soProp = cmStrCat("IMPORTED_SONAME", suffix);
6615     if (cmProp config_soname = this->GetProperty(soProp)) {
6616       info.SOName = *config_soname;
6617     } else if (cmProp soname = this->GetProperty("IMPORTED_SONAME")) {
6618       info.SOName = *soname;
6619     }
6620   }
6621
6622   // Get the "no-soname" mark.
6623   if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
6624     std::string soProp = cmStrCat("IMPORTED_NO_SONAME", suffix);
6625     if (cmProp config_no_soname = this->GetProperty(soProp)) {
6626       info.NoSOName = cmIsOn(*config_no_soname);
6627     } else if (cmProp no_soname = this->GetProperty("IMPORTED_NO_SONAME")) {
6628       info.NoSOName = cmIsOn(*no_soname);
6629     }
6630   }
6631
6632   // Get the import library.
6633   if (imp) {
6634     info.ImportLibrary = *imp;
6635   } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
6636              this->IsExecutableWithExports()) {
6637     std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
6638     if (cmProp config_implib = this->GetProperty(impProp)) {
6639       info.ImportLibrary = *config_implib;
6640     } else if (cmProp implib = this->GetProperty("IMPORTED_IMPLIB")) {
6641       info.ImportLibrary = *implib;
6642     }
6643   }
6644
6645   // Get the link dependencies.
6646   {
6647     std::string linkProp =
6648       cmStrCat("IMPORTED_LINK_DEPENDENT_LIBRARIES", suffix);
6649     if (cmProp config_libs = this->GetProperty(linkProp)) {
6650       info.SharedDeps = *config_libs;
6651     } else if (cmProp libs =
6652                  this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES")) {
6653       info.SharedDeps = *libs;
6654     }
6655   }
6656
6657   // Get the link languages.
6658   if (this->LinkLanguagePropagatesToDependents()) {
6659     std::string linkProp =
6660       cmStrCat("IMPORTED_LINK_INTERFACE_LANGUAGES", suffix);
6661     if (cmProp config_libs = this->GetProperty(linkProp)) {
6662       info.Languages = *config_libs;
6663     } else if (cmProp libs =
6664                  this->GetProperty("IMPORTED_LINK_INTERFACE_LANGUAGES")) {
6665       info.Languages = *libs;
6666     }
6667   }
6668
6669   // Get information if target is managed assembly.
6670   {
6671     std::string linkProp = "IMPORTED_COMMON_LANGUAGE_RUNTIME";
6672     if (cmProp pc = this->GetProperty(linkProp + suffix)) {
6673       info.Managed = this->CheckManagedType(*pc);
6674     } else if (cmProp p = this->GetProperty(linkProp)) {
6675       info.Managed = this->CheckManagedType(*p);
6676     }
6677   }
6678
6679   // Get the cyclic repetition count.
6680   if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
6681     std::string linkProp =
6682       cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
6683     if (cmProp config_reps = this->GetProperty(linkProp)) {
6684       sscanf(config_reps->c_str(), "%u", &info.Multiplicity);
6685     } else if (cmProp reps =
6686                  this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY")) {
6687       sscanf(reps->c_str(), "%u", &info.Multiplicity);
6688     }
6689   }
6690 }
6691
6692 cmHeadToLinkInterfaceMap& cmGeneratorTarget::GetHeadToLinkInterfaceMap(
6693   const std::string& config) const
6694 {
6695   return this->LinkInterfaceMap[cmSystemTools::UpperCase(config)];
6696 }
6697
6698 cmHeadToLinkInterfaceMap&
6699 cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap(
6700   const std::string& config) const
6701 {
6702   return this
6703     ->LinkInterfaceUsageRequirementsOnlyMap[cmSystemTools::UpperCase(config)];
6704 }
6705
6706 const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
6707   const std::string& config) const
6708 {
6709   return this->GetLinkImplementation(config, false);
6710 }
6711
6712 const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
6713   const std::string& config, bool secondPass) const
6714 {
6715   // There is no link implementation for imported targets.
6716   if (this->IsImported()) {
6717     return nullptr;
6718   }
6719
6720   cmOptionalLinkImplementation& impl =
6721     this->LinkImplMap[cmSystemTools::UpperCase(config)][this];
6722   if (secondPass) {
6723     impl = cmOptionalLinkImplementation();
6724   }
6725   if (!impl.LibrariesDone) {
6726     impl.LibrariesDone = true;
6727     this->ComputeLinkImplementationLibraries(config, impl, this);
6728   }
6729   if (!impl.LanguagesDone) {
6730     impl.LanguagesDone = true;
6731     this->ComputeLinkImplementationLanguages(config, impl);
6732   }
6733   return &impl;
6734 }
6735
6736 bool cmGeneratorTarget::GetConfigCommonSourceFiles(
6737   std::vector<cmSourceFile*>& files) const
6738 {
6739   std::vector<std::string> const& configs =
6740     this->Makefile->GetGeneratorConfigs();
6741
6742   auto it = configs.begin();
6743   const std::string& firstConfig = *it;
6744   this->GetSourceFilesWithoutObjectLibraries(files, firstConfig);
6745
6746   for (; it != configs.end(); ++it) {
6747     std::vector<cmSourceFile*> configFiles;
6748     this->GetSourceFilesWithoutObjectLibraries(configFiles, *it);
6749     if (configFiles != files) {
6750       std::string firstConfigFiles;
6751       const char* sep = "";
6752       for (cmSourceFile* f : files) {
6753         firstConfigFiles += sep;
6754         firstConfigFiles += f->ResolveFullPath();
6755         sep = "\n  ";
6756       }
6757
6758       std::string thisConfigFiles;
6759       sep = "";
6760       for (cmSourceFile* f : configFiles) {
6761         thisConfigFiles += sep;
6762         thisConfigFiles += f->ResolveFullPath();
6763         sep = "\n  ";
6764       }
6765       std::ostringstream e;
6766       /* clang-format off */
6767       e << "Target \"" << this->GetName()
6768         << "\" has source files which vary by "
6769         "configuration. This is not supported by the \""
6770         << this->GlobalGenerator->GetName()
6771         << "\" generator.\n"
6772           "Config \"" << firstConfig << "\":\n"
6773           "  " << firstConfigFiles << "\n"
6774           "Config \"" << *it << "\":\n"
6775           "  " << thisConfigFiles << "\n";
6776       /* clang-format on */
6777       this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str());
6778       return false;
6779     }
6780   }
6781   return true;
6782 }
6783
6784 void cmGeneratorTarget::GetObjectLibrariesCMP0026(
6785   std::vector<cmGeneratorTarget*>& objlibs) const
6786 {
6787   // At configure-time, this method can be called as part of getting the
6788   // LOCATION property or to export() a file to be include()d.  However
6789   // there is no cmGeneratorTarget at configure-time, so search the SOURCES
6790   // for TARGET_OBJECTS instead for backwards compatibility with OLD
6791   // behavior of CMP0024 and CMP0026 only.
6792   cmStringRange rng = this->Target->GetSourceEntries();
6793   for (std::string const& entry : rng) {
6794     std::vector<std::string> files = cmExpandedList(entry);
6795     for (std::string const& li : files) {
6796       if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') {
6797         std::string objLibName = li.substr(17, li.size() - 18);
6798
6799         if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
6800           continue;
6801         }
6802         cmGeneratorTarget* objLib =
6803           this->LocalGenerator->FindGeneratorTargetToUse(objLibName);
6804         if (objLib) {
6805           objlibs.push_back(objLib);
6806         }
6807       }
6808     }
6809   }
6810 }
6811
6812 std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const
6813 {
6814   // Strip whitespace off the library names because we used to do this
6815   // in case variables were expanded at generate time.  We no longer
6816   // do the expansion but users link to libraries like " ${VAR} ".
6817   std::string lib = item;
6818   std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
6819   if (pos != std::string::npos) {
6820     lib = lib.substr(pos);
6821   }
6822   pos = lib.find_last_not_of(" \t\r\n");
6823   if (pos != std::string::npos) {
6824     lib = lib.substr(0, pos + 1);
6825   }
6826   if (lib != item) {
6827     cmake* cm = this->LocalGenerator->GetCMakeInstance();
6828     switch (this->GetPolicyStatusCMP0004()) {
6829       case cmPolicies::WARN: {
6830         std::ostringstream w;
6831         w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0004) << "\n"
6832           << "Target \"" << this->GetName() << "\" links to item \"" << item
6833           << "\" which has leading or trailing whitespace.";
6834         cm->IssueMessage(MessageType::AUTHOR_WARNING, w.str(),
6835                          this->GetBacktrace());
6836       }
6837       case cmPolicies::OLD:
6838         break;
6839       case cmPolicies::NEW: {
6840         std::ostringstream e;
6841         e << "Target \"" << this->GetName() << "\" links to item \"" << item
6842           << "\" which has leading or trailing whitespace.  "
6843           << "This is now an error according to policy CMP0004.";
6844         cm->IssueMessage(MessageType::FATAL_ERROR, e.str(),
6845                          this->GetBacktrace());
6846       } break;
6847       case cmPolicies::REQUIRED_IF_USED:
6848       case cmPolicies::REQUIRED_ALWAYS: {
6849         std::ostringstream e;
6850         e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0004) << "\n"
6851           << "Target \"" << this->GetName() << "\" links to item \"" << item
6852           << "\" which has leading or trailing whitespace.";
6853         cm->IssueMessage(MessageType::FATAL_ERROR, e.str(),
6854                          this->GetBacktrace());
6855       } break;
6856     }
6857   }
6858   return lib;
6859 }
6860
6861 bool cmGeneratorTarget::IsDeprecated() const
6862 {
6863   cmProp deprecation = this->GetProperty("DEPRECATION");
6864   return deprecation && !deprecation->empty();
6865 }
6866
6867 std::string cmGeneratorTarget::GetDeprecation() const
6868 {
6869   // find DEPRECATION property
6870   if (cmProp deprecation = this->GetProperty("DEPRECATION")) {
6871     return *deprecation;
6872   }
6873   return std::string();
6874 }
6875
6876 void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
6877                                      const std::string& config) const
6878 {
6879   std::vector<cmSourceFile*> sourceFiles;
6880   this->GetSourceFiles(sourceFiles, config);
6881   for (cmSourceFile* src : sourceFiles) {
6882     const std::string& lang = src->GetOrDetermineLanguage();
6883     if (!lang.empty()) {
6884       languages.insert(lang);
6885     }
6886   }
6887
6888   std::vector<cmGeneratorTarget*> objectLibraries;
6889   std::vector<cmSourceFile const*> externalObjects;
6890   if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
6891     std::vector<cmGeneratorTarget*> objectTargets;
6892     this->GetObjectLibrariesCMP0026(objectTargets);
6893     objectLibraries.reserve(objectTargets.size());
6894     for (cmGeneratorTarget* gt : objectTargets) {
6895       objectLibraries.push_back(gt);
6896     }
6897   } else {
6898     this->GetExternalObjects(externalObjects, config);
6899     for (cmSourceFile const* extObj : externalObjects) {
6900       std::string objLib = extObj->GetObjectLibrary();
6901       if (cmGeneratorTarget* tgt =
6902             this->LocalGenerator->FindGeneratorTargetToUse(objLib)) {
6903         auto const objLibIt =
6904           std::find_if(objectLibraries.cbegin(), objectLibraries.cend(),
6905                        [tgt](cmGeneratorTarget* t) { return t == tgt; });
6906         if (objectLibraries.cend() == objLibIt) {
6907           objectLibraries.push_back(tgt);
6908         }
6909       }
6910     }
6911   }
6912   for (cmGeneratorTarget* objLib : objectLibraries) {
6913     objLib->GetLanguages(languages, config);
6914   }
6915 }
6916
6917 bool cmGeneratorTarget::IsCSharpOnly() const
6918 {
6919   // Only certain target types may compile CSharp.
6920   if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
6921       this->GetType() != cmStateEnums::STATIC_LIBRARY &&
6922       this->GetType() != cmStateEnums::EXECUTABLE) {
6923     return false;
6924   }
6925   std::set<std::string> languages = this->GetAllConfigCompileLanguages();
6926   // Consider an explicit linker language property, but *not* the
6927   // computed linker language that may depend on linked targets.
6928   cmProp linkLang = this->GetProperty("LINKER_LANGUAGE");
6929   if (linkLang && !linkLang->empty()) {
6930     languages.insert(*linkLang);
6931   }
6932   return languages.size() == 1 && languages.count("CSharp") > 0;
6933 }
6934
6935 void cmGeneratorTarget::ComputeLinkImplementationLanguages(
6936   const std::string& config, cmOptionalLinkImplementation& impl) const
6937 {
6938   // This target needs runtime libraries for its source languages.
6939   std::set<std::string> languages;
6940   // Get languages used in our source files.
6941   this->GetLanguages(languages, config);
6942   // Copy the set of languages to the link implementation.
6943   impl.Languages.insert(impl.Languages.begin(), languages.begin(),
6944                         languages.end());
6945 }
6946
6947 bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const
6948 {
6949   if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) {
6950     return false;
6951   }
6952   std::string build_rpath;
6953   if (this->GetBuildRPATH(config, build_rpath)) {
6954     return true;
6955   }
6956   if (cmLinkImplementationLibraries const* impl =
6957         this->GetLinkImplementationLibraries(config)) {
6958     return !impl->Libraries.empty();
6959   }
6960   return false;
6961 }
6962
6963 cmLinkImplementationLibraries const*
6964 cmGeneratorTarget::GetLinkImplementationLibraries(
6965   const std::string& config) const
6966 {
6967   return this->GetLinkImplementationLibrariesInternal(config, this);
6968 }
6969
6970 cmLinkImplementationLibraries const*
6971 cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
6972   const std::string& config, cmGeneratorTarget const* head) const
6973 {
6974   // There is no link implementation for imported targets.
6975   if (this->IsImported()) {
6976     return nullptr;
6977   }
6978
6979   // Populate the link implementation libraries for this configuration.
6980   HeadToLinkImplementationMap& hm =
6981     this->LinkImplMap[cmSystemTools::UpperCase(config)];
6982
6983   // If the link implementation does not depend on the head target
6984   // then return the one we computed first.
6985   if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
6986     return &hm.begin()->second;
6987   }
6988
6989   cmOptionalLinkImplementation& impl = hm[head];
6990   if (!impl.LibrariesDone) {
6991     impl.LibrariesDone = true;
6992     this->ComputeLinkImplementationLibraries(config, impl, head);
6993   }
6994   return &impl;
6995 }
6996
6997 bool cmGeneratorTarget::IsNullImpliedByLinkLibraries(
6998   const std::string& p) const
6999 {
7000   return cm::contains(this->LinkImplicitNullProperties, p);
7001 }
7002
7003 void cmGeneratorTarget::ComputeLinkImplementationLibraries(
7004   const std::string& config, cmOptionalLinkImplementation& impl,
7005   cmGeneratorTarget const* head) const
7006 {
7007   cmLocalGenerator const* lg = this->LocalGenerator;
7008   cmStringRange entryRange = this->Target->GetLinkImplementationEntries();
7009   cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces();
7010   cmBacktraceRange::const_iterator btIt = btRange.begin();
7011   // Collect libraries directly linked in this configuration.
7012   for (cmStringRange::const_iterator le = entryRange.begin(),
7013                                      end = entryRange.end();
7014        le != end; ++le, ++btIt) {
7015     std::vector<std::string> llibs;
7016     // Keep this logic in sync with ExpandLinkItems.
7017     cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr,
7018                                                nullptr);
7019     cmGeneratorExpression ge(*btIt);
7020     std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
7021     std::string const& evaluated =
7022       cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr,
7023                     this->LinkerLanguage);
7024     cmExpandList(evaluated, llibs);
7025     if (cge->GetHadHeadSensitiveCondition()) {
7026       impl.HadHeadSensitiveCondition = true;
7027     }
7028     if (cge->GetHadContextSensitiveCondition()) {
7029       impl.HadContextSensitiveCondition = true;
7030     }
7031     if (cge->GetHadLinkLanguageSensitiveCondition()) {
7032       impl.HadLinkLanguageSensitiveCondition = true;
7033     }
7034
7035     for (std::string const& lib : llibs) {
7036       if (this->IsLinkLookupScope(lib, lg)) {
7037         continue;
7038       }
7039
7040       // Skip entries that resolve to the target itself or are empty.
7041       std::string name = this->CheckCMP0004(lib);
7042       if (this->GetPolicyStatusCMP0108() == cmPolicies::NEW) {
7043         // resolve alias name
7044         auto target = this->Makefile->FindTargetToUse(name);
7045         if (target) {
7046           name = target->GetName();
7047         }
7048       }
7049       if (name == this->GetName() || name.empty()) {
7050         if (name == this->GetName()) {
7051           bool noMessage = false;
7052           MessageType messageType = MessageType::FATAL_ERROR;
7053           std::ostringstream e;
7054           switch (this->GetPolicyStatusCMP0038()) {
7055             case cmPolicies::WARN: {
7056               e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0038) << "\n";
7057               messageType = MessageType::AUTHOR_WARNING;
7058             } break;
7059             case cmPolicies::OLD:
7060               noMessage = true;
7061             case cmPolicies::REQUIRED_IF_USED:
7062             case cmPolicies::REQUIRED_ALWAYS:
7063             case cmPolicies::NEW:
7064               // Issue the fatal message.
7065               break;
7066           }
7067
7068           if (!noMessage) {
7069             e << "Target \"" << this->GetName() << "\" links to itself.";
7070             this->LocalGenerator->GetCMakeInstance()->IssueMessage(
7071               messageType, e.str(), this->GetBacktrace());
7072             if (messageType == MessageType::FATAL_ERROR) {
7073               return;
7074             }
7075           }
7076         }
7077         continue;
7078       }
7079
7080       // The entry is meant for this configuration.
7081       impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt, lg),
7082                                   evaluated != *le);
7083     }
7084
7085     std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
7086     for (std::string const& sp : seenProps) {
7087       if (!this->GetProperty(sp)) {
7088         this->LinkImplicitNullProperties.insert(sp);
7089       }
7090     }
7091     cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards);
7092   }
7093
7094   // Get the list of configurations considered to be DEBUG.
7095   std::vector<std::string> debugConfigs =
7096     this->Makefile->GetCMakeInstance()->GetDebugConfigs();
7097
7098   cmTargetLinkLibraryType linkType =
7099     CMP0003_ComputeLinkType(config, debugConfigs);
7100   cmTarget::LinkLibraryVectorType const& oldllibs =
7101     this->Target->GetOriginalLinkLibraries();
7102   for (cmTarget::LibraryID const& oldllib : oldllibs) {
7103     if (oldllib.second != GENERAL_LibraryType && oldllib.second != linkType) {
7104       std::string name = this->CheckCMP0004(oldllib.first);
7105       if (name == this->GetName() || name.empty()) {
7106         continue;
7107       }
7108       // Support OLD behavior for CMP0003.
7109       impl.WrongConfigLibraries.push_back(
7110         this->ResolveLinkItem(name, cmListFileBacktrace()));
7111     }
7112   }
7113 }
7114
7115 cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference(
7116   std::string const& name) const
7117 {
7118   return this->ResolveTargetReference(name, this->LocalGenerator);
7119 }
7120
7121 cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference(
7122   std::string const& name, cmLocalGenerator const* lg) const
7123 {
7124   TargetOrString resolved;
7125
7126   if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(name)) {
7127     resolved.Target = tgt;
7128   } else {
7129     resolved.String = name;
7130   }
7131
7132   return resolved;
7133 }
7134
7135 cmLinkItem cmGeneratorTarget::ResolveLinkItem(
7136   std::string const& name, cmListFileBacktrace const& bt) const
7137 {
7138   return this->ResolveLinkItem(name, bt, this->LocalGenerator);
7139 }
7140
7141 cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name,
7142                                               cmListFileBacktrace const& bt,
7143                                               cmLocalGenerator const* lg) const
7144 {
7145   TargetOrString resolved = this->ResolveTargetReference(name, lg);
7146
7147   if (!resolved.Target) {
7148     return cmLinkItem(resolved.String, false, bt);
7149   }
7150
7151   // Check deprecation, issue message with `bt` backtrace.
7152   if (resolved.Target->IsDeprecated()) {
7153     std::ostringstream w;
7154     /* clang-format off */
7155     w <<
7156       "The library that is being linked to, "  << resolved.Target->GetName() <<
7157       ", is marked as being deprecated by the owner.  The message provided by "
7158       "the developer is: \n" << resolved.Target->GetDeprecation() << "\n";
7159     /* clang-format on */
7160     this->LocalGenerator->GetCMakeInstance()->IssueMessage(
7161       MessageType::AUTHOR_WARNING, w.str(), bt);
7162   }
7163
7164   // Skip targets that will not really be linked.  This is probably a
7165   // name conflict between an external library and an executable
7166   // within the project.
7167   if (resolved.Target->GetType() == cmStateEnums::EXECUTABLE &&
7168       !resolved.Target->IsExecutableWithExports()) {
7169     return cmLinkItem(resolved.Target->GetName(), false, bt);
7170   }
7171
7172   return cmLinkItem(resolved.Target, false, bt);
7173 }
7174
7175 std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const
7176 {
7177   if (OutputInfo const* info = this->GetOutputInfo(config)) {
7178     // Return the directory in which the target will be built.
7179     return info->PdbDir;
7180   }
7181   return "";
7182 }
7183
7184 bool cmGeneratorTarget::HasImplibGNUtoMS(std::string const& config) const
7185 {
7186   return this->HasImportLibrary(config) && this->GetPropertyAsBool("GNUtoMS");
7187 }
7188
7189 bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& config,
7190                                          std::string const& gnuName,
7191                                          std::string& out,
7192                                          const char* newExt) const
7193 {
7194   if (this->HasImplibGNUtoMS(config) && gnuName.size() > 6 &&
7195       gnuName.substr(gnuName.size() - 6) == ".dll.a") {
7196     out = cmStrCat(cm::string_view(gnuName).substr(0, gnuName.size() - 6),
7197                    newExt ? newExt : ".lib");
7198     return true;
7199   }
7200   return false;
7201 }
7202
7203 bool cmGeneratorTarget::IsExecutableWithExports() const
7204 {
7205   return (this->GetType() == cmStateEnums::EXECUTABLE &&
7206           this->GetPropertyAsBool("ENABLE_EXPORTS"));
7207 }
7208
7209 bool cmGeneratorTarget::HasImportLibrary(std::string const& config) const
7210 {
7211   return (this->IsDLLPlatform() &&
7212           (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
7213            this->IsExecutableWithExports()) &&
7214           // Assemblies which have only managed code do not have
7215           // import libraries.
7216           this->GetManagedType(config) != ManagedType::Managed) ||
7217     (this->Target->IsAIX() && this->IsExecutableWithExports());
7218 }
7219
7220 bool cmGeneratorTarget::NeedImportLibraryName(std::string const& config) const
7221 {
7222   return this->HasImportLibrary(config) ||
7223     // On DLL platforms we always generate the import library name
7224     // just in case the sources have export markup.
7225     (this->IsDLLPlatform() &&
7226      (this->GetType() == cmStateEnums::EXECUTABLE ||
7227       this->GetType() == cmStateEnums::MODULE_LIBRARY));
7228 }
7229
7230 std::string cmGeneratorTarget::GetSupportDirectory() const
7231 {
7232   std::string dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
7233                              "/CMakeFiles/", this->GetName());
7234 #if defined(__VMS)
7235   dir += "_dir";
7236 #else
7237   dir += ".dir";
7238 #endif
7239   return dir;
7240 }
7241
7242 bool cmGeneratorTarget::IsLinkable() const
7243 {
7244   return (this->GetType() == cmStateEnums::STATIC_LIBRARY ||
7245           this->GetType() == cmStateEnums::SHARED_LIBRARY ||
7246           this->GetType() == cmStateEnums::MODULE_LIBRARY ||
7247           this->GetType() == cmStateEnums::UNKNOWN_LIBRARY ||
7248           this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
7249           this->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
7250           this->IsExecutableWithExports());
7251 }
7252
7253 bool cmGeneratorTarget::IsFrameworkOnApple() const
7254 {
7255   return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
7256            this->GetType() == cmStateEnums::STATIC_LIBRARY) &&
7257           this->Makefile->IsOn("APPLE") &&
7258           this->GetPropertyAsBool("FRAMEWORK"));
7259 }
7260
7261 bool cmGeneratorTarget::IsAppBundleOnApple() const
7262 {
7263   return (this->GetType() == cmStateEnums::EXECUTABLE &&
7264           this->Makefile->IsOn("APPLE") &&
7265           this->GetPropertyAsBool("MACOSX_BUNDLE"));
7266 }
7267
7268 bool cmGeneratorTarget::IsXCTestOnApple() const
7269 {
7270   return (this->IsCFBundleOnApple() && this->GetPropertyAsBool("XCTEST"));
7271 }
7272
7273 bool cmGeneratorTarget::IsCFBundleOnApple() const
7274 {
7275   return (this->GetType() == cmStateEnums::MODULE_LIBRARY &&
7276           this->Makefile->IsOn("APPLE") && this->GetPropertyAsBool("BUNDLE"));
7277 }
7278
7279 cmGeneratorTarget::ManagedType cmGeneratorTarget::CheckManagedType(
7280   std::string const& propval) const
7281 {
7282   // The type of the managed assembly (mixed unmanaged C++ and C++/CLI,
7283   // or only C++/CLI) does only depend on whether the property is an empty
7284   // string or contains any value at all. In Visual Studio generators
7285   // this propval is prepended with /clr[:] which results in:
7286   //
7287   // 1. propval does not exist: no /clr flag, unmanaged target, has import
7288   //                            lib
7289   // 2. empty propval:          add /clr as flag, mixed unmanaged/managed
7290   //                            target, has import lib
7291   // 3. any value (safe,pure):  add /clr:[propval] as flag, target with
7292   //                            managed code only, no import lib
7293   return propval.empty() ? ManagedType::Mixed : ManagedType::Managed;
7294 }
7295
7296 cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType(
7297   const std::string& config) const
7298 {
7299   // Only libraries and executables can be managed targets.
7300   if (this->GetType() > cmStateEnums::SHARED_LIBRARY) {
7301     return ManagedType::Undefined;
7302   }
7303
7304   if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
7305     return ManagedType::Native;
7306   }
7307
7308   // Check imported target.
7309   if (this->IsImported()) {
7310     if (cmGeneratorTarget::ImportInfo const* info =
7311           this->GetImportInfo(config)) {
7312       return info->Managed;
7313     }
7314     return ManagedType::Undefined;
7315   }
7316
7317   // Check for explicitly set clr target property.
7318   if (cmProp clr = this->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
7319     return this->CheckManagedType(*clr);
7320   }
7321
7322   // C# targets are always managed. This language specific check
7323   // is added to avoid that the COMMON_LANGUAGE_RUNTIME target property
7324   // has to be set manually for C# targets.
7325   return this->IsCSharpOnly() ? ManagedType::Managed : ManagedType::Native;
7326 }