Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Source / cmVisualStudio10TargetGenerator.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 "cmVisualStudio10TargetGenerator.h"
4
5 #include <algorithm>
6 #include <cstdio>
7 #include <cstring>
8 #include <iterator>
9 #include <set>
10 #include <sstream>
11
12 #include <cm/memory>
13 #include <cm/optional>
14 #include <cm/string_view>
15 #include <cm/vector>
16 #include <cmext/algorithm>
17
18 #include "windows.h"
19
20 #include "cmsys/FStream.hxx"
21 #include "cmsys/RegularExpression.hxx"
22
23 #include "cmComputeLinkInformation.h"
24 #include "cmCustomCommand.h"
25 #include "cmCustomCommandGenerator.h"
26 #include "cmGeneratedFileStream.h"
27 #include "cmGeneratorExpression.h"
28 #include "cmGeneratorTarget.h"
29 #include "cmGlobalGenerator.h"
30 #include "cmGlobalVisualStudio10Generator.h"
31 #include "cmGlobalVisualStudio7Generator.h"
32 #include "cmGlobalVisualStudioGenerator.h"
33 #include "cmLinkLineDeviceComputer.h"
34 #include "cmListFileCache.h"
35 #include "cmLocalGenerator.h"
36 #include "cmLocalVisualStudio10Generator.h"
37 #include "cmLocalVisualStudio7Generator.h"
38 #include "cmLocalVisualStudioGenerator.h"
39 #include "cmMakefile.h"
40 #include "cmMessageType.h"
41 #include "cmPropertyMap.h"
42 #include "cmSourceFile.h"
43 #include "cmSourceFileLocation.h"
44 #include "cmSourceFileLocationKind.h"
45 #include "cmSourceGroup.h"
46 #include "cmStateTypes.h"
47 #include "cmStringAlgorithms.h"
48 #include "cmSystemTools.h"
49 #include "cmTarget.h"
50 #include "cmValue.h"
51 #include "cmVisualStudioGeneratorOptions.h"
52
53 struct cmIDEFlagTable;
54
55 static void ConvertToWindowsSlash(std::string& s);
56
57 static std::string cmVS10EscapeXML(std::string arg)
58 {
59   cmSystemTools::ReplaceString(arg, "&", "&amp;");
60   cmSystemTools::ReplaceString(arg, "<", "&lt;");
61   cmSystemTools::ReplaceString(arg, ">", "&gt;");
62   return arg;
63 }
64
65 static std::string cmVS10EscapeAttr(std::string arg)
66 {
67   cmSystemTools::ReplaceString(arg, "&", "&amp;");
68   cmSystemTools::ReplaceString(arg, "<", "&lt;");
69   cmSystemTools::ReplaceString(arg, ">", "&gt;");
70   cmSystemTools::ReplaceString(arg, "\"", "&quot;");
71   cmSystemTools::ReplaceString(arg, "\n", "&#10;");
72   return arg;
73 }
74
75 struct cmVisualStudio10TargetGenerator::Elem
76 {
77   std::ostream& S;
78   const int Indent;
79   bool HasElements = false;
80   bool HasContent = false;
81   std::string Tag;
82
83   Elem(std::ostream& s, const std::string& tag)
84     : S(s)
85     , Indent(0)
86     , Tag(tag)
87   {
88     this->StartElement();
89   }
90   Elem(const Elem&) = delete;
91   Elem(Elem& par, cm::string_view tag)
92     : S(par.S)
93     , Indent(par.Indent + 1)
94     , Tag(std::string(tag))
95   {
96     par.SetHasElements();
97     this->StartElement();
98   }
99   void SetHasElements()
100   {
101     if (!HasElements) {
102       this->S << ">";
103       HasElements = true;
104     }
105   }
106   std::ostream& WriteString(const char* line);
107   void StartElement() { this->WriteString("<") << this->Tag; }
108   void Element(cm::string_view tag, std::string val)
109   {
110     Elem(*this, tag).Content(std::move(val));
111   }
112   Elem& Attribute(const char* an, std::string av)
113   {
114     this->S << " " << an << "=\"" << cmVS10EscapeAttr(std::move(av)) << "\"";
115     return *this;
116   }
117   void Content(std::string val)
118   {
119     if (!this->HasContent) {
120       this->S << ">";
121       this->HasContent = true;
122     }
123     this->S << cmVS10EscapeXML(std::move(val));
124   }
125   ~Elem()
126   {
127     // Do not emit element which has not been started
128     if (Tag.empty()) {
129       return;
130     }
131
132     if (HasElements) {
133       this->WriteString("</") << this->Tag << ">";
134     } else if (HasContent) {
135       this->S << "</" << this->Tag << ">";
136     } else {
137       this->S << " />";
138     }
139   }
140
141   void WritePlatformConfigTag(const std::string& tag, const std::string& cond,
142                               const std::string& content);
143 };
144
145 class cmVS10GeneratorOptions : public cmVisualStudioGeneratorOptions
146 {
147 public:
148   using Elem = cmVisualStudio10TargetGenerator::Elem;
149   cmVS10GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
150                          cmVS7FlagTable const* table,
151                          cmVisualStudio10TargetGenerator* g = nullptr)
152     : cmVisualStudioGeneratorOptions(lg, tool, table)
153     , TargetGenerator(g)
154   {
155   }
156
157   void OutputFlag(std::ostream& /*fout*/, int /*indent*/,
158                   const std::string& tag, const std::string& content) override
159   {
160     if (!this->GetConfiguration().empty()) {
161       // if there are configuration specific flags, then
162       // use the configuration specific tag for PreprocessorDefinitions
163       const std::string cond =
164         this->TargetGenerator->CalcCondition(this->GetConfiguration());
165       this->Parent->WritePlatformConfigTag(tag, cond, content);
166     } else {
167       this->Parent->Element(tag, content);
168     }
169   }
170
171 private:
172   cmVisualStudio10TargetGenerator* const TargetGenerator;
173   Elem* Parent = nullptr;
174   friend cmVisualStudio10TargetGenerator::OptionsHelper;
175 };
176
177 struct cmVisualStudio10TargetGenerator::OptionsHelper
178 {
179   cmVS10GeneratorOptions& O;
180   OptionsHelper(cmVS10GeneratorOptions& o, Elem& e)
181     : O(o)
182   {
183     O.Parent = &e;
184   }
185   ~OptionsHelper() { O.Parent = nullptr; }
186
187   void OutputPreprocessorDefinitions(const std::string& lang)
188   {
189     O.OutputPreprocessorDefinitions(O.Parent->S, O.Parent->Indent + 1, lang);
190   }
191   void OutputAdditionalIncludeDirectories(const std::string& lang)
192   {
193     O.OutputAdditionalIncludeDirectories(O.Parent->S, O.Parent->Indent + 1,
194                                          lang);
195   }
196   void OutputFlagMap() { O.OutputFlagMap(O.Parent->S, O.Parent->Indent + 1); }
197   void PrependInheritedString(std::string const& key)
198   {
199     O.PrependInheritedString(key);
200   }
201 };
202
203 static std::string cmVS10EscapeComment(std::string comment)
204 {
205   // MSBuild takes the CDATA of a <Message></Message> element and just
206   // does "echo $CDATA" with no escapes.  We must encode the string.
207   // http://technet.microsoft.com/en-us/library/cc772462%28WS.10%29.aspx
208   std::string echoable;
209   for (char c : comment) {
210     switch (c) {
211       case '\r':
212         break;
213       case '\n':
214         echoable += '\t';
215         break;
216       case '"': /* no break */
217       case '|': /* no break */
218       case '&': /* no break */
219       case '<': /* no break */
220       case '>': /* no break */
221       case '^':
222         echoable += '^'; /* no break */
223         CM_FALLTHROUGH;
224       default:
225         echoable += c;
226         break;
227     }
228   }
229   return echoable;
230 }
231
232 static bool cmVS10IsTargetsFile(std::string const& path)
233 {
234   std::string const ext = cmSystemTools::GetFilenameLastExtension(path);
235   return cmSystemTools::Strucmp(ext.c_str(), ".targets") == 0;
236 }
237
238 static VsProjectType computeProjectType(cmGeneratorTarget const* t)
239 {
240   if (t->IsCSharpOnly()) {
241     return VsProjectType::csproj;
242   }
243   return VsProjectType::vcxproj;
244 }
245
246 static std::string computeProjectFileExtension(VsProjectType projectType)
247 {
248   switch (projectType) {
249     case VsProjectType::csproj:
250       return ".csproj";
251     case VsProjectType::proj:
252       return ".proj";
253     default:
254       return ".vcxproj";
255   }
256 }
257
258 static std::string computeProjectFileExtension(cmGeneratorTarget const* t)
259 {
260   return computeProjectFileExtension(computeProjectType(t));
261 }
262
263 cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
264   cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg)
265   : GeneratorTarget(target)
266   , Makefile(target->Target->GetMakefile())
267   , Platform(gg->GetPlatformName())
268   , Name(target->GetName())
269   , GUID(gg->GetGUID(this->Name))
270   , GlobalGenerator(gg)
271   , LocalGenerator(
272       (cmLocalVisualStudio10Generator*)target->GetLocalGenerator())
273 {
274   this->Configurations =
275     this->Makefile->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
276   this->NsightTegra = gg->IsNsightTegra();
277   this->Android = gg->TargetsAndroid();
278   for (int i = 0; i < 4; ++i) {
279     this->NsightTegraVersion[i] = 0;
280   }
281   sscanf(gg->GetNsightTegraVersion().c_str(), "%u.%u.%u.%u",
282          &this->NsightTegraVersion[0], &this->NsightTegraVersion[1],
283          &this->NsightTegraVersion[2], &this->NsightTegraVersion[3]);
284   this->MSTools = !this->NsightTegra && !this->Android;
285   this->Managed = false;
286   this->TargetCompileAsWinRT = false;
287   this->IsMissingFiles = false;
288   this->DefaultArtifactDir =
289     this->LocalGenerator->GetCurrentBinaryDirectory() + "/" +
290     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
291   this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() ==
292                          this->Makefile->GetCurrentBinaryDirectory());
293   this->ClassifyAllConfigSources();
294 }
295
296 cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
297 {
298 }
299
300 std::string cmVisualStudio10TargetGenerator::CalcCondition(
301   const std::string& config) const
302 {
303   std::ostringstream oss;
304   oss << "'$(Configuration)|$(Platform)'=='";
305   oss << config << "|" << this->Platform;
306   oss << "'";
307   // handle special case for 32 bit C# targets
308   if (this->ProjectType == VsProjectType::csproj &&
309       this->Platform == "Win32") {
310     oss << " Or ";
311     oss << "'$(Configuration)|$(Platform)'=='";
312     oss << config << "|x86";
313     oss << "'";
314   }
315   return oss.str();
316 }
317
318 void cmVisualStudio10TargetGenerator::Elem::WritePlatformConfigTag(
319   const std::string& tag, const std::string& cond, const std::string& content)
320 {
321   Elem(*this, tag).Attribute("Condition", cond).Content(content);
322 }
323
324 std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
325   const char* line)
326 {
327   this->S << '\n';
328   this->S.fill(' ');
329   this->S.width(this->Indent * 2);
330   // write an empty string to get the fill level indent to print
331   this->S << "";
332   this->S << line;
333   return this->S;
334 }
335
336 #define VS10_CXX_DEFAULT_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
337 #define VS10_CXX_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.props"
338 #define VS10_CXX_USER_PROPS                                                   \
339   "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props"
340 #define VS10_CXX_TARGETS "$(VCTargetsPath)\\Microsoft.Cpp.targets"
341
342 #define VS10_CSharp_DEFAULT_PROPS                                             \
343   "$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props"
344 // This does not seem to exist by default, it's just provided for consistency
345 // in case users want to have default custom props for C# targets
346 #define VS10_CSharp_USER_PROPS                                                \
347   "$(UserRootDir)\\Microsoft.CSharp.$(Platform).user.props"
348 #define VS10_CSharp_TARGETS "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"
349
350 #define VS10_CSharp_NETCF_TARGETS                                             \
351   "$(MSBuildExtensionsPath)\\Microsoft\\$(TargetFrameworkIdentifier)\\"       \
352   "$(TargetFrameworkTargetsVersion)\\Microsoft.$(TargetFrameworkIdentifier)"  \
353   ".CSharp.targets"
354
355 void cmVisualStudio10TargetGenerator::Generate()
356 {
357   for (std::string const& config : this->Configurations) {
358     this->GeneratorTarget->CheckCxxModuleStatus(config);
359   }
360
361   if (this->GeneratorTarget->HaveCxx20ModuleSources()) {
362     this->Makefile->IssueMessage(
363       MessageType::FATAL_ERROR,
364       cmStrCat("The \"", this->GeneratorTarget->GetName(),
365                "\" target contains C++ module sources which are not supported "
366                "by the generator"));
367   }
368
369   this->ProjectType = computeProjectType(this->GeneratorTarget);
370   this->Managed = this->ProjectType == VsProjectType::csproj;
371   const std::string ProjectFileExtension =
372     computeProjectFileExtension(this->ProjectType);
373
374   if (this->ProjectType == VsProjectType::csproj &&
375       this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
376     std::string message = "The C# target \"" +
377       this->GeneratorTarget->GetName() +
378       "\" is of type STATIC_LIBRARY. This is discouraged (and may be "
379       "disabled in future). Make it a SHARED library instead.";
380     this->Makefile->IssueMessage(MessageType::DEPRECATION_WARNING, message);
381   }
382
383   if (this->Android &&
384       this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
385       !this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
386     this->GlobalGenerator->AddAndroidExecutableWarning(this->Name);
387   }
388
389   // Tell the global generator the name of the project file
390   this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
391                                              this->Name);
392   this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
393                                              ProjectFileExtension);
394   this->DotNetHintReferences.clear();
395   this->AdditionalUsingDirectories.clear();
396   if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
397     if (!this->ComputeClOptions()) {
398       return;
399     }
400     if (!this->ComputeRcOptions()) {
401       return;
402     }
403     if (!this->ComputeCudaOptions()) {
404       return;
405     }
406     if (!this->ComputeCudaLinkOptions()) {
407       return;
408     }
409     if (!this->ComputeMasmOptions()) {
410       return;
411     }
412     if (!this->ComputeNasmOptions()) {
413       return;
414     }
415     if (!this->ComputeLinkOptions()) {
416       return;
417     }
418     if (!this->ComputeLibOptions()) {
419       return;
420     }
421   }
422   std::string path =
423     cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
424              this->Name, ProjectFileExtension);
425   cmGeneratedFileStream BuildFileStream(path);
426   const std::string PathToProjectFile = path;
427   BuildFileStream.SetCopyIfDifferent(true);
428
429   // Write the encoding header into the file
430   char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
431   BuildFileStream.write(magic, 3);
432
433   if (this->ProjectType == VsProjectType::csproj &&
434       this->GeneratorTarget->IsDotNetSdkTarget() &&
435       this->GlobalGenerator->GetVersion() >=
436         cmGlobalVisualStudioGenerator::VSVersion::VS16) {
437     this->WriteSdkStyleProjectFile(BuildFileStream);
438   } else {
439     this->WriteClassicMsBuildProjectFile(BuildFileStream);
440   }
441
442   if (BuildFileStream.Close()) {
443     this->GlobalGenerator->FileReplacedDuringGenerate(PathToProjectFile);
444   }
445
446   // The groups are stored in a separate file for VS 10
447   this->WriteGroups();
448
449   // Update cache with project-specific entries.
450   this->UpdateCache();
451 }
452
453 void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile(
454   cmGeneratedFileStream& BuildFileStream)
455 {
456   BuildFileStream << "<?xml version=\"1.0\" encoding=\""
457                   << this->GlobalGenerator->Encoding() << "\"?>";
458   {
459     Elem e0(BuildFileStream, "Project");
460     e0.Attribute("DefaultTargets", "Build");
461     const char* toolsVersion = this->GlobalGenerator->GetToolsVersion();
462     if (this->GlobalGenerator->GetVersion() ==
463           cmGlobalVisualStudioGenerator::VSVersion::VS12 &&
464         this->GlobalGenerator->TargetsWindowsCE()) {
465       toolsVersion = "4.0";
466     }
467     e0.Attribute("ToolsVersion", toolsVersion);
468     e0.Attribute("xmlns",
469                  "http://schemas.microsoft.com/developer/msbuild/2003");
470
471     if (this->NsightTegra) {
472       Elem e1(e0, "PropertyGroup");
473       e1.Attribute("Label", "NsightTegraProject");
474       const unsigned int nsightTegraMajorVersion = this->NsightTegraVersion[0];
475       const unsigned int nsightTegraMinorVersion = this->NsightTegraVersion[1];
476       if (nsightTegraMajorVersion >= 2) {
477         if (nsightTegraMajorVersion > 3 ||
478             (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) {
479           e1.Element("NsightTegraProjectRevisionNumber", "11");
480         } else {
481           // Nsight Tegra 2.0 uses project revision 9.
482           e1.Element("NsightTegraProjectRevisionNumber", "9");
483         }
484         // Tell newer versions to upgrade silently when loading.
485         e1.Element("NsightTegraUpgradeOnceWithoutPrompt", "true");
486       } else {
487         // Require Nsight Tegra 1.6 for JCompile support.
488         e1.Element("NsightTegraProjectRevisionNumber", "7");
489       }
490     }
491
492     if (const char* hostArch =
493           this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
494       Elem e1(e0, "PropertyGroup");
495       e1.Element("PreferredToolArchitecture", hostArch);
496     }
497
498     // The ALL_BUILD, PACKAGE, and ZERO_CHECK projects transitively include
499     // Microsoft.Common.CurrentVersion.targets which triggers Target
500     // ResolveNugetPackageAssets when SDK-style targets are in the project.
501     // However, these projects have no nuget packages to reference and the
502     // build fails.
503     // Setting ResolveNugetPackages to false skips this target and the build
504     // succeeds.
505     cm::string_view targetName{ this->GeneratorTarget->GetName() };
506     if (targetName == "ALL_BUILD" || targetName == "PACKAGE" ||
507         targetName == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
508       Elem e1(e0, "PropertyGroup");
509       e1.Element("ResolveNugetPackages", "false");
510     }
511
512     if (this->ProjectType != VsProjectType::csproj) {
513       this->WriteProjectConfigurations(e0);
514     }
515
516     {
517       Elem e1(e0, "PropertyGroup");
518       this->WriteCommonPropertyGroupGlobals(e1);
519
520       if ((this->MSTools || this->Android) &&
521           this->GeneratorTarget->IsInBuildSystem()) {
522         this->WriteApplicationTypeSettings(e1);
523         this->VerifyNecessaryFiles();
524       }
525
526       cmValue vsProjectName =
527         this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
528       cmValue vsLocalPath =
529         this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
530       cmValue vsProvider =
531         this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
532
533       if (vsProjectName && vsLocalPath && vsProvider) {
534         e1.Element("SccProjectName", *vsProjectName);
535         e1.Element("SccLocalPath", *vsLocalPath);
536         e1.Element("SccProvider", *vsProvider);
537
538         cmValue vsAuxPath =
539           this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
540         if (vsAuxPath) {
541           e1.Element("SccAuxPath", *vsAuxPath);
542         }
543       }
544
545       if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
546         e1.Element("WinMDAssembly", "true");
547       }
548
549       e1.Element("Platform", this->Platform);
550       cmValue projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
551       e1.Element("ProjectName", projLabel ? projLabel : this->Name);
552       {
553         cm::optional<std::string> targetFramework;
554         cm::optional<std::string> targetFrameworkVersion;
555         cm::optional<std::string> targetFrameworkIdentifier;
556         cm::optional<std::string> targetFrameworkTargetsVersion;
557         if (cmValue tf =
558               this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK")) {
559           targetFramework = *tf;
560         } else if (cmValue vstfVer = this->GeneratorTarget->GetProperty(
561                      "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
562           // FIXME: Someday, add a deprecation warning for VS_* property.
563           targetFrameworkVersion = *vstfVer;
564         } else if (cmValue tfVer = this->GeneratorTarget->GetProperty(
565                      "DOTNET_TARGET_FRAMEWORK_VERSION")) {
566           targetFrameworkVersion = *tfVer;
567         } else if (this->ProjectType == VsProjectType::csproj) {
568           targetFrameworkVersion =
569             this->GlobalGenerator->GetTargetFrameworkVersion();
570         }
571         if (this->ProjectType == VsProjectType::vcxproj &&
572             this->GlobalGenerator->TargetsWindowsCE()) {
573           e1.Element("EnableRedirectPlatform", "true");
574           e1.Element("RedirectPlatformValue", this->Platform);
575         }
576         if (this->ProjectType == VsProjectType::csproj) {
577           if (this->GlobalGenerator->TargetsWindowsCE()) {
578             // FIXME: These target VS_TARGET_FRAMEWORK* target properties
579             // are undocumented settings only ever supported for WinCE.
580             // We need a better way to control these in general.
581             if (cmValue tfId = this->GeneratorTarget->GetProperty(
582                   "VS_TARGET_FRAMEWORK_IDENTIFIER")) {
583               targetFrameworkIdentifier = *tfId;
584             }
585             if (cmValue tfTargetsVer = this->GeneratorTarget->GetProperty(
586                   "VS_TARGET_FRAMEWORKS_TARGET_VERSION")) {
587               targetFrameworkTargetsVersion = *tfTargetsVer;
588             }
589           }
590           if (!targetFrameworkIdentifier) {
591             targetFrameworkIdentifier =
592               this->GlobalGenerator->GetTargetFrameworkIdentifier();
593           }
594           if (!targetFrameworkTargetsVersion) {
595             targetFrameworkTargetsVersion =
596               this->GlobalGenerator->GetTargetFrameworkTargetsVersion();
597           }
598         }
599         if (targetFramework) {
600           if (targetFramework->find(';') != std::string::npos) {
601             e1.Element("TargetFrameworks", *targetFramework);
602           } else {
603             e1.Element("TargetFramework", *targetFramework);
604           }
605         }
606         if (targetFrameworkVersion) {
607           e1.Element("TargetFrameworkVersion", *targetFrameworkVersion);
608         }
609         if (targetFrameworkIdentifier) {
610           e1.Element("TargetFrameworkIdentifier", *targetFrameworkIdentifier);
611         }
612         if (targetFrameworkTargetsVersion) {
613           e1.Element("TargetFrameworkTargetsVersion",
614                      *targetFrameworkTargetsVersion);
615         }
616         if (!this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString()
617                .empty()) {
618           e1.Element(
619             "CudaToolkitCustomDir",
620             this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString() +
621               this->GlobalGenerator->GetPlatformToolsetCudaNvccSubdirString());
622         }
623       }
624
625       // Disable the project upgrade prompt that is displayed the first time a
626       // project using an older toolset version is opened in a newer version of
627       // the IDE (respected by VS 2013 and above).
628       if (this->GlobalGenerator->GetVersion() >=
629           cmGlobalVisualStudioGenerator::VSVersion::VS12) {
630         e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
631       }
632
633       if (const char* vcTargetsPath =
634             this->GlobalGenerator->GetCustomVCTargetsPath()) {
635         e1.Element("VCTargetsPath", vcTargetsPath);
636       }
637
638       if (this->Managed) {
639         if (this->LocalGenerator->GetVersion() >=
640             cmGlobalVisualStudioGenerator::VSVersion::VS17) {
641           e1.Element("ManagedAssembly", "true");
642         }
643         std::string outputType;
644         switch (this->GeneratorTarget->GetType()) {
645           case cmStateEnums::OBJECT_LIBRARY:
646           case cmStateEnums::STATIC_LIBRARY:
647           case cmStateEnums::SHARED_LIBRARY:
648             outputType = "Library";
649             break;
650           case cmStateEnums::MODULE_LIBRARY:
651             outputType = "Module";
652             break;
653           case cmStateEnums::EXECUTABLE: {
654             auto const win32 =
655               this->GeneratorTarget->GetSafeProperty("WIN32_EXECUTABLE");
656             if (win32.find("$<") != std::string::npos) {
657               this->Makefile->IssueMessage(
658                 MessageType::FATAL_ERROR,
659                 cmStrCat(
660                   "Target \"", this->GeneratorTarget->GetName(),
661                   "\" has a generator expression in its WIN32_EXECUTABLE "
662                   "property. This is not supported on managed executables."));
663               return;
664             }
665             if (cmIsOn(win32)) {
666               outputType = "WinExe";
667             } else {
668               outputType = "Exe";
669             }
670           } break;
671           case cmStateEnums::UTILITY:
672           case cmStateEnums::INTERFACE_LIBRARY:
673           case cmStateEnums::GLOBAL_TARGET:
674             outputType = "Utility";
675             break;
676           case cmStateEnums::UNKNOWN_LIBRARY:
677             break;
678         }
679         e1.Element("OutputType", outputType);
680         e1.Element("AppDesignerFolder", "Properties");
681       }
682     }
683
684     cmValue startupObject =
685       this->GeneratorTarget->GetProperty("VS_DOTNET_STARTUP_OBJECT");
686
687     if (startupObject && this->Managed) {
688       Elem e1(e0, "PropertyGroup");
689       e1.Element("StartupObject", *startupObject);
690     }
691
692     switch (this->ProjectType) {
693       case VsProjectType::vcxproj: {
694         std::string const& props =
695           this->GlobalGenerator->GetPlatformToolsetVersionProps();
696         if (!props.empty()) {
697           Elem(e0, "Import").Attribute("Project", props);
698         }
699         Elem(e0, "Import").Attribute("Project", VS10_CXX_DEFAULT_PROPS);
700       } break;
701       case VsProjectType::csproj:
702         Elem(e0, "Import")
703           .Attribute("Project", VS10_CSharp_DEFAULT_PROPS)
704           .Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')");
705         break;
706       default:
707         break;
708     }
709
710     this->WriteProjectConfigurationValues(e0);
711
712     if (this->ProjectType == VsProjectType::vcxproj) {
713       Elem(e0, "Import").Attribute("Project", VS10_CXX_PROPS);
714     }
715     {
716       Elem e1(e0, "ImportGroup");
717       e1.Attribute("Label", "ExtensionSettings");
718       e1.SetHasElements();
719
720       if (this->GlobalGenerator->IsCudaEnabled()) {
721         auto customDir =
722           this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
723         std::string cudaPath = customDir.empty()
724           ? "$(VCTargetsPath)\\BuildCustomizations\\"
725           : customDir +
726             this->GlobalGenerator
727               ->GetPlatformToolsetCudaVSIntegrationSubdirString() +
728             "extras\\visual_studio_integration\\MSBuildExtensions\\";
729         Elem(e1, "Import")
730           .Attribute("Project",
731                      std::move(cudaPath) + "CUDA " +
732                        this->GlobalGenerator->GetPlatformToolsetCuda() +
733                        ".props");
734       }
735       if (this->GlobalGenerator->IsMasmEnabled()) {
736         Elem(e1, "Import")
737           .Attribute("Project",
738                      "$(VCTargetsPath)\\BuildCustomizations\\masm.props");
739       }
740       if (this->GlobalGenerator->IsNasmEnabled()) {
741         // Always search in the standard modules location.
742         std::string propsTemplate =
743           GetCMakeFilePath("Templates/MSBuild/nasm.props.in");
744
745         std::string propsLocal =
746           cmStrCat(this->DefaultArtifactDir, "\\nasm.props");
747         ConvertToWindowsSlash(propsLocal);
748         this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true,
749                                       true);
750         Elem(e1, "Import").Attribute("Project", propsLocal);
751       }
752     }
753     {
754       Elem e1(e0, "ImportGroup");
755       e1.Attribute("Label", "PropertySheets");
756       std::string props;
757       switch (this->ProjectType) {
758         case VsProjectType::vcxproj:
759           props = VS10_CXX_USER_PROPS;
760           break;
761         case VsProjectType::csproj:
762           props = VS10_CSharp_USER_PROPS;
763           break;
764         default:
765           break;
766       }
767       if (cmValue p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
768         props = *p;
769       }
770       if (!props.empty()) {
771         ConvertToWindowsSlash(props);
772         Elem(e1, "Import")
773           .Attribute("Project", props)
774           .Attribute("Condition", "exists('" + props + "')")
775           .Attribute("Label", "LocalAppDataPlatform");
776       }
777
778       this->WritePlatformExtensions(e1);
779     }
780
781     this->WriteDotNetDocumentationFile(e0);
782     Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros");
783     this->WriteWinRTPackageCertificateKeyFile(e0);
784     this->WritePathAndIncrementalLinkOptions(e0);
785     this->WriteCEDebugProjectConfigurationValues(e0);
786     this->WriteItemDefinitionGroups(e0);
787     this->WriteCustomCommands(e0);
788     this->WriteAllSources(e0);
789     this->WriteDotNetReferences(e0);
790     this->WritePackageReferences(e0);
791     this->WriteImports(e0);
792     this->WriteEmbeddedResourceGroup(e0);
793     this->WriteXamlFilesGroup(e0);
794     this->WriteWinRTReferences(e0);
795     this->WriteProjectReferences(e0);
796     this->WriteSDKReferences(e0);
797     switch (this->ProjectType) {
798       case VsProjectType::vcxproj:
799         Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS);
800         break;
801       case VsProjectType::csproj:
802         if (this->GlobalGenerator->TargetsWindowsCE()) {
803           Elem(e0, "Import").Attribute("Project", VS10_CSharp_NETCF_TARGETS);
804         } else {
805           Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS);
806         }
807         break;
808       default:
809         break;
810     }
811
812     this->WriteTargetSpecificReferences(e0);
813     {
814       Elem e1(e0, "ImportGroup");
815       e1.Attribute("Label", "ExtensionTargets");
816       e1.SetHasElements();
817       this->WriteTargetsFileReferences(e1);
818       if (this->GlobalGenerator->IsCudaEnabled()) {
819         auto customDir =
820           this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
821         std::string cudaPath = customDir.empty()
822           ? "$(VCTargetsPath)\\BuildCustomizations\\"
823           : customDir +
824             this->GlobalGenerator
825               ->GetPlatformToolsetCudaVSIntegrationSubdirString() +
826             "extras\\visual_studio_integration\\MSBuildExtensions\\";
827         Elem(e1, "Import")
828           .Attribute("Project",
829                      std::move(cudaPath) + "CUDA " +
830                        this->GlobalGenerator->GetPlatformToolsetCuda() +
831                        ".targets");
832       }
833       if (this->GlobalGenerator->IsMasmEnabled()) {
834         Elem(e1, "Import")
835           .Attribute("Project",
836                      "$(VCTargetsPath)\\BuildCustomizations\\masm.targets");
837       }
838       if (this->GlobalGenerator->IsNasmEnabled()) {
839         std::string nasmTargets =
840           GetCMakeFilePath("Templates/MSBuild/nasm.targets");
841         Elem(e1, "Import").Attribute("Project", nasmTargets);
842       }
843     }
844     if (this->ProjectType == VsProjectType::vcxproj &&
845         this->HaveCustomCommandDepfile) {
846       std::string depfileTargets =
847         GetCMakeFilePath("Templates/MSBuild/CustomBuildDepFile.targets");
848       Elem(e0, "Import").Attribute("Project", depfileTargets);
849     }
850     if (this->ProjectType == VsProjectType::csproj) {
851       for (std::string const& c : this->Configurations) {
852         Elem e1(e0, "PropertyGroup");
853         e1.Attribute("Condition", "'$(Configuration)' == '" + c + "'");
854         e1.SetHasElements();
855         this->WriteEvents(e1, c);
856       }
857       // make sure custom commands are executed before build (if necessary)
858       {
859         Elem e1(e0, "PropertyGroup");
860         std::ostringstream oss;
861         oss << "\n";
862         for (std::string const& i : this->CSharpCustomCommandNames) {
863           oss << "      " << i << ";\n";
864         }
865         oss << "      "
866             << "$(BuildDependsOn)\n";
867         e1.Element("BuildDependsOn", oss.str());
868       }
869     }
870   }
871 }
872
873 void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile(
874   cmGeneratedFileStream& BuildFileStream)
875 {
876   if (this->ProjectType != VsProjectType::csproj ||
877       !this->GeneratorTarget->IsDotNetSdkTarget()) {
878     std::string message = "The target \"" + this->GeneratorTarget->GetName() +
879       "\" is not eligible for .Net SDK style project.";
880     this->Makefile->IssueMessage(MessageType::INTERNAL_ERROR, message);
881     return;
882   }
883
884   if (this->HasCustomCommands()) {
885     std::string message = "The target \"" + this->GeneratorTarget->GetName() +
886       "\" does not currently support add_custom_command as the Visual Studio "
887       "generators have not yet learned how to generate custom commands in "
888       ".Net SDK-style projects.";
889     this->Makefile->IssueMessage(MessageType::FATAL_ERROR, message);
890     return;
891   }
892
893   Elem e0(BuildFileStream, "Project");
894   e0.Attribute("Sdk", *this->GeneratorTarget->GetProperty("DOTNET_SDK"));
895
896   {
897     Elem e1(e0, "PropertyGroup");
898     this->WriteCommonPropertyGroupGlobals(e1);
899
900     e1.Element("EnableDefaultItems", "false");
901     // Disable the project upgrade prompt that is displayed the first time a
902     // project using an older toolset version is opened in a newer version
903     // of the IDE.
904     e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
905     e1.Element("ManagedAssembly", "true");
906
907     cmValue targetFramework =
908       this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK");
909     if (targetFramework) {
910       if (targetFramework->find(';') != std::string::npos) {
911         e1.Element("TargetFrameworks", *targetFramework);
912       } else {
913         e1.Element("TargetFramework", *targetFramework);
914         e1.Element("AppendTargetFrameworkToOutputPath", "false");
915       }
916     } else {
917       e1.Element("TargetFramework", "net5.0");
918       e1.Element("AppendTargetFrameworkToOutputPath", "false");
919     }
920
921     std::string outputType;
922     switch (this->GeneratorTarget->GetType()) {
923       case cmStateEnums::OBJECT_LIBRARY:
924       case cmStateEnums::STATIC_LIBRARY:
925       case cmStateEnums::MODULE_LIBRARY:
926         this->Makefile->IssueMessage(
927           MessageType::FATAL_ERROR,
928           cmStrCat("Target \"", this->GeneratorTarget->GetName(),
929                    "\" is of a type not supported for managed binaries."));
930         return;
931       case cmStateEnums::SHARED_LIBRARY:
932         outputType = "Library";
933         break;
934       case cmStateEnums::EXECUTABLE: {
935         auto const win32 =
936           this->GeneratorTarget->GetSafeProperty("WIN32_EXECUTABLE");
937         if (win32.find("$<") != std::string::npos) {
938           this->Makefile->IssueMessage(
939             MessageType::FATAL_ERROR,
940             cmStrCat("Target \"", this->GeneratorTarget->GetName(),
941                      "\" has a generator expression in its WIN32_EXECUTABLE "
942                      "property. This is not supported on managed "
943                      "executables."));
944           return;
945         }
946         outputType = "Exe";
947       } break;
948       case cmStateEnums::UTILITY:
949       case cmStateEnums::INTERFACE_LIBRARY:
950       case cmStateEnums::GLOBAL_TARGET:
951         outputType = "Utility";
952         break;
953       case cmStateEnums::UNKNOWN_LIBRARY:
954         break;
955     }
956     e1.Element("OutputType", outputType);
957
958     cmValue startupObject =
959       this->GeneratorTarget->GetProperty("VS_DOTNET_STARTUP_OBJECT");
960     if (startupObject) {
961       e1.Element("StartupObject", *startupObject);
962     }
963   }
964
965   for (const std::string& config : this->Configurations) {
966     Elem e1(e0, "PropertyGroup");
967     e1.Attribute("Condition", "'$(Configuration)' == '" + config + "'");
968     e1.SetHasElements();
969     this->WriteEvents(e1, config);
970
971     std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
972     ConvertToWindowsSlash(outDir);
973     e1.Element("OutputPath", outDir);
974
975     Options& o = *(this->ClOptions[config]);
976     OptionsHelper oh(o, e1);
977     oh.OutputFlagMap();
978   }
979
980   this->WriteDotNetDocumentationFile(e0);
981   this->WriteAllSources(e0);
982   this->WriteDotNetReferences(e0);
983   this->WritePackageReferences(e0);
984   this->WriteProjectReferences(e0);
985 }
986
987 void cmVisualStudio10TargetGenerator::WriteCommonPropertyGroupGlobals(Elem& e1)
988 {
989   e1.Attribute("Label", "Globals");
990   e1.Element("ProjectGuid", "{" + this->GUID + "}");
991
992   cmValue vsProjectTypes =
993     this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
994   if (vsProjectTypes) {
995     const char* tagName = "ProjectTypes";
996     if (this->ProjectType == VsProjectType::csproj) {
997       tagName = "ProjectTypeGuids";
998     }
999     e1.Element(tagName, *vsProjectTypes);
1000   }
1001
1002   cmValue vsGlobalKeyword =
1003     this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
1004   if (!vsGlobalKeyword) {
1005     if (this->GlobalGenerator->TargetsAndroid()) {
1006       e1.Element("Keyword", "Android");
1007     } else {
1008       e1.Element("Keyword", "Win32Proj");
1009     }
1010   } else {
1011     e1.Element("Keyword", *vsGlobalKeyword);
1012   }
1013
1014   cmValue vsGlobalRootNamespace =
1015     this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
1016   if (vsGlobalRootNamespace) {
1017     e1.Element("RootNamespace", *vsGlobalRootNamespace);
1018   }
1019
1020   std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
1021   for (std::string const& keyIt : keys) {
1022     static const cm::string_view prefix = "VS_GLOBAL_";
1023     if (!cmHasPrefix(keyIt, prefix))
1024       continue;
1025     cm::string_view globalKey = cm::string_view(keyIt).substr(prefix.length());
1026     // Skip invalid or separately-handled properties.
1027     if (globalKey.empty() || globalKey == "PROJECT_TYPES" ||
1028         globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
1029       continue;
1030     }
1031     cmValue value = this->GeneratorTarget->GetProperty(keyIt);
1032     if (!value)
1033       continue;
1034     e1.Element(globalKey, *value);
1035   }
1036 }
1037
1038 bool cmVisualStudio10TargetGenerator::HasCustomCommands() const
1039 {
1040   if (!this->GeneratorTarget->GetPreBuildCommands().empty() ||
1041       !this->GeneratorTarget->GetPreLinkCommands().empty() ||
1042       !this->GeneratorTarget->GetPostBuildCommands().empty()) {
1043     return true;
1044   }
1045
1046   for (cmGeneratorTarget::AllConfigSource const& si :
1047        this->GeneratorTarget->GetAllConfigSources()) {
1048     if (si.Source->GetCustomCommand()) {
1049       return true;
1050     }
1051   }
1052
1053   return false;
1054 }
1055
1056 void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0)
1057 {
1058   std::vector<std::string> packageReferences =
1059     this->GeneratorTarget->GetPackageReferences();
1060
1061   if (!packageReferences.empty()) {
1062     Elem e1(e0, "ItemGroup");
1063     for (std::string const& ri : packageReferences) {
1064       size_t versionIndex = ri.find_last_of('_');
1065       if (versionIndex != std::string::npos) {
1066         Elem e2(e1, "PackageReference");
1067         e2.Attribute("Include", ri.substr(0, versionIndex));
1068         e2.Attribute("Version", ri.substr(versionIndex + 1));
1069       }
1070     }
1071   }
1072 }
1073
1074 void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0)
1075 {
1076   std::vector<std::string> references;
1077   if (cmValue vsDotNetReferences =
1078         this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) {
1079     cmExpandList(*vsDotNetReferences, references);
1080   }
1081   cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
1082   for (auto const& i : props.GetList()) {
1083     static const cm::string_view vsDnRef = "VS_DOTNET_REFERENCE_";
1084     if (cmHasPrefix(i.first, vsDnRef)) {
1085       std::string path = i.second;
1086       if (!cmsys::SystemTools::FileIsFullPath(path)) {
1087         path = this->Makefile->GetCurrentSourceDirectory() + "/" + path;
1088       }
1089       ConvertToWindowsSlash(path);
1090       this->DotNetHintReferences[""].emplace_back(
1091         DotNetHintReference(i.first.substr(vsDnRef.length()), path));
1092     }
1093   }
1094   if (!references.empty() || !this->DotNetHintReferences.empty()) {
1095     Elem e1(e0, "ItemGroup");
1096     for (std::string const& ri : references) {
1097       // if the entry from VS_DOTNET_REFERENCES is an existing file, generate
1098       // a new hint-reference and name it from the filename
1099       if (cmsys::SystemTools::FileExists(ri, true)) {
1100         std::string name =
1101           cmsys::SystemTools::GetFilenameWithoutLastExtension(ri);
1102         std::string path = ri;
1103         ConvertToWindowsSlash(path);
1104         this->DotNetHintReferences[""].emplace_back(
1105           DotNetHintReference(name, path));
1106       } else {
1107         this->WriteDotNetReference(e1, ri, "", "");
1108       }
1109     }
1110     for (const auto& h : this->DotNetHintReferences) {
1111       // DotNetHintReferences is also populated from AddLibraries().
1112       // The configuration specific hint references are added there.
1113       for (const auto& i : h.second) {
1114         this->WriteDotNetReference(e1, i.first, i.second, h.first);
1115       }
1116     }
1117   }
1118 }
1119
1120 void cmVisualStudio10TargetGenerator::WriteDotNetReference(
1121   Elem& e1, std::string const& ref, std::string const& hint,
1122   std::string const& config)
1123 {
1124   Elem e2(e1, "Reference");
1125   // If 'config' is not empty, the reference is only added for the given
1126   // configuration. This is used when referencing imported managed assemblies.
1127   // See also cmVisualStudio10TargetGenerator::AddLibraries().
1128   if (!config.empty()) {
1129     e2.Attribute("Condition", this->CalcCondition(config));
1130   }
1131   e2.Attribute("Include", ref);
1132   e2.Element("CopyLocalSatelliteAssemblies", "true");
1133   e2.Element("ReferenceOutputAssembly", "true");
1134   if (!hint.empty()) {
1135     const char* privateReference = "True";
1136     if (cmValue value = this->GeneratorTarget->GetProperty(
1137           "VS_DOTNET_REFERENCES_COPY_LOCAL")) {
1138       if (cmIsOff(*value)) {
1139         privateReference = "False";
1140       }
1141     }
1142     e2.Element("Private", privateReference);
1143     e2.Element("HintPath", hint);
1144   }
1145   this->WriteDotNetReferenceCustomTags(e2, ref);
1146 }
1147
1148 void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0)
1149 {
1150   cmValue imports =
1151     this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT");
1152   if (imports) {
1153     std::vector<std::string> argsSplit = cmExpandedList(*imports, false);
1154     for (auto& path : argsSplit) {
1155       if (!cmsys::SystemTools::FileIsFullPath(path)) {
1156         path = this->Makefile->GetCurrentSourceDirectory() + "/" + path;
1157       }
1158       ConvertToWindowsSlash(path);
1159       Elem e1(e0, "Import");
1160       e1.Attribute("Project", path);
1161     }
1162   }
1163 }
1164
1165 void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags(
1166   Elem& e2, std::string const& ref)
1167 {
1168
1169   static const std::string refpropPrefix = "VS_DOTNET_REFERENCEPROP_";
1170   static const std::string refpropInfix = "_TAG_";
1171   const std::string refPropFullPrefix = refpropPrefix + ref + refpropInfix;
1172   using CustomTags = std::map<std::string, std::string>;
1173   CustomTags tags;
1174   cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
1175   for (const auto& i : props.GetList()) {
1176     if (cmHasPrefix(i.first, refPropFullPrefix) && !i.second.empty()) {
1177       tags[i.first.substr(refPropFullPrefix.length())] = i.second;
1178     }
1179   }
1180   for (auto const& tag : tags) {
1181     e2.Element(tag.first, tag.second);
1182   }
1183 }
1184
1185 void cmVisualStudio10TargetGenerator::WriteDotNetDocumentationFile(Elem& e0)
1186 {
1187   std::string const& documentationFile =
1188     this->GeneratorTarget->GetSafeProperty("VS_DOTNET_DOCUMENTATION_FILE");
1189
1190   if (this->ProjectType == VsProjectType::csproj &&
1191       !documentationFile.empty()) {
1192     Elem e1(e0, "PropertyGroup");
1193     Elem e2(e1, "DocumentationFile");
1194     e2.Content(documentationFile);
1195   }
1196 }
1197
1198 void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
1199 {
1200   if (!this->ResxObjs.empty()) {
1201     Elem e1(e0, "ItemGroup");
1202     std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
1203     ConvertToWindowsSlash(srcDir);
1204     for (cmSourceFile const* oi : this->ResxObjs) {
1205       std::string obj = oi->GetFullPath();
1206       ConvertToWindowsSlash(obj);
1207       bool useRelativePath = false;
1208       if (this->ProjectType == VsProjectType::csproj && this->InSourceBuild) {
1209         // If we do an in-source build and the resource file is in a
1210         // subdirectory
1211         // of the .csproj file, we have to use relative pathnames, otherwise
1212         // visual studio does not show the file in the IDE. Sorry.
1213         if (cmHasPrefix(obj, srcDir)) {
1214           obj = this->ConvertPath(obj, true);
1215           ConvertToWindowsSlash(obj);
1216           useRelativePath = true;
1217         }
1218       }
1219       Elem e2(e1, "EmbeddedResource");
1220       e2.Attribute("Include", obj);
1221
1222       if (this->ProjectType != VsProjectType::csproj) {
1223         std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
1224         e2.Element("DependentUpon", hFileName);
1225
1226         for (std::string const& c : this->Configurations) {
1227           std::string s;
1228           if (this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE") ||
1229               // Handle variant of VS_GLOBAL_<variable> for RootNamespace.
1230               this->GeneratorTarget->GetProperty("VS_GLOBAL_RootNamespace")) {
1231             s = "$(RootNamespace).";
1232           }
1233           s += "%(Filename).resources";
1234           e2.WritePlatformConfigTag("LogicalName", this->CalcCondition(c), s);
1235         }
1236       } else {
1237         std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
1238         ConvertToWindowsSlash(binDir);
1239         // If the resource was NOT added using a relative path (which should
1240         // be the default), we have to provide a link here
1241         if (!useRelativePath) {
1242           std::string link = this->GetCSharpSourceLink(oi);
1243           if (link.empty()) {
1244             link = cmsys::SystemTools::GetFilenameName(obj);
1245           }
1246           e2.Element("Link", link);
1247         }
1248         // Determine if this is a generated resource from a .Designer.cs file
1249         std::string designerResource =
1250           cmSystemTools::GetFilenamePath(oi->GetFullPath()) + "/" +
1251           cmSystemTools::GetFilenameWithoutLastExtension(oi->GetFullPath()) +
1252           ".Designer.cs";
1253         if (cmsys::SystemTools::FileExists(designerResource)) {
1254           std::string generator = "PublicResXFileCodeGenerator";
1255           if (cmValue g = oi->GetProperty("VS_RESOURCE_GENERATOR")) {
1256             generator = *g;
1257           }
1258           if (!generator.empty()) {
1259             e2.Element("Generator", generator);
1260             if (cmHasPrefix(designerResource, srcDir)) {
1261               designerResource.erase(0, srcDir.length());
1262             } else if (cmHasPrefix(designerResource, binDir)) {
1263               designerResource.erase(0, binDir.length());
1264             } else {
1265               designerResource =
1266                 cmsys::SystemTools::GetFilenameName(designerResource);
1267             }
1268             ConvertToWindowsSlash(designerResource);
1269             e2.Element("LastGenOutput", designerResource);
1270           }
1271         }
1272         const cmPropertyMap& props = oi->GetProperties();
1273         for (const std::string& p : props.GetKeys()) {
1274           static const cm::string_view propNamePrefix = "VS_CSHARP_";
1275           if (cmHasPrefix(p, propNamePrefix)) {
1276             cm::string_view tagName =
1277               cm::string_view(p).substr(propNamePrefix.length());
1278             if (!tagName.empty()) {
1279               cmValue value = props.GetPropertyValue(p);
1280               if (cmNonempty(value)) {
1281                 e2.Element(tagName, *value);
1282               }
1283             }
1284           }
1285         }
1286       }
1287     }
1288   }
1289 }
1290
1291 void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0)
1292 {
1293   if (!this->XamlObjs.empty()) {
1294     Elem e1(e0, "ItemGroup");
1295     for (cmSourceFile const* oi : this->XamlObjs) {
1296       std::string obj = oi->GetFullPath();
1297       std::string xamlType;
1298       cmValue xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
1299       if (xamlTypeProperty) {
1300         xamlType = *xamlTypeProperty;
1301       } else {
1302         xamlType = "Page";
1303       }
1304
1305       Elem e2(e1, xamlType);
1306       this->WriteSource(e2, oi);
1307       e2.SetHasElements();
1308       e2.Element("SubType", "Designer");
1309     }
1310   }
1311 }
1312
1313 void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences(Elem& e0)
1314 {
1315   if (this->MSTools) {
1316     if (this->GlobalGenerator->TargetsWindowsPhone() &&
1317         this->GlobalGenerator->GetSystemVersion() == "8.0") {
1318       Elem(e0, "Import")
1319         .Attribute("Project",
1320                    "$(MSBuildExtensionsPath)\\Microsoft\\WindowsPhone\\v"
1321                    "$(TargetPlatformVersion)\\Microsoft.Cpp.WindowsPhone."
1322                    "$(TargetPlatformVersion).targets");
1323     }
1324   }
1325 }
1326
1327 void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences(Elem& e1)
1328 {
1329   for (TargetsFileAndConfigs const& tac : this->TargetsFileAndConfigsVec) {
1330     std::ostringstream oss;
1331     oss << "Exists('" << tac.File << "')";
1332     if (!tac.Configs.empty()) {
1333       oss << " And (";
1334       for (size_t j = 0; j < tac.Configs.size(); ++j) {
1335         if (j > 0) {
1336           oss << " Or ";
1337         }
1338         oss << "'$(Configuration)'=='" << tac.Configs[j] << "'";
1339       }
1340       oss << ")";
1341     }
1342
1343     Elem(e1, "Import")
1344       .Attribute("Project", tac.File)
1345       .Attribute("Condition", oss.str());
1346   }
1347 }
1348
1349 void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0)
1350 {
1351   std::vector<std::string> references;
1352   if (cmValue vsWinRTReferences =
1353         this->GeneratorTarget->GetProperty("VS_WINRT_REFERENCES")) {
1354     cmExpandList(*vsWinRTReferences, references);
1355   }
1356
1357   if (this->GlobalGenerator->TargetsWindowsPhone() &&
1358       this->GlobalGenerator->GetSystemVersion() == "8.0" &&
1359       references.empty()) {
1360     references.push_back("platform.winmd");
1361   }
1362   if (!references.empty()) {
1363     Elem e1(e0, "ItemGroup");
1364     for (std::string const& ri : references) {
1365       Elem e2(e1, "Reference");
1366       e2.Attribute("Include", ri);
1367       e2.Element("IsWinMDFile", "true");
1368     }
1369   }
1370 }
1371
1372 // ConfigurationType Application, Utility StaticLibrary DynamicLibrary
1373
1374 void cmVisualStudio10TargetGenerator::WriteProjectConfigurations(Elem& e0)
1375 {
1376   Elem e1(e0, "ItemGroup");
1377   e1.Attribute("Label", "ProjectConfigurations");
1378   for (std::string const& c : this->Configurations) {
1379     Elem e2(e1, "ProjectConfiguration");
1380     e2.Attribute("Include", c + "|" + this->Platform);
1381     e2.Element("Configuration", c);
1382     e2.Element("Platform", this->Platform);
1383   }
1384 }
1385
1386 void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
1387 {
1388   for (std::string const& c : this->Configurations) {
1389     Elem e1(e0, "PropertyGroup");
1390     e1.Attribute("Condition", this->CalcCondition(c));
1391     e1.Attribute("Label", "Configuration");
1392
1393     if (this->ProjectType != VsProjectType::csproj) {
1394       std::string configType;
1395       if (cmValue vsConfigurationType =
1396             this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
1397         configType = cmGeneratorExpression::Evaluate(*vsConfigurationType,
1398                                                      this->LocalGenerator, c);
1399       } else {
1400         switch (this->GeneratorTarget->GetType()) {
1401           case cmStateEnums::SHARED_LIBRARY:
1402           case cmStateEnums::MODULE_LIBRARY:
1403             configType = "DynamicLibrary";
1404             break;
1405           case cmStateEnums::OBJECT_LIBRARY:
1406           case cmStateEnums::STATIC_LIBRARY:
1407             configType = "StaticLibrary";
1408             break;
1409           case cmStateEnums::EXECUTABLE:
1410             if (this->NsightTegra &&
1411                 !this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
1412               // Android executables are .so too.
1413               configType = "DynamicLibrary";
1414             } else if (this->Android) {
1415               configType = "DynamicLibrary";
1416             } else {
1417               configType = "Application";
1418             }
1419             break;
1420           case cmStateEnums::UTILITY:
1421           case cmStateEnums::INTERFACE_LIBRARY:
1422           case cmStateEnums::GLOBAL_TARGET:
1423             if (this->NsightTegra) {
1424               // Tegra-Android platform does not understand "Utility".
1425               configType = "StaticLibrary";
1426             } else {
1427               configType = "Utility";
1428             }
1429             break;
1430           case cmStateEnums::UNKNOWN_LIBRARY:
1431             break;
1432         }
1433       }
1434       e1.Element("ConfigurationType", configType);
1435     }
1436
1437     if (this->MSTools) {
1438       if (!this->Managed) {
1439         this->WriteMSToolConfigurationValues(e1, c);
1440       } else {
1441         this->WriteMSToolConfigurationValuesManaged(e1, c);
1442       }
1443     } else if (this->NsightTegra) {
1444       this->WriteNsightTegraConfigurationValues(e1, c);
1445     } else if (this->Android) {
1446       this->WriteAndroidConfigurationValues(e1, c);
1447     }
1448   }
1449 }
1450
1451 void cmVisualStudio10TargetGenerator::WriteCEDebugProjectConfigurationValues(
1452   Elem& e0)
1453 {
1454   if (!this->GlobalGenerator->TargetsWindowsCE()) {
1455     return;
1456   }
1457   cmValue additionalFiles =
1458     this->GeneratorTarget->GetProperty("DEPLOYMENT_ADDITIONAL_FILES");
1459   cmValue remoteDirectory =
1460     this->GeneratorTarget->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY");
1461   if (!(additionalFiles || remoteDirectory)) {
1462     return;
1463   }
1464   for (std::string const& c : this->Configurations) {
1465     Elem e1(e0, "PropertyGroup");
1466     e1.Attribute("Condition", this->CalcCondition(c));
1467
1468     if (remoteDirectory) {
1469       e1.Element("RemoteDirectory", *remoteDirectory);
1470     }
1471     if (additionalFiles) {
1472       e1.Element("CEAdditionalFiles", *additionalFiles);
1473     }
1474   }
1475 }
1476
1477 void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
1478   Elem& e1, std::string const& config)
1479 {
1480   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
1481   cmValue mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
1482   if (mfcFlag) {
1483     std::string const mfcFlagValue =
1484       cmGeneratorExpression::Evaluate(*mfcFlag, this->LocalGenerator, config);
1485
1486     std::string useOfMfcValue = "false";
1487     if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
1488       if (mfcFlagValue == "1") {
1489         useOfMfcValue = "Static";
1490       } else if (mfcFlagValue == "2") {
1491         useOfMfcValue = "Dynamic";
1492       }
1493     }
1494     e1.Element("UseOfMfc", useOfMfcValue);
1495   }
1496
1497   if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY &&
1498        this->ClOptions[config]->UsingUnicode()) ||
1499       this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
1500       this->GlobalGenerator->TargetsWindowsPhone() ||
1501       this->GlobalGenerator->TargetsWindowsStore() ||
1502       this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
1503     e1.Element("CharacterSet", "Unicode");
1504   } else if (this->GeneratorTarget->GetType() <=
1505                cmStateEnums::OBJECT_LIBRARY &&
1506              this->ClOptions[config]->UsingSBCS()) {
1507     e1.Element("CharacterSet", "NotSet");
1508   } else {
1509     e1.Element("CharacterSet", "MultiByte");
1510   }
1511   if (cmValue projectToolsetOverride =
1512         this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
1513     e1.Element("PlatformToolset", *projectToolsetOverride);
1514   } else if (const char* toolset = gg->GetPlatformToolset()) {
1515     e1.Element("PlatformToolset", toolset);
1516   }
1517   if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
1518       this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
1519     e1.Element("WindowsAppContainer", "true");
1520   }
1521   if (this->IPOEnabledConfigurations.count(config) > 0) {
1522     e1.Element("WholeProgramOptimization", "true");
1523   }
1524   if (this->ASanEnabledConfigurations.find(config) !=
1525       this->ASanEnabledConfigurations.end()) {
1526     e1.Element("EnableAsan", "true");
1527   }
1528   if (this->FuzzerEnabledConfigurations.find(config) !=
1529       this->FuzzerEnabledConfigurations.end()) {
1530     e1.Element("EnableFuzzer", "true");
1531   }
1532   {
1533     auto s = this->SpectreMitigation.find(config);
1534     if (s != this->SpectreMitigation.end()) {
1535       e1.Element("SpectreMitigation", s->second);
1536     }
1537   }
1538 }
1539
1540 void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
1541   Elem& e1, std::string const& config)
1542 {
1543   if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
1544     return;
1545   }
1546
1547   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
1548
1549   Options& o = *(this->ClOptions[config]);
1550
1551   if (o.IsDebug()) {
1552     e1.Element("DebugSymbols", "true");
1553     e1.Element("DefineDebug", "true");
1554   }
1555
1556   std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
1557   ConvertToWindowsSlash(outDir);
1558   e1.Element("OutputPath", outDir);
1559
1560   if (o.HasFlag("Platform")) {
1561     e1.Element("PlatformTarget", o.GetFlag("Platform"));
1562     o.RemoveFlag("Platform");
1563   }
1564
1565   if (cmValue projectToolsetOverride =
1566         this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
1567     e1.Element("PlatformToolset", *projectToolsetOverride);
1568   } else if (const char* toolset = gg->GetPlatformToolset()) {
1569     e1.Element("PlatformToolset", toolset);
1570   }
1571
1572   std::string postfixName =
1573     cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
1574   std::string assemblyName = this->GeneratorTarget->GetOutputName(
1575     config, cmStateEnums::RuntimeBinaryArtifact);
1576   if (cmValue postfix = this->GeneratorTarget->GetProperty(postfixName)) {
1577     assemblyName += *postfix;
1578   }
1579   e1.Element("AssemblyName", assemblyName);
1580
1581   if (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType()) {
1582     e1.Element("StartAction", "Program");
1583     e1.Element("StartProgram", outDir + assemblyName + ".exe");
1584   }
1585
1586   OptionsHelper oh(o, e1);
1587   oh.OutputFlagMap();
1588 }
1589
1590 //----------------------------------------------------------------------------
1591 void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
1592   Elem& e1, std::string const&)
1593 {
1594   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
1595   const char* toolset = gg->GetPlatformToolset();
1596   e1.Element("NdkToolchainVersion", toolset ? toolset : "Default");
1597   if (cmValue minApi = this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) {
1598     e1.Element("AndroidMinAPI", "android-" + *minApi);
1599   }
1600   if (cmValue api = this->GeneratorTarget->GetProperty("ANDROID_API")) {
1601     e1.Element("AndroidTargetAPI", "android-" + *api);
1602   }
1603
1604   if (cmValue cpuArch = this->GeneratorTarget->GetProperty("ANDROID_ARCH")) {
1605     e1.Element("AndroidArch", *cpuArch);
1606   }
1607
1608   if (cmValue stlType =
1609         this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
1610     e1.Element("AndroidStlType", *stlType);
1611   }
1612 }
1613
1614 void cmVisualStudio10TargetGenerator::WriteAndroidConfigurationValues(
1615   Elem& e1, std::string const&)
1616 {
1617   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
1618   if (cmValue projectToolsetOverride =
1619         this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
1620     e1.Element("PlatformToolset", *projectToolsetOverride);
1621   } else if (const char* toolset = gg->GetPlatformToolset()) {
1622     e1.Element("PlatformToolset", toolset);
1623   }
1624   if (cmValue stlType =
1625         this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
1626     if (*stlType != "none") {
1627       e1.Element("UseOfStl", *stlType);
1628     }
1629   }
1630   std::string const& apiLevel = gg->GetSystemVersion();
1631   if (!apiLevel.empty()) {
1632     e1.Element("AndroidAPILevel", cmStrCat("android-", apiLevel));
1633   }
1634 }
1635
1636 void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0)
1637 {
1638   this->CSharpCustomCommandNames.clear();
1639
1640   cmSourceFile const* srcCMakeLists =
1641     this->LocalGenerator->CreateVCProjBuildRule();
1642
1643   for (cmGeneratorTarget::AllConfigSource const& si :
1644        this->GeneratorTarget->GetAllConfigSources()) {
1645     if (si.Source == srcCMakeLists) {
1646       // Skip explicit reference to CMakeLists.txt source.
1647       continue;
1648     }
1649     this->WriteCustomCommand(e0, si.Source);
1650   }
1651
1652   // Add CMakeLists.txt file with rule to re-run CMake for user convenience.
1653   if (this->GeneratorTarget->GetType() != cmStateEnums::GLOBAL_TARGET &&
1654       this->GeneratorTarget->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
1655     if (srcCMakeLists) {
1656       // Write directly rather than through WriteCustomCommand because
1657       // we do not want the de-duplication and it has no dependencies.
1658       if (cmCustomCommand const* command = srcCMakeLists->GetCustomCommand()) {
1659         this->WriteCustomRule(e0, srcCMakeLists, *command);
1660       }
1661     }
1662   }
1663 }
1664
1665 void cmVisualStudio10TargetGenerator::WriteCustomCommand(
1666   Elem& e0, cmSourceFile const* sf)
1667 {
1668   if (this->LocalGenerator->GetSourcesVisited(this->GeneratorTarget)
1669         .insert(sf)
1670         .second) {
1671     if (std::vector<cmSourceFile*> const* depends =
1672           this->GeneratorTarget->GetSourceDepends(sf)) {
1673       for (cmSourceFile const* di : *depends) {
1674         this->WriteCustomCommand(e0, di);
1675       }
1676     }
1677     if (cmCustomCommand const* command = sf->GetCustomCommand()) {
1678       // C# projects write their <Target> within WriteCustomRule()
1679       this->WriteCustomRule(e0, sf, *command);
1680     }
1681   }
1682 }
1683
1684 void cmVisualStudio10TargetGenerator::WriteCustomRule(
1685   Elem& e0, cmSourceFile const* source, cmCustomCommand const& command)
1686 {
1687   std::string sourcePath = source->GetFullPath();
1688   // VS 10 will always rebuild a custom command attached to a .rule
1689   // file that doesn't exist so create the file explicitly.
1690   if (source->GetPropertyAsBool("__CMAKE_RULE")) {
1691     if (!cmSystemTools::FileExists(sourcePath)) {
1692       // Make sure the path exists for the file
1693       std::string path = cmSystemTools::GetFilenamePath(sourcePath);
1694       cmSystemTools::MakeDirectory(path);
1695       cmsys::ofstream fout(sourcePath.c_str());
1696       if (fout) {
1697         fout << "# generated from CMake\n";
1698         fout.flush();
1699         fout.close();
1700         // Force given file to have a very old timestamp, thus
1701         // preventing dependent rebuilds.
1702         this->ForceOld(sourcePath);
1703       } else {
1704         std::string error =
1705           cmStrCat("Could not create file: [", sourcePath, "]  ");
1706         cmSystemTools::Error(error + cmSystemTools::GetLastSystemError());
1707       }
1708     }
1709   }
1710   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
1711
1712   std::unique_ptr<Elem> spe1;
1713   std::unique_ptr<Elem> spe2;
1714   if (this->ProjectType != VsProjectType::csproj) {
1715     spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
1716     spe2 = cm::make_unique<Elem>(*spe1, "CustomBuild");
1717     this->WriteSource(*spe2, source);
1718     spe2->SetHasElements();
1719     if (command.GetStdPipesUTF8()) {
1720       this->WriteStdOutEncodingUtf8(*spe2);
1721     }
1722   } else {
1723     Elem e1(e0, "ItemGroup");
1724     Elem e2(e1, "None");
1725     this->WriteSource(e2, source);
1726     e2.SetHasElements();
1727   }
1728   for (std::string const& c : this->Configurations) {
1729     cmCustomCommandGenerator ccg(command, c, lg, true);
1730     std::string comment = lg->ConstructComment(ccg);
1731     comment = cmVS10EscapeComment(comment);
1732     std::string script = lg->ConstructScript(ccg);
1733     bool symbolic = false;
1734     // input files for custom command
1735     std::stringstream additional_inputs;
1736     {
1737       const char* sep = "";
1738       if (this->ProjectType == VsProjectType::csproj) {
1739         // csproj files do not attach the command to a specific file
1740         // so the primary input must be listed explicitly.
1741         additional_inputs << source->GetFullPath();
1742         sep = ";";
1743       }
1744
1745       // Avoid listing an input more than once.
1746       std::set<std::string> unique_inputs;
1747       // The source is either implicit an input or has been added above.
1748       unique_inputs.insert(source->GetFullPath());
1749
1750       for (std::string const& d : ccg.GetDepends()) {
1751         std::string dep;
1752         if (lg->GetRealDependency(d, c, dep)) {
1753           if (!unique_inputs.insert(dep).second) {
1754             // already listed
1755             continue;
1756           }
1757           ConvertToWindowsSlash(dep);
1758           additional_inputs << sep << dep;
1759           sep = ";";
1760           if (!symbolic) {
1761             if (cmSourceFile* sf = this->Makefile->GetSource(
1762                   dep, cmSourceFileLocationKind::Known)) {
1763               symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1764             }
1765           }
1766         }
1767       }
1768       if (this->ProjectType != VsProjectType::csproj) {
1769         additional_inputs << sep << "%(AdditionalInputs)";
1770       }
1771     }
1772     // output files for custom command
1773     std::stringstream outputs;
1774     {
1775       const char* sep = "";
1776       for (std::string const& o : ccg.GetOutputs()) {
1777         std::string out = o;
1778         ConvertToWindowsSlash(out);
1779         outputs << sep << out;
1780         sep = ";";
1781         if (!symbolic) {
1782           if (cmSourceFile* sf = this->Makefile->GetSource(
1783                 o, cmSourceFileLocationKind::Known)) {
1784             symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1785           }
1786         }
1787       }
1788     }
1789     script += lg->FinishConstructScript(this->ProjectType);
1790     if (this->ProjectType == VsProjectType::csproj) {
1791       std::string name = "CustomCommand_" + c + "_" +
1792         cmSystemTools::ComputeStringMD5(sourcePath);
1793       this->WriteCustomRuleCSharp(e0, c, name, script, additional_inputs.str(),
1794                                   outputs.str(), comment, ccg);
1795     } else {
1796       this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(),
1797                                outputs.str(), comment, ccg, symbolic);
1798     }
1799   }
1800 }
1801
1802 void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
1803   Elem& e2, std::string const& config, std::string const& script,
1804   std::string const& additional_inputs, std::string const& outputs,
1805   std::string const& comment, cmCustomCommandGenerator const& ccg,
1806   bool symbolic)
1807 {
1808   const std::string cond = this->CalcCondition(config);
1809   e2.WritePlatformConfigTag("Message", cond, comment);
1810   e2.WritePlatformConfigTag("Command", cond, script);
1811   e2.WritePlatformConfigTag("AdditionalInputs", cond, additional_inputs);
1812   e2.WritePlatformConfigTag("Outputs", cond, outputs);
1813   // Turn off linking of custom command outputs.
1814   e2.WritePlatformConfigTag("LinkObjects", cond, "false");
1815   if (symbolic &&
1816       this->LocalGenerator->GetVersion() >=
1817         cmGlobalVisualStudioGenerator::VSVersion::VS16) {
1818     // VS >= 16.4 warn if outputs are not created, but one of our
1819     // outputs is marked SYMBOLIC and not expected to be created.
1820     e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false");
1821   }
1822
1823   std::string depfile = ccg.GetFullDepfile();
1824   if (!depfile.empty()) {
1825     this->HaveCustomCommandDepfile = true;
1826     std::string internal_depfile = ccg.GetInternalDepfile();
1827     ConvertToWindowsSlash(internal_depfile);
1828     e2.WritePlatformConfigTag("DepFileAdditionalInputsFile", cond,
1829                               internal_depfile);
1830   }
1831 }
1832
1833 void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
1834   Elem& e0, std::string const& config, std::string const& name,
1835   std::string const& script, std::string const& inputs,
1836   std::string const& outputs, std::string const& comment,
1837   cmCustomCommandGenerator const& ccg)
1838 {
1839   if (!ccg.GetFullDepfile().empty()) {
1840     this->Makefile->IssueMessage(
1841       MessageType::FATAL_ERROR,
1842       cmStrCat("CSharp target \"", this->GeneratorTarget->GetName(),
1843                "\" does not support add_custom_command DEPFILE."));
1844   }
1845   this->CSharpCustomCommandNames.insert(name);
1846   Elem e1(e0, "Target");
1847   e1.Attribute("Condition", this->CalcCondition(config));
1848   e1.S << "\n    Name=\"" << name << "\"";
1849   e1.S << "\n    Inputs=\"" << cmVS10EscapeAttr(inputs) << "\"";
1850   e1.S << "\n    Outputs=\"" << cmVS10EscapeAttr(outputs) << "\"";
1851   if (!comment.empty()) {
1852     Elem(e1, "Exec").Attribute("Command", "echo " + comment);
1853   }
1854   Elem(e1, "Exec").Attribute("Command", script);
1855 }
1856
1857 std::string cmVisualStudio10TargetGenerator::ConvertPath(
1858   std::string const& path, bool forceRelative)
1859 {
1860   return forceRelative
1861     ? cmSystemTools::RelativePath(
1862         this->LocalGenerator->GetCurrentBinaryDirectory(), path)
1863     : path;
1864 }
1865
1866 static void ConvertToWindowsSlash(std::string& s)
1867 {
1868   // first convert all of the slashes
1869   for (auto& ch : s) {
1870     if (ch == '/') {
1871       ch = '\\';
1872     }
1873   }
1874 }
1875
1876 void cmVisualStudio10TargetGenerator::WriteGroups()
1877 {
1878   if (this->ProjectType == VsProjectType::csproj) {
1879     return;
1880   }
1881
1882   // collect up group information
1883   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
1884
1885   std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
1886     this->GeneratorTarget->GetAllConfigSources();
1887
1888   std::set<cmSourceGroup const*> groupsUsed;
1889   for (cmGeneratorTarget::AllConfigSource const& si : sources) {
1890     std::string const& source = si.Source->GetFullPath();
1891     cmSourceGroup* sourceGroup =
1892       this->Makefile->FindSourceGroup(source, sourceGroups);
1893     groupsUsed.insert(sourceGroup);
1894   }
1895
1896   if (cmSourceFile const* srcCMakeLists =
1897         this->LocalGenerator->CreateVCProjBuildRule()) {
1898     std::string const& source = srcCMakeLists->GetFullPath();
1899     cmSourceGroup* sourceGroup =
1900       this->Makefile->FindSourceGroup(source, sourceGroups);
1901     groupsUsed.insert(sourceGroup);
1902   }
1903
1904   this->AddMissingSourceGroups(groupsUsed, sourceGroups);
1905
1906   // Write out group file
1907   std::string path = cmStrCat(
1908     this->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->Name,
1909     computeProjectFileExtension(this->GeneratorTarget), ".filters");
1910   cmGeneratedFileStream fout(path);
1911   fout.SetCopyIfDifferent(true);
1912   char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
1913   fout.write(magic, 3);
1914
1915   fout << "<?xml version=\"1.0\" encoding=\""
1916        << this->GlobalGenerator->Encoding() << "\"?>";
1917   {
1918     Elem e0(fout, "Project");
1919     e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion());
1920     e0.Attribute("xmlns",
1921                  "http://schemas.microsoft.com/developer/msbuild/2003");
1922
1923     for (auto const& ti : this->Tools) {
1924       this->WriteGroupSources(e0, ti.first, ti.second, sourceGroups);
1925     }
1926
1927     // Added files are images and the manifest.
1928     if (!this->AddedFiles.empty()) {
1929       Elem e1(e0, "ItemGroup");
1930       e1.SetHasElements();
1931       for (std::string const& oi : this->AddedFiles) {
1932         std::string fileName =
1933           cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(oi));
1934         if (fileName == "wmappmanifest.xml") {
1935           Elem e2(e1, "XML");
1936           e2.Attribute("Include", oi);
1937           e2.Element("Filter", "Resource Files");
1938         } else if (cmSystemTools::GetFilenameExtension(fileName) ==
1939                    ".appxmanifest") {
1940           Elem e2(e1, "AppxManifest");
1941           e2.Attribute("Include", oi);
1942           e2.Element("Filter", "Resource Files");
1943         } else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") {
1944           Elem e2(e1, "None");
1945           e2.Attribute("Include", oi);
1946           e2.Element("Filter", "Resource Files");
1947         } else {
1948           Elem e2(e1, "Image");
1949           e2.Attribute("Include", oi);
1950           e2.Element("Filter", "Resource Files");
1951         }
1952       }
1953     }
1954
1955     if (!this->ResxObjs.empty()) {
1956       Elem e1(e0, "ItemGroup");
1957       for (cmSourceFile const* oi : this->ResxObjs) {
1958         std::string obj = oi->GetFullPath();
1959         ConvertToWindowsSlash(obj);
1960         Elem e2(e1, "EmbeddedResource");
1961         e2.Attribute("Include", obj);
1962         e2.Element("Filter", "Resource Files");
1963       }
1964     }
1965     {
1966       Elem e1(e0, "ItemGroup");
1967       e1.SetHasElements();
1968       std::vector<cmSourceGroup const*> groupsVec(groupsUsed.begin(),
1969                                                   groupsUsed.end());
1970       std::sort(groupsVec.begin(), groupsVec.end(),
1971                 [](cmSourceGroup const* l, cmSourceGroup const* r) {
1972                   return l->GetFullName() < r->GetFullName();
1973                 });
1974       for (cmSourceGroup const* sg : groupsVec) {
1975         std::string const& name = sg->GetFullName();
1976         if (!name.empty()) {
1977           std::string guidName = "SG_Filter_" + name;
1978           std::string guid = this->GlobalGenerator->GetGUID(guidName);
1979           Elem e2(e1, "Filter");
1980           e2.Attribute("Include", name);
1981           e2.Element("UniqueIdentifier", "{" + guid + "}");
1982         }
1983       }
1984
1985       if (!this->ResxObjs.empty() || !this->AddedFiles.empty()) {
1986         std::string guidName = "SG_Filter_Resource Files";
1987         std::string guid = this->GlobalGenerator->GetGUID(guidName);
1988         Elem e2(e1, "Filter");
1989         e2.Attribute("Include", "Resource Files");
1990         e2.Element("UniqueIdentifier", "{" + guid + "}");
1991         e2.Element("Extensions",
1992                    "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;"
1993                    "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms");
1994       }
1995     }
1996   }
1997   fout << '\n';
1998
1999   if (fout.Close()) {
2000     this->GlobalGenerator->FileReplacedDuringGenerate(path);
2001   }
2002 }
2003
2004 // Add to groupsUsed empty source groups that have non-empty children.
2005 void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
2006   std::set<cmSourceGroup const*>& groupsUsed,
2007   const std::vector<cmSourceGroup>& allGroups)
2008 {
2009   for (cmSourceGroup const& current : allGroups) {
2010     std::vector<cmSourceGroup> const& children = current.GetGroupChildren();
2011     if (children.empty()) {
2012       continue; // the group is really empty
2013     }
2014
2015     this->AddMissingSourceGroups(groupsUsed, children);
2016
2017     if (groupsUsed.count(&current) > 0) {
2018       continue; // group has already been added to set
2019     }
2020
2021     // check if it least one of the group's descendants is not empty
2022     // (at least one child must already have been added)
2023     auto child_it = children.begin();
2024     while (child_it != children.end()) {
2025       if (groupsUsed.count(&(*child_it)) > 0) {
2026         break; // found a child that was already added => add current group too
2027       }
2028       child_it++;
2029     }
2030
2031     if (child_it == children.end()) {
2032       continue; // no descendants have source files => ignore this group
2033     }
2034
2035     groupsUsed.insert(&current);
2036   }
2037 }
2038
2039 void cmVisualStudio10TargetGenerator::WriteGroupSources(
2040   Elem& e0, std::string const& name, ToolSources const& sources,
2041   std::vector<cmSourceGroup>& sourceGroups)
2042 {
2043   Elem e1(e0, "ItemGroup");
2044   e1.SetHasElements();
2045   for (ToolSource const& s : sources) {
2046     cmSourceFile const* sf = s.SourceFile;
2047     std::string const& source = sf->GetFullPath();
2048     cmSourceGroup* sourceGroup =
2049       this->Makefile->FindSourceGroup(source, sourceGroups);
2050     std::string const& filter = sourceGroup->GetFullName();
2051     std::string path = this->ConvertPath(source, s.RelativePath);
2052     ConvertToWindowsSlash(path);
2053     Elem e2(e1, name);
2054     e2.Attribute("Include", path);
2055     if (!filter.empty()) {
2056       e2.Element("Filter", filter);
2057     }
2058   }
2059 }
2060
2061 void cmVisualStudio10TargetGenerator::WriteHeaderSource(
2062   Elem& e1, cmSourceFile const* sf, ConfigToSettings const& toolSettings)
2063 {
2064   std::string const& fileName = sf->GetFullPath();
2065   Elem e2(e1, "ClInclude");
2066   this->WriteSource(e2, sf);
2067   if (this->IsResxHeader(fileName)) {
2068     e2.Element("FileType", "CppForm");
2069   } else if (this->IsXamlHeader(fileName)) {
2070     e2.Element("DependentUpon",
2071                fileName.substr(0, fileName.find_last_of(".")));
2072   }
2073   this->FinishWritingSource(e2, toolSettings);
2074 }
2075
2076 void cmVisualStudio10TargetGenerator::ParseSettingsProperty(
2077   const std::string& settingsPropertyValue, ConfigToSettings& toolSettings)
2078 {
2079   if (!settingsPropertyValue.empty()) {
2080     cmGeneratorExpression ge;
2081
2082     std::unique_ptr<cmCompiledGeneratorExpression> cge =
2083       ge.Parse(settingsPropertyValue);
2084
2085     for (const std::string& config : this->Configurations) {
2086       std::string evaluated = cge->Evaluate(this->LocalGenerator, config);
2087
2088       std::vector<std::string> settings = cmExpandedList(evaluated);
2089       for (const std::string& setting : settings) {
2090         const std::string::size_type assignment = setting.find('=');
2091         if (assignment != std::string::npos) {
2092           const std::string propName = setting.substr(0, assignment);
2093           const std::string propValue = setting.substr(assignment + 1);
2094
2095           if (!propValue.empty()) {
2096             toolSettings[config][propName] = propValue;
2097           }
2098         }
2099       }
2100     }
2101   }
2102 }
2103
2104 bool cmVisualStudio10TargetGenerator::PropertyIsSameInAllConfigs(
2105   const ConfigToSettings& toolSettings, const std::string& propName)
2106 {
2107   std::string firstPropValue = "";
2108   for (const auto& configToSettings : toolSettings) {
2109     const std::unordered_map<std::string, std::string>& settings =
2110       configToSettings.second;
2111
2112     if (firstPropValue.empty()) {
2113       if (settings.find(propName) != settings.end()) {
2114         firstPropValue = settings.find(propName)->second;
2115       }
2116     }
2117
2118     if (settings.find(propName) == settings.end()) {
2119       return false;
2120     }
2121
2122     if (settings.find(propName)->second != firstPropValue) {
2123       return false;
2124     }
2125   }
2126
2127   return true;
2128 }
2129
2130 void cmVisualStudio10TargetGenerator::WriteExtraSource(
2131   Elem& e1, cmSourceFile const* sf, ConfigToSettings& toolSettings)
2132 {
2133   bool toolHasSettings = false;
2134   const char* tool = "None";
2135   std::string settingsGenerator;
2136   std::string settingsLastGenOutput;
2137   std::string sourceLink;
2138   std::string subType;
2139   std::string copyToOutDir;
2140   std::string includeInVsix;
2141   std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
2142
2143   if (this->ProjectType == VsProjectType::csproj && !this->InSourceBuild) {
2144     toolHasSettings = true;
2145   }
2146   if (ext == "hlsl") {
2147     tool = "FXCompile";
2148     // Figure out the type of shader compiler to use.
2149     if (cmValue st = sf->GetProperty("VS_SHADER_TYPE")) {
2150       for (const std::string& config : this->Configurations) {
2151         toolSettings[config]["ShaderType"] = *st;
2152       }
2153     }
2154     // Figure out which entry point to use if any
2155     if (cmValue se = sf->GetProperty("VS_SHADER_ENTRYPOINT")) {
2156       for (const std::string& config : this->Configurations) {
2157         toolSettings[config]["EntryPointName"] = *se;
2158       }
2159     }
2160     // Figure out which shader model to use if any
2161     if (cmValue sm = sf->GetProperty("VS_SHADER_MODEL")) {
2162       for (const std::string& config : this->Configurations) {
2163         toolSettings[config]["ShaderModel"] = *sm;
2164       }
2165     }
2166     // Figure out which output header file to use if any
2167     if (cmValue ohf = sf->GetProperty("VS_SHADER_OUTPUT_HEADER_FILE")) {
2168       for (const std::string& config : this->Configurations) {
2169         toolSettings[config]["HeaderFileOutput"] = *ohf;
2170       }
2171     }
2172     // Figure out which variable name to use if any
2173     if (cmValue vn = sf->GetProperty("VS_SHADER_VARIABLE_NAME")) {
2174       for (const std::string& config : this->Configurations) {
2175         toolSettings[config]["VariableName"] = *vn;
2176       }
2177     }
2178     // Figure out if there's any additional flags to use
2179     if (cmValue saf = sf->GetProperty("VS_SHADER_FLAGS")) {
2180       cmGeneratorExpression ge;
2181       std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*saf);
2182
2183       for (const std::string& config : this->Configurations) {
2184         std::string evaluated = cge->Evaluate(this->LocalGenerator, config);
2185
2186         if (!evaluated.empty()) {
2187           toolSettings[config]["AdditionalOptions"] = evaluated;
2188         }
2189       }
2190     }
2191     // Figure out if debug information should be generated
2192     if (cmValue sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) {
2193       cmGeneratorExpression ge;
2194       std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*sed);
2195
2196       for (const std::string& config : this->Configurations) {
2197         std::string evaluated = cge->Evaluate(this->LocalGenerator, config);
2198
2199         if (!evaluated.empty()) {
2200           toolSettings[config]["EnableDebuggingInformation"] =
2201             cmIsOn(evaluated) ? "true" : "false";
2202         }
2203       }
2204     }
2205     // Figure out if optimizations should be disabled
2206     if (cmValue sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) {
2207       cmGeneratorExpression ge;
2208       std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*sdo);
2209
2210       for (const std::string& config : this->Configurations) {
2211         std::string evaluated = cge->Evaluate(this->LocalGenerator, config);
2212
2213         if (!evaluated.empty()) {
2214           toolSettings[config]["DisableOptimizations"] =
2215             cmIsOn(evaluated) ? "true" : "false";
2216         }
2217       }
2218     }
2219     if (cmValue sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) {
2220       for (const std::string& config : this->Configurations) {
2221         toolSettings[config]["ObjectFileOutput"] = *sofn;
2222       }
2223     }
2224   } else if (ext == "jpg" || ext == "png") {
2225     tool = "Image";
2226   } else if (ext == "resw") {
2227     tool = "PRIResource";
2228   } else if (ext == "xml") {
2229     tool = "XML";
2230   } else if (ext == "natvis") {
2231     tool = "Natvis";
2232   } else if (ext == "settings") {
2233     settingsLastGenOutput =
2234       cmsys::SystemTools::GetFilenameName(sf->GetFullPath());
2235     std::size_t pos = settingsLastGenOutput.find(".settings");
2236     settingsLastGenOutput.replace(pos, 9, ".Designer.cs");
2237     settingsGenerator = "SettingsSingleFileGenerator";
2238     toolHasSettings = true;
2239   } else if (ext == "vsixmanifest") {
2240     subType = "Designer";
2241   }
2242   if (cmValue c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) {
2243     tool = "Content";
2244     copyToOutDir = *c;
2245     toolHasSettings = true;
2246   }
2247   if (sf->GetPropertyAsBool("VS_INCLUDE_IN_VSIX")) {
2248     includeInVsix = "True";
2249     tool = "Content";
2250     toolHasSettings = true;
2251   }
2252
2253   // Collect VS_CSHARP_* property values (if some are set)
2254   std::map<std::string, std::string> sourceFileTags;
2255   this->GetCSharpSourceProperties(sf, sourceFileTags);
2256
2257   if (this->NsightTegra) {
2258     // Nsight Tegra needs specific file types to check up-to-dateness.
2259     std::string name = cmSystemTools::LowerCase(sf->GetLocation().GetName());
2260     if (name == "androidmanifest.xml" || name == "build.xml" ||
2261         name == "proguard.cfg" || name == "proguard-project.txt" ||
2262         ext == "properties") {
2263       tool = "AndroidBuild";
2264     } else if (ext == "java") {
2265       tool = "JCompile";
2266     } else if (ext == "asm" || ext == "s") {
2267       tool = "ClCompile";
2268     }
2269   }
2270
2271   cmValue toolOverride = sf->GetProperty("VS_TOOL_OVERRIDE");
2272   if (cmNonempty(toolOverride)) {
2273     tool = toolOverride->c_str();
2274   }
2275
2276   std::string deployContent;
2277   std::string deployLocation;
2278   if (this->GlobalGenerator->TargetsWindowsPhone() ||
2279       this->GlobalGenerator->TargetsWindowsStore()) {
2280     cmValue content = sf->GetProperty("VS_DEPLOYMENT_CONTENT");
2281     if (cmNonempty(content)) {
2282       toolHasSettings = true;
2283       deployContent = *content;
2284
2285       cmValue location = sf->GetProperty("VS_DEPLOYMENT_LOCATION");
2286       if (cmNonempty(location)) {
2287         deployLocation = *location;
2288       }
2289     }
2290   }
2291
2292   if (ParsedToolTargetSettings.find(tool) == ParsedToolTargetSettings.end()) {
2293     cmValue toolTargetProperty = this->GeneratorTarget->Target->GetProperty(
2294       "VS_SOURCE_SETTINGS_" + std::string(tool));
2295     ConfigToSettings toolTargetSettings;
2296     if (toolTargetProperty) {
2297       ParseSettingsProperty(*toolTargetProperty, toolTargetSettings);
2298     }
2299
2300     ParsedToolTargetSettings[tool] = toolTargetSettings;
2301   }
2302
2303   for (const auto& configToSetting : ParsedToolTargetSettings[tool]) {
2304     for (const auto& setting : configToSetting.second) {
2305       toolSettings[configToSetting.first][setting.first] = setting.second;
2306     }
2307   }
2308
2309   if (!toolSettings.empty()) {
2310     toolHasSettings = true;
2311   }
2312
2313   Elem e2(e1, tool);
2314   this->WriteSource(e2, sf);
2315   if (toolHasSettings) {
2316     e2.SetHasElements();
2317
2318     this->FinishWritingSource(e2, toolSettings);
2319
2320     if (!deployContent.empty()) {
2321       cmGeneratorExpression ge;
2322       std::unique_ptr<cmCompiledGeneratorExpression> cge =
2323         ge.Parse(deployContent);
2324       // Deployment location cannot be set on a configuration basis
2325       if (!deployLocation.empty()) {
2326         e2.Element("Link", deployLocation + "\\%(FileName)%(Extension)");
2327       }
2328       for (size_t i = 0; i != this->Configurations.size(); ++i) {
2329         if (cge->Evaluate(this->LocalGenerator, this->Configurations[i]) ==
2330             "1") {
2331           e2.WritePlatformConfigTag("DeploymentContent",
2332                                     "'$(Configuration)|$(Platform)'=='" +
2333                                       this->Configurations[i] + "|" +
2334                                       this->Platform + "'",
2335                                     "true");
2336         } else {
2337           e2.WritePlatformConfigTag("ExcludedFromBuild",
2338                                     "'$(Configuration)|$(Platform)'=='" +
2339                                       this->Configurations[i] + "|" +
2340                                       this->Platform + "'",
2341                                     "true");
2342         }
2343       }
2344     }
2345
2346     if (!settingsGenerator.empty()) {
2347       e2.Element("Generator", settingsGenerator);
2348     }
2349     if (!settingsLastGenOutput.empty()) {
2350       e2.Element("LastGenOutput", settingsLastGenOutput);
2351     }
2352     if (!subType.empty()) {
2353       e2.Element("SubType", subType);
2354     }
2355     if (!copyToOutDir.empty()) {
2356       e2.Element("CopyToOutputDirectory", copyToOutDir);
2357     }
2358     if (!includeInVsix.empty()) {
2359       e2.Element("IncludeInVSIX", includeInVsix);
2360     }
2361     // write source file specific tags
2362     this->WriteCSharpSourceProperties(e2, sourceFileTags);
2363   }
2364 }
2365
2366 void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
2367                                                   cmSourceFile const* sf)
2368 {
2369   // Visual Studio tools append relative paths to the current dir, as in:
2370   //
2371   //  c:\path\to\current\dir\..\..\..\relative\path\to\source.c
2372   //
2373   // and fail if this exceeds the maximum allowed path length.  Our path
2374   // conversion uses full paths when possible to allow deeper trees.
2375   // However, CUDA 8.0 msbuild rules fail on absolute paths so for CUDA
2376   // we must use relative paths.
2377   bool forceRelative = sf->GetLanguage() == "CUDA";
2378   std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
2379   ConvertToWindowsSlash(sourceFile);
2380   e2.Attribute("Include", sourceFile);
2381
2382   if (this->ProjectType == VsProjectType::csproj && !this->InSourceBuild) {
2383     // For out of source projects we have to provide a link (if not specified
2384     // via property) for every source file (besides .cs files) otherwise they
2385     // will not be visible in VS at all.
2386     // First we check if the file is in a source group, then we check if the
2387     // file path is relative to current source- or binary-dir, otherwise it is
2388     // added with the plain filename without any path. This means the file will
2389     // show up at root-level of the csproj (where CMakeLists.txt etc. are).
2390     std::string link = this->GetCSharpSourceLink(sf);
2391     if (link.empty())
2392       link = cmsys::SystemTools::GetFilenameName(sf->GetFullPath());
2393     e2.Element("Link", link);
2394   }
2395
2396   ToolSource toolSource = { sf, forceRelative };
2397   this->Tools[e2.Tag].push_back(toolSource);
2398 }
2399
2400 void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
2401 {
2402   if (this->GeneratorTarget->GetType() == cmStateEnums::GLOBAL_TARGET) {
2403     return;
2404   }
2405
2406   const bool haveUnityBuild =
2407     this->GeneratorTarget->GetPropertyAsBool("UNITY_BUILD");
2408
2409   if (haveUnityBuild && this->GlobalGenerator->GetSupportsUnityBuilds()) {
2410     Elem e1(e0, "PropertyGroup");
2411     e1.Element("EnableUnitySupport", "true");
2412   }
2413
2414   Elem e1(e0, "ItemGroup");
2415   e1.SetHasElements();
2416
2417   std::vector<size_t> all_configs;
2418   for (size_t ci = 0; ci < this->Configurations.size(); ++ci) {
2419     all_configs.push_back(ci);
2420   }
2421
2422   std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
2423     this->GeneratorTarget->GetAllConfigSources();
2424
2425   cmSourceFile const* srcCMakeLists =
2426     this->LocalGenerator->CreateVCProjBuildRule();
2427
2428   for (cmGeneratorTarget::AllConfigSource const& si : sources) {
2429     if (si.Source == srcCMakeLists) {
2430       // Skip explicit reference to CMakeLists.txt source.
2431       continue;
2432     }
2433
2434     ConfigToSettings toolSettings;
2435     for (const auto& config : this->Configurations) {
2436       toolSettings[config];
2437     }
2438     if (cmValue p = si.Source->GetProperty("VS_SETTINGS")) {
2439       ParseSettingsProperty(*p, toolSettings);
2440     }
2441
2442     const char* tool = nullptr;
2443     switch (si.Kind) {
2444       case cmGeneratorTarget::SourceKindAppManifest:
2445         tool = "AppxManifest";
2446         break;
2447       case cmGeneratorTarget::SourceKindCertificate:
2448         tool = "None";
2449         break;
2450       case cmGeneratorTarget::SourceKindCustomCommand:
2451         // Handled elsewhere.
2452         break;
2453       case cmGeneratorTarget::SourceKindExternalObject:
2454         tool = "Object";
2455         if (this->LocalGenerator->GetVersion() <
2456             cmGlobalVisualStudioGenerator::VSVersion::VS11) {
2457           // For VS == 10 we cannot use LinkObjects to avoid linking custom
2458           // command outputs.  If an object file is generated in this target,
2459           // then vs10 will use it in the build, and we have to list it as
2460           // None instead of Object.
2461           std::vector<cmSourceFile*> const* d =
2462             this->GeneratorTarget->GetSourceDepends(si.Source);
2463           if (d && !d->empty()) {
2464             tool = "None";
2465           }
2466         }
2467         break;
2468       case cmGeneratorTarget::SourceKindExtra:
2469         this->WriteExtraSource(e1, si.Source, toolSettings);
2470         break;
2471       case cmGeneratorTarget::SourceKindHeader:
2472         this->WriteHeaderSource(e1, si.Source, toolSettings);
2473         break;
2474       case cmGeneratorTarget::SourceKindIDL:
2475         tool = "Midl";
2476         break;
2477       case cmGeneratorTarget::SourceKindManifest:
2478         // Handled elsewhere.
2479         break;
2480       case cmGeneratorTarget::SourceKindModuleDefinition:
2481         tool = "None";
2482         break;
2483       case cmGeneratorTarget::SourceKindUnityBatched:
2484       case cmGeneratorTarget::SourceKindObjectSource: {
2485         const std::string& lang = si.Source->GetLanguage();
2486         if (lang == "C" || lang == "CXX") {
2487           tool = "ClCompile";
2488         } else if (lang == "ASM_MASM" &&
2489                    this->GlobalGenerator->IsMasmEnabled()) {
2490           tool = "MASM";
2491         } else if (lang == "ASM_NASM" &&
2492                    this->GlobalGenerator->IsNasmEnabled()) {
2493           tool = "NASM";
2494         } else if (lang == "RC") {
2495           tool = "ResourceCompile";
2496         } else if (lang == "CSharp") {
2497           tool = "Compile";
2498         } else if (lang == "CUDA" && this->GlobalGenerator->IsCudaEnabled()) {
2499           tool = "CudaCompile";
2500         } else {
2501           tool = "None";
2502         }
2503       } break;
2504       case cmGeneratorTarget::SourceKindResx:
2505         this->ResxObjs.push_back(si.Source);
2506         break;
2507       case cmGeneratorTarget::SourceKindXaml:
2508         this->XamlObjs.push_back(si.Source);
2509         break;
2510     }
2511
2512     if (tool) {
2513       // Compute set of configurations to exclude, if any.
2514       std::vector<size_t> const& include_configs = si.Configs;
2515       std::vector<size_t> exclude_configs;
2516       std::set_difference(all_configs.begin(), all_configs.end(),
2517                           include_configs.begin(), include_configs.end(),
2518                           std::back_inserter(exclude_configs));
2519
2520       Elem e2(e1, tool);
2521       bool isCSharp = (si.Source->GetLanguage() == "CSharp");
2522       if (isCSharp && exclude_configs.size() > 0) {
2523         std::stringstream conditions;
2524         bool firstConditionSet{ false };
2525         for (const auto& ci : include_configs) {
2526           if (firstConditionSet) {
2527             conditions << " Or ";
2528           }
2529           conditions << "('$(Configuration)|$(Platform)'=='" +
2530               this->Configurations[ci] + "|" + this->Platform + "')";
2531           firstConditionSet = true;
2532         }
2533         e2.Attribute("Condition", conditions.str());
2534       }
2535       this->WriteSource(e2, si.Source);
2536
2537       bool useNativeUnityBuild = false;
2538       if (haveUnityBuild && this->GlobalGenerator->GetSupportsUnityBuilds()) {
2539         // Magic value taken from cmGlobalVisualStudioVersionedGenerator.cxx
2540         static const std::string vs15 = "141";
2541         std::string toolset =
2542           this->GlobalGenerator->GetPlatformToolsetString();
2543         cmSystemTools::ReplaceString(toolset, "v", "");
2544
2545         if (toolset.empty() ||
2546             cmSystemTools::VersionCompareGreaterEq(toolset, vs15)) {
2547           useNativeUnityBuild = true;
2548         }
2549       }
2550
2551       if (haveUnityBuild && strcmp(tool, "ClCompile") == 0 &&
2552           si.Source->GetProperty("UNITY_SOURCE_FILE")) {
2553         if (useNativeUnityBuild) {
2554           e2.Attribute(
2555             "IncludeInUnityFile",
2556             si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")
2557               ? "false"
2558               : "true");
2559           e2.Attribute("CustomUnityFile", "true");
2560
2561           std::string unityDir = cmSystemTools::GetFilenamePath(
2562             *si.Source->GetProperty("UNITY_SOURCE_FILE"));
2563           e2.Attribute("UnityFilesDirectory", unityDir);
2564         } else {
2565           // Visual Studio versions prior to 2017 15.8 do not know about unity
2566           // builds, thus we exclude the files already part of unity sources.
2567           if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) {
2568             exclude_configs = all_configs;
2569           }
2570         }
2571       }
2572
2573       if (si.Kind == cmGeneratorTarget::SourceKindObjectSource ||
2574           si.Kind == cmGeneratorTarget::SourceKindUnityBatched) {
2575         this->OutputSourceSpecificFlags(e2, si.Source);
2576       }
2577       if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
2578         e2.Element("PrecompiledHeader", "NotUsing");
2579       }
2580       if (!isCSharp && !exclude_configs.empty()) {
2581         this->WriteExcludeFromBuild(e2, exclude_configs);
2582       }
2583
2584       this->FinishWritingSource(e2, toolSettings);
2585     }
2586   }
2587
2588   if (this->IsMissingFiles) {
2589     this->WriteMissingFiles(e1);
2590   }
2591 }
2592
2593 void cmVisualStudio10TargetGenerator::FinishWritingSource(
2594   Elem& e2, ConfigToSettings const& toolSettings)
2595 {
2596   std::vector<std::string> writtenSettings;
2597   for (const auto& configSettings : toolSettings) {
2598     for (const auto& setting : configSettings.second) {
2599
2600       if (std::find(writtenSettings.begin(), writtenSettings.end(),
2601                     setting.first) != writtenSettings.end()) {
2602         continue;
2603       }
2604
2605       if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) {
2606         e2.Element(setting.first, setting.second);
2607         writtenSettings.push_back(setting.first);
2608       } else {
2609         e2.WritePlatformConfigTag(setting.first,
2610                                   "'$(Configuration)|$(Platform)'=='" +
2611                                     configSettings.first + "|" +
2612                                     this->Platform + "'",
2613                                   setting.second);
2614       }
2615     }
2616   }
2617 }
2618
2619 void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
2620   Elem& e2, cmSourceFile const* source)
2621 {
2622   cmSourceFile const& sf = *source;
2623
2624   std::string objectName;
2625   if (this->GeneratorTarget->HasExplicitObjectName(&sf)) {
2626     objectName = this->GeneratorTarget->GetObjectName(&sf);
2627   }
2628   std::string flags;
2629   bool configDependentFlags = false;
2630   std::string options;
2631   bool configDependentOptions = false;
2632   std::string defines;
2633   bool configDependentDefines = false;
2634   std::string includes;
2635   bool configDependentIncludes = false;
2636   if (cmValue cflags = sf.GetProperty("COMPILE_FLAGS")) {
2637     configDependentFlags =
2638       cmGeneratorExpression::Find(*cflags) != std::string::npos;
2639     flags += *cflags;
2640   }
2641   if (cmValue coptions = sf.GetProperty("COMPILE_OPTIONS")) {
2642     configDependentOptions =
2643       cmGeneratorExpression::Find(*coptions) != std::string::npos;
2644     options += *coptions;
2645   }
2646   if (cmValue cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
2647     configDependentDefines =
2648       cmGeneratorExpression::Find(*cdefs) != std::string::npos;
2649     defines += *cdefs;
2650   }
2651   if (cmValue cincludes = sf.GetProperty("INCLUDE_DIRECTORIES")) {
2652     configDependentIncludes =
2653       cmGeneratorExpression::Find(*cincludes) != std::string::npos;
2654     includes += *cincludes;
2655   }
2656
2657   // Force language if the file extension does not match.
2658   // Note that MSVC treats the upper-case '.C' extension as C and not C++.
2659   std::string const ext = sf.GetExtension();
2660   std::string const extLang = ext == "C"
2661     ? "C"
2662     : this->GlobalGenerator->GetLanguageFromExtension(ext.c_str());
2663   std::string lang = this->LocalGenerator->GetSourceFileLanguage(sf);
2664   const char* compileAs = 0;
2665   if (lang != extLang) {
2666     if (lang == "CXX") {
2667       // force a C++ file type
2668       compileAs = "CompileAsCpp";
2669     } else if (lang == "C") {
2670       // force to c
2671       compileAs = "CompileAsC";
2672     }
2673   }
2674
2675   bool noWinRT = this->TargetCompileAsWinRT && lang == "C";
2676   // for the first time we need a new line if there is something
2677   // produced here.
2678   if (!objectName.empty()) {
2679     if (lang == "CUDA") {
2680       e2.Element("CompileOut", "$(IntDir)/" + objectName);
2681     } else {
2682       e2.Element("ObjectFileName", "$(IntDir)/" + objectName);
2683     }
2684   }
2685
2686   if (lang == "ASM_NASM") {
2687     if (cmValue objectDeps = sf.GetProperty("OBJECT_DEPENDS")) {
2688       std::string dependencies;
2689       std::vector<std::string> depends = cmExpandedList(*objectDeps);
2690       const char* sep = "";
2691       for (std::string& d : depends) {
2692         ConvertToWindowsSlash(d);
2693         dependencies += sep;
2694         dependencies += d;
2695         sep = ";";
2696       }
2697       e2.Element("AdditionalDependencies", dependencies);
2698     }
2699   }
2700
2701   for (std::string const& config : this->Configurations) {
2702     std::string configUpper = cmSystemTools::UpperCase(config);
2703     std::string configDefines = defines;
2704     std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
2705     if (cmValue ccdefs = sf.GetProperty(defPropName)) {
2706       if (!configDefines.empty()) {
2707         configDefines += ";";
2708       }
2709       configDependentDefines |=
2710         cmGeneratorExpression::Find(*ccdefs) != std::string::npos;
2711       configDefines += *ccdefs;
2712     }
2713
2714     // We have pch state in the following situation:
2715     // 1. We have SKIP_PRECOMPILE_HEADERS == true
2716     // 2. We are creating the pre-compiled header
2717     // 3. We are a different language than the linker language AND pch is
2718     //    enabled.
2719     std::string const& linkLanguage =
2720       this->GeneratorTarget->GetLinkerLanguage(config);
2721     std::string const& pchSource =
2722       this->GeneratorTarget->GetPchSource(config, lang);
2723     const bool skipPCH =
2724       pchSource.empty() || sf.GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS");
2725     const bool makePCH = (sf.GetFullPath() == pchSource);
2726     const bool useSharedPCH = !skipPCH && (lang == linkLanguage);
2727     const bool useDifferentLangPCH = !skipPCH && (lang != linkLanguage);
2728     const bool useNoPCH = skipPCH && (lang != linkLanguage) &&
2729       !this->GeneratorTarget->GetPchHeader(config, linkLanguage).empty();
2730     const bool needsPCHFlags =
2731       (makePCH || useSharedPCH || useDifferentLangPCH || useNoPCH);
2732
2733     // if we have flags or defines for this config then
2734     // use them
2735     if (!flags.empty() || !options.empty() || !configDefines.empty() ||
2736         !includes.empty() || compileAs || noWinRT || !options.empty() ||
2737         needsPCHFlags) {
2738       cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
2739       cmIDEFlagTable const* flagtable = nullptr;
2740       const std::string& srclang = source->GetLanguage();
2741       if (srclang == "C" || srclang == "CXX") {
2742         flagtable = gg->GetClFlagTable();
2743       } else if (srclang == "ASM_MASM" &&
2744                  this->GlobalGenerator->IsMasmEnabled()) {
2745         flagtable = gg->GetMasmFlagTable();
2746       } else if (lang == "ASM_NASM" &&
2747                  this->GlobalGenerator->IsNasmEnabled()) {
2748         flagtable = gg->GetNasmFlagTable();
2749       } else if (srclang == "RC") {
2750         flagtable = gg->GetRcFlagTable();
2751       } else if (srclang == "CSharp") {
2752         flagtable = gg->GetCSharpFlagTable();
2753       }
2754       cmGeneratorExpressionInterpreter genexInterpreter(
2755         this->LocalGenerator, config, this->GeneratorTarget, lang);
2756       cmVS10GeneratorOptions clOptions(
2757         this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
2758         flagtable, this);
2759       if (compileAs) {
2760         clOptions.AddFlag("CompileAs", compileAs);
2761       }
2762       if (noWinRT) {
2763         clOptions.AddFlag("CompileAsWinRT", "false");
2764       }
2765       if (configDependentFlags) {
2766         clOptions.Parse(genexInterpreter.Evaluate(flags, "COMPILE_FLAGS"));
2767       } else {
2768         clOptions.Parse(flags);
2769       }
2770
2771       if (needsPCHFlags) {
2772         // Add precompile headers compile options.
2773         if (makePCH) {
2774           clOptions.AddFlag("PrecompiledHeader", "Create");
2775           std::string pchHeader =
2776             this->GeneratorTarget->GetPchHeader(config, lang);
2777           clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
2778           std::string pchFile =
2779             this->GeneratorTarget->GetPchFile(config, lang);
2780           clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
2781           clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
2782         } else if (useNoPCH) {
2783           clOptions.AddFlag("PrecompiledHeader", "NotUsing");
2784         } else if (useSharedPCH) {
2785           std::string pchHeader =
2786             this->GeneratorTarget->GetPchHeader(config, lang);
2787           clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
2788         } else if (useDifferentLangPCH) {
2789           clOptions.AddFlag("PrecompiledHeader", "Use");
2790           std::string pchHeader =
2791             this->GeneratorTarget->GetPchHeader(config, lang);
2792           clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
2793           std::string pchFile =
2794             this->GeneratorTarget->GetPchFile(config, lang);
2795           clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
2796           clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
2797         }
2798       }
2799
2800       if (!options.empty()) {
2801         std::string expandedOptions;
2802         if (configDependentOptions) {
2803           this->LocalGenerator->AppendCompileOptions(
2804             expandedOptions,
2805             genexInterpreter.Evaluate(options, "COMPILE_OPTIONS"));
2806         } else {
2807           this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
2808         }
2809         clOptions.Parse(expandedOptions);
2810       }
2811       if (clOptions.HasFlag("DisableSpecificWarnings")) {
2812         clOptions.AppendFlag("DisableSpecificWarnings",
2813                              "%(DisableSpecificWarnings)");
2814       }
2815       if (clOptions.HasFlag("ForcedIncludeFiles")) {
2816         clOptions.AppendFlag("ForcedIncludeFiles", "%(ForcedIncludeFiles)");
2817       }
2818       if (configDependentDefines) {
2819         clOptions.AddDefines(
2820           genexInterpreter.Evaluate(configDefines, "COMPILE_DEFINITIONS"));
2821       } else {
2822         clOptions.AddDefines(configDefines);
2823       }
2824       std::vector<std::string> includeList;
2825       if (configDependentIncludes) {
2826         this->LocalGenerator->AppendIncludeDirectories(
2827           includeList,
2828           genexInterpreter.Evaluate(includes, "INCLUDE_DIRECTORIES"), *source);
2829       } else {
2830         this->LocalGenerator->AppendIncludeDirectories(includeList, includes,
2831                                                        *source);
2832       }
2833       clOptions.AddIncludes(includeList);
2834       clOptions.SetConfiguration(config);
2835       OptionsHelper oh(clOptions, e2);
2836       oh.PrependInheritedString("AdditionalOptions");
2837       oh.OutputAdditionalIncludeDirectories(lang);
2838       oh.OutputFlagMap();
2839       oh.OutputPreprocessorDefinitions(lang);
2840     }
2841   }
2842   if (this->IsXamlSource(source->GetFullPath())) {
2843     const std::string& fileName = source->GetFullPath();
2844     e2.Element("DependentUpon",
2845                fileName.substr(0, fileName.find_last_of(".")));
2846   }
2847   if (this->ProjectType == VsProjectType::csproj) {
2848     std::string f = source->GetFullPath();
2849     using CsPropMap = std::map<std::string, std::string>;
2850     CsPropMap sourceFileTags;
2851     this->GetCSharpSourceProperties(&sf, sourceFileTags);
2852     // write source file specific tags
2853     if (!sourceFileTags.empty()) {
2854       this->WriteCSharpSourceProperties(e2, sourceFileTags);
2855     }
2856   }
2857 }
2858
2859 void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
2860   Elem& e2, std::vector<size_t> const& exclude_configs)
2861 {
2862   for (size_t ci : exclude_configs) {
2863     e2.WritePlatformConfigTag("ExcludedFromBuild",
2864                               "'$(Configuration)|$(Platform)'=='" +
2865                                 this->Configurations[ci] + "|" +
2866                                 this->Platform + "'",
2867                               "true");
2868   }
2869 }
2870
2871 void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
2872   Elem& e0)
2873 {
2874   cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
2875   if (ttype > cmStateEnums::INTERFACE_LIBRARY) {
2876     return;
2877   }
2878   if (this->ProjectType == VsProjectType::csproj) {
2879     return;
2880   }
2881
2882   Elem e1(e0, "PropertyGroup");
2883   e1.Element("_ProjectFileVersion", "10.0.20506.1");
2884   for (std::string const& config : this->Configurations) {
2885     const std::string cond = this->CalcCondition(config);
2886
2887     if (ttype >= cmStateEnums::UTILITY) {
2888       e1.WritePlatformConfigTag(
2889         "IntDir", cond, "$(Platform)\\$(Configuration)\\$(ProjectName)\\");
2890     } else {
2891       std::string intermediateDir = cmStrCat(
2892         this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/',
2893         config, '/');
2894       std::string outDir;
2895       std::string targetNameFull;
2896       if (ttype == cmStateEnums::OBJECT_LIBRARY) {
2897         outDir = intermediateDir;
2898         targetNameFull = cmStrCat(this->GeneratorTarget->GetName(), ".lib");
2899       } else {
2900         outDir = this->GeneratorTarget->GetDirectory(config) + "/";
2901         targetNameFull = this->GeneratorTarget->GetFullName(config);
2902       }
2903       ConvertToWindowsSlash(intermediateDir);
2904       ConvertToWindowsSlash(outDir);
2905
2906       e1.WritePlatformConfigTag("OutDir", cond, outDir);
2907
2908       e1.WritePlatformConfigTag("IntDir", cond, intermediateDir);
2909
2910       if (cmValue sdkExecutableDirectories = this->Makefile->GetDefinition(
2911             "CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES")) {
2912         e1.WritePlatformConfigTag("ExecutablePath", cond,
2913                                   *sdkExecutableDirectories);
2914       }
2915
2916       if (cmValue sdkIncludeDirectories = this->Makefile->GetDefinition(
2917             "CMAKE_VS_SDK_INCLUDE_DIRECTORIES")) {
2918         e1.WritePlatformConfigTag("IncludePath", cond, *sdkIncludeDirectories);
2919       }
2920
2921       if (cmValue sdkReferenceDirectories = this->Makefile->GetDefinition(
2922             "CMAKE_VS_SDK_REFERENCE_DIRECTORIES")) {
2923         e1.WritePlatformConfigTag("ReferencePath", cond,
2924                                   *sdkReferenceDirectories);
2925       }
2926
2927       if (cmValue sdkLibraryDirectories = this->Makefile->GetDefinition(
2928             "CMAKE_VS_SDK_LIBRARY_DIRECTORIES")) {
2929         e1.WritePlatformConfigTag("LibraryPath", cond, *sdkLibraryDirectories);
2930       }
2931
2932       if (cmValue sdkLibraryWDirectories = this->Makefile->GetDefinition(
2933             "CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES")) {
2934         e1.WritePlatformConfigTag("LibraryWPath", cond,
2935                                   *sdkLibraryWDirectories);
2936       }
2937
2938       if (cmValue sdkSourceDirectories =
2939             this->Makefile->GetDefinition("CMAKE_VS_SDK_SOURCE_DIRECTORIES")) {
2940         e1.WritePlatformConfigTag("SourcePath", cond, *sdkSourceDirectories);
2941       }
2942
2943       if (cmValue sdkExcludeDirectories = this->Makefile->GetDefinition(
2944             "CMAKE_VS_SDK_EXCLUDE_DIRECTORIES")) {
2945         e1.WritePlatformConfigTag("ExcludePath", cond, *sdkExcludeDirectories);
2946       }
2947
2948       std::string name =
2949         cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
2950       e1.WritePlatformConfigTag("TargetName", cond, name);
2951
2952       std::string ext =
2953         cmSystemTools::GetFilenameLastExtension(targetNameFull);
2954       if (ext.empty()) {
2955         // An empty TargetExt causes a default extension to be used.
2956         // A single "." appears to be treated as an empty extension.
2957         ext = ".";
2958       }
2959       e1.WritePlatformConfigTag("TargetExt", cond, ext);
2960
2961       this->OutputLinkIncremental(e1, config);
2962     }
2963
2964     if (ttype <= cmStateEnums::UTILITY) {
2965       if (cmValue workingDir = this->GeneratorTarget->GetProperty(
2966             "VS_DEBUGGER_WORKING_DIRECTORY")) {
2967         std::string genWorkingDir = cmGeneratorExpression::Evaluate(
2968           *workingDir, this->LocalGenerator, config);
2969         e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond,
2970                                   genWorkingDir);
2971       }
2972
2973       if (cmValue environment =
2974             this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) {
2975         std::string genEnvironment = cmGeneratorExpression::Evaluate(
2976           *environment, this->LocalGenerator, config);
2977         e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond,
2978                                   genEnvironment);
2979       }
2980
2981       if (cmValue debuggerCommand =
2982             this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
2983         std::string genDebuggerCommand = cmGeneratorExpression::Evaluate(
2984           *debuggerCommand, this->LocalGenerator, config);
2985         e1.WritePlatformConfigTag("LocalDebuggerCommand", cond,
2986                                   genDebuggerCommand);
2987       }
2988
2989       if (cmValue commandArguments = this->GeneratorTarget->GetProperty(
2990             "VS_DEBUGGER_COMMAND_ARGUMENTS")) {
2991         std::string genCommandArguments = cmGeneratorExpression::Evaluate(
2992           *commandArguments, this->LocalGenerator, config);
2993         e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond,
2994                                   genCommandArguments);
2995       }
2996     }
2997   }
2998 }
2999
3000 void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
3001   Elem& e1, std::string const& configName)
3002 {
3003   if (!this->MSTools) {
3004     return;
3005   }
3006   if (this->ProjectType == VsProjectType::csproj) {
3007     return;
3008   }
3009   // static libraries and things greater than modules do not need
3010   // to set this option
3011   if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
3012       this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
3013     return;
3014   }
3015   Options& linkOptions = *(this->LinkOptions[configName]);
3016   const std::string cond = this->CalcCondition(configName);
3017
3018   if (this->IPOEnabledConfigurations.count(configName) == 0) {
3019     const char* incremental = linkOptions.GetFlag("LinkIncremental");
3020     e1.WritePlatformConfigTag("LinkIncremental", cond,
3021                               (incremental ? incremental : "true"));
3022   }
3023   linkOptions.RemoveFlag("LinkIncremental");
3024
3025   const char* manifest = linkOptions.GetFlag("GenerateManifest");
3026   e1.WritePlatformConfigTag("GenerateManifest", cond,
3027                             (manifest ? manifest : "true"));
3028   linkOptions.RemoveFlag("GenerateManifest");
3029
3030   // Some link options belong here.  Use them now and remove them so that
3031   // WriteLinkOptions does not use them.
3032   static const std::vector<std::string> flags{ "LinkDelaySign",
3033                                                "LinkKeyFile" };
3034   for (const std::string& flag : flags) {
3035     if (const char* value = linkOptions.GetFlag(flag)) {
3036       e1.WritePlatformConfigTag(flag, cond, value);
3037       linkOptions.RemoveFlag(flag);
3038     }
3039   }
3040 }
3041
3042 std::vector<std::string> cmVisualStudio10TargetGenerator::GetIncludes(
3043   std::string const& config, std::string const& lang) const
3044 {
3045   std::vector<std::string> includes;
3046   this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
3047                                               lang, config);
3048   for (std::string& i : includes) {
3049     ConvertToWindowsSlash(i);
3050   }
3051   return includes;
3052 }
3053
3054 bool cmVisualStudio10TargetGenerator::ComputeClOptions()
3055 {
3056   for (std::string const& c : this->Configurations) {
3057     if (!this->ComputeClOptions(c)) {
3058       return false;
3059     }
3060   }
3061   return true;
3062 }
3063
3064 bool cmVisualStudio10TargetGenerator::ComputeClOptions(
3065   std::string const& configName)
3066 {
3067   // much of this was copied from here:
3068   // copied from cmLocalVisualStudio7Generator.cxx 805
3069   // TODO: Integrate code below with cmLocalVisualStudio7Generator.
3070
3071   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
3072   std::unique_ptr<Options> pOptions;
3073   switch (this->ProjectType) {
3074     case VsProjectType::vcxproj:
3075       pOptions = cm::make_unique<Options>(
3076         this->LocalGenerator, Options::Compiler, gg->GetClFlagTable());
3077       break;
3078     case VsProjectType::csproj:
3079       pOptions =
3080         cm::make_unique<Options>(this->LocalGenerator, Options::CSharpCompiler,
3081                                  gg->GetCSharpFlagTable());
3082       break;
3083     default:
3084       break;
3085   }
3086   Options& clOptions = *pOptions;
3087
3088   std::string flags;
3089   const std::string& linkLanguage =
3090     this->GeneratorTarget->GetLinkerLanguage(configName);
3091   if (linkLanguage.empty()) {
3092     cmSystemTools::Error(
3093       "CMake can not determine linker language for target: " + this->Name);
3094     return false;
3095   }
3096
3097   // Choose a language whose flags to use for ClCompile.
3098   static const char* clLangs[] = { "CXX", "C", "Fortran" };
3099   std::string langForClCompile;
3100   if (this->ProjectType == VsProjectType::csproj) {
3101     langForClCompile = "CSharp";
3102   } else if (cm::contains(clLangs, linkLanguage)) {
3103     langForClCompile = linkLanguage;
3104   } else {
3105     std::set<std::string> languages;
3106     this->GeneratorTarget->GetLanguages(languages, configName);
3107     for (const char* l : clLangs) {
3108       if (languages.count(l)) {
3109         langForClCompile = l;
3110         break;
3111       }
3112     }
3113   }
3114   this->LangForClCompile = langForClCompile;
3115   if (!langForClCompile.empty()) {
3116     this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
3117                                            cmBuildStep::Compile,
3118                                            langForClCompile, configName);
3119     this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
3120                                             langForClCompile, configName);
3121   }
3122
3123   // Put the IPO enabled configurations into a set.
3124   if (this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName)) {
3125     this->IPOEnabledConfigurations.insert(configName);
3126   }
3127
3128   // Check if ASan is enabled.
3129   if (flags.find("/fsanitize=address") != std::string::npos ||
3130       flags.find("-fsanitize=address") != std::string::npos) {
3131     this->ASanEnabledConfigurations.insert(configName);
3132   }
3133
3134   // Check if (lib)Fuzzer is enabled.
3135   if (flags.find("/fsanitize=fuzzer") != std::string::npos ||
3136       flags.find("-fsanitize=fuzzer") != std::string::npos) {
3137     this->FuzzerEnabledConfigurations.insert(configName);
3138   }
3139
3140   // Precompile Headers
3141   std::string pchHeader =
3142     this->GeneratorTarget->GetPchHeader(configName, linkLanguage);
3143   if (this->MSTools && VsProjectType::vcxproj == this->ProjectType &&
3144       pchHeader.empty()) {
3145     clOptions.AddFlag("PrecompiledHeader", "NotUsing");
3146   } else if (this->MSTools && VsProjectType::vcxproj == this->ProjectType &&
3147              !pchHeader.empty()) {
3148     clOptions.AddFlag("PrecompiledHeader", "Use");
3149     clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
3150     std::string pchFile =
3151       this->GeneratorTarget->GetPchFile(configName, linkLanguage);
3152     clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
3153   }
3154
3155   // Get preprocessor definitions for this directory.
3156   std::string defineFlags = this->Makefile->GetDefineFlags();
3157   if (this->MSTools) {
3158     if (this->ProjectType == VsProjectType::vcxproj) {
3159       clOptions.FixExceptionHandlingDefault();
3160       if (this->GlobalGenerator->GetVersion() >=
3161           cmGlobalVisualStudioGenerator::VSVersion::VS15) {
3162         // Toolsets that come with VS 2017 may now enable UseFullPaths
3163         // by default and there is no negative /FC option that projects
3164         // can use to switch it back.  Older toolsets disable this by
3165         // default anyway so this will not hurt them.  If the project
3166         // is using an explicit /FC option then parsing flags will
3167         // replace this setting with "true" below.
3168         clOptions.AddFlag("UseFullPaths", "false");
3169       }
3170       clOptions.AddFlag("AssemblerListingLocation", "$(IntDir)");
3171     }
3172   }
3173
3174   // check for managed C++ assembly compiler flag. This overrides any
3175   // /clr* compiler flags which may be defined in the flags variable(s).
3176   if (this->ProjectType != VsProjectType::csproj) {
3177     // Warn if /clr was added manually. This should not be done
3178     // anymore, because cmGeneratorTarget may not be aware that the
3179     // target uses C++/CLI.
3180     if (flags.find("/clr") != std::string::npos ||
3181         flags.find("-clr") != std::string::npos ||
3182         defineFlags.find("/clr") != std::string::npos ||
3183         defineFlags.find("-clr") != std::string::npos) {
3184       if (configName == this->Configurations[0]) {
3185         std::string message = "For the target \"" +
3186           this->GeneratorTarget->GetName() +
3187           "\" the /clr compiler flag was added manually. " +
3188           "Set usage of C++/CLI by setting COMMON_LANGUAGE_RUNTIME "
3189           "target property.";
3190         this->Makefile->IssueMessage(MessageType::WARNING, message);
3191       }
3192     }
3193     if (cmValue clr =
3194           this->GeneratorTarget->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
3195       std::string clrString = *clr;
3196       if (!clrString.empty()) {
3197         clrString = ":" + clrString;
3198       }
3199       flags += " /clr" + clrString;
3200     }
3201   }
3202
3203   // Get includes for this target
3204   if (!this->LangForClCompile.empty()) {
3205     auto includeList = this->GetIncludes(configName, this->LangForClCompile);
3206
3207     auto sysIncludeFlag = this->Makefile->GetDefinition(
3208       cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", this->LangForClCompile));
3209
3210     if (sysIncludeFlag) {
3211       bool gotOneSys = false;
3212       for (auto i : includeList) {
3213         cmSystemTools::ConvertToUnixSlashes(i);
3214         if (this->GeneratorTarget->IsSystemIncludeDirectory(
3215               i, configName, this->LangForClCompile)) {
3216           auto flag = cmTrimWhitespace(*sysIncludeFlag);
3217           if (this->MSTools) {
3218             cmSystemTools::ReplaceString(flag, "-external:I", "/external:I");
3219           }
3220           clOptions.AppendFlagString("AdditionalOptions",
3221                                      cmStrCat(flag, " \"", i, '"'));
3222           gotOneSys = true;
3223         } else {
3224           clOptions.AddInclude(i);
3225         }
3226       }
3227
3228       if (gotOneSys) {
3229         if (auto sysIncludeFlagWarning = this->Makefile->GetDefinition(
3230               cmStrCat("_CMAKE_INCLUDE_SYSTEM_FLAG_", this->LangForClCompile,
3231                        "_WARNING"))) {
3232           flags = cmStrCat(flags, ' ', *sysIncludeFlagWarning);
3233         }
3234       }
3235     } else {
3236       clOptions.AddIncludes(includeList);
3237     }
3238   }
3239
3240   clOptions.Parse(flags);
3241   clOptions.Parse(defineFlags);
3242   std::vector<std::string> targetDefines;
3243   switch (this->ProjectType) {
3244     case VsProjectType::vcxproj:
3245       if (!langForClCompile.empty()) {
3246         this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
3247                                                      langForClCompile);
3248       }
3249       break;
3250     case VsProjectType::csproj:
3251       this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
3252                                                    "CSharp");
3253       cm::erase_if(targetDefines, [](std::string const& def) {
3254         return def.find('=') != std::string::npos;
3255       });
3256       break;
3257     default:
3258       break;
3259   }
3260   clOptions.AddDefines(targetDefines);
3261
3262   if (this->ProjectType == VsProjectType::csproj) {
3263     clOptions.AppendFlag("DefineConstants", targetDefines);
3264   }
3265
3266   if (this->MSTools) {
3267     clOptions.SetVerboseMakefile(
3268       this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
3269   }
3270
3271   // Add C-specific flags expressible in a ClCompile meant for C++.
3272   if (langForClCompile == "CXX") {
3273     std::set<std::string> languages;
3274     this->GeneratorTarget->GetLanguages(languages, configName);
3275     if (languages.count("C")) {
3276       std::string flagsC;
3277       this->LocalGenerator->AddCompileOptions(flagsC, this->GeneratorTarget,
3278                                               "C", configName);
3279       Options optC(this->LocalGenerator, Options::Compiler,
3280                    gg->GetClFlagTable());
3281       optC.Parse(flagsC);
3282       if (const char* stdC = optC.GetFlag("LanguageStandard_C")) {
3283         clOptions.AddFlag("LanguageStandard_C", stdC);
3284       }
3285     }
3286   }
3287
3288   // Add a definition for the configuration name.
3289   std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
3290   clOptions.AddDefine(configDefine);
3291   if (const std::string* exportMacro =
3292         this->GeneratorTarget->GetExportMacro()) {
3293     clOptions.AddDefine(*exportMacro);
3294   }
3295
3296   if (this->MSTools) {
3297     // If we have the VS_WINRT_COMPONENT set then force Compile as WinRT
3298     if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
3299       clOptions.AddFlag("CompileAsWinRT", "true");
3300       // For WinRT components, add the _WINRT_DLL define to produce a lib
3301       if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
3302           this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
3303         clOptions.AddDefine("_WINRT_DLL");
3304       }
3305     } else if (this->GlobalGenerator->TargetsWindowsStore() ||
3306                this->GlobalGenerator->TargetsWindowsPhone() ||
3307                this->Makefile->IsOn("CMAKE_VS_WINRT_BY_DEFAULT")) {
3308       if (!clOptions.IsWinRt()) {
3309         clOptions.AddFlag("CompileAsWinRT", "false");
3310       }
3311     }
3312     if (const char* winRT = clOptions.GetFlag("CompileAsWinRT")) {
3313       if (cmIsOn(winRT)) {
3314         this->TargetCompileAsWinRT = true;
3315       }
3316     }
3317   }
3318
3319   if (this->ProjectType != VsProjectType::csproj && clOptions.IsManaged()) {
3320     this->Managed = true;
3321     std::string managedType = clOptions.GetFlag("CompileAsManaged");
3322     if (managedType == "Safe" || managedType == "Pure") {
3323       // force empty calling convention if safe clr is used
3324       clOptions.AddFlag("CallingConvention", "");
3325     }
3326     // The default values of these flags are incompatible to
3327     // managed assemblies. We have to force valid values if
3328     // the target is a managed C++ target.
3329     clOptions.AddFlag("ExceptionHandling", "Async");
3330     clOptions.AddFlag("BasicRuntimeChecks", "Default");
3331   }
3332   if (this->ProjectType == VsProjectType::csproj) {
3333     // /nowin32manifest overrides /win32manifest: parameter
3334     if (clOptions.HasFlag("NoWin32Manifest")) {
3335       clOptions.RemoveFlag("ApplicationManifest");
3336     }
3337   }
3338
3339   if (const char* s = clOptions.GetFlag("SpectreMitigation")) {
3340     this->SpectreMitigation[configName] = s;
3341     clOptions.RemoveFlag("SpectreMitigation");
3342   }
3343
3344   // Remove any target-wide -TC or -TP flag added by the project.
3345   // Such flags are unnecessary and break our model of language selection.
3346   if (langForClCompile == "C" || langForClCompile == "CXX") {
3347     clOptions.RemoveFlag("CompileAs");
3348   }
3349
3350   this->ClOptions[configName] = std::move(pOptions);
3351   return true;
3352 }
3353
3354 void cmVisualStudio10TargetGenerator::WriteClOptions(
3355   Elem& e1, std::string const& configName)
3356 {
3357   Options& clOptions = *(this->ClOptions[configName]);
3358   if (this->ProjectType == VsProjectType::csproj) {
3359     return;
3360   }
3361   Elem e2(e1, "ClCompile");
3362   OptionsHelper oh(clOptions, e2);
3363   oh.PrependInheritedString("AdditionalOptions");
3364   oh.OutputAdditionalIncludeDirectories(this->LangForClCompile);
3365   oh.OutputFlagMap();
3366   oh.OutputPreprocessorDefinitions(this->LangForClCompile);
3367
3368   if (this->NsightTegra) {
3369     if (cmValue processMax =
3370           this->GeneratorTarget->GetProperty("ANDROID_PROCESS_MAX")) {
3371       e2.Element("ProcessMax", *processMax);
3372     }
3373   }
3374
3375   if (this->Android) {
3376     e2.Element("ObjectFileName", "$(IntDir)%(filename).o");
3377   } else if (this->MSTools) {
3378     cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*");
3379     const char* toolset = this->GlobalGenerator->GetPlatformToolset();
3380     cmValue noCompileBatching =
3381       this->GeneratorTarget->GetProperty("VS_NO_COMPILE_BATCHING");
3382     if (noCompileBatching.IsOn() || (toolset && clangToolset.find(toolset))) {
3383       e2.Element("ObjectFileName", "$(IntDir)%(filename).obj");
3384     } else {
3385       e2.Element("ObjectFileName", "$(IntDir)");
3386     }
3387
3388     // If not in debug mode, write the DebugInformationFormat field
3389     // without value so PDBs don't get generated uselessly. Each tag
3390     // goes on its own line because Visual Studio corrects it this
3391     // way when saving the project after CMake generates it.
3392     if (!clOptions.IsDebug()) {
3393       Elem e3(e2, "DebugInformationFormat");
3394       e3.SetHasElements();
3395     }
3396
3397     // Specify the compiler program database file if configured.
3398     std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
3399     if (!pdb.empty()) {
3400       if (this->GlobalGenerator->IsCudaEnabled()) {
3401         // CUDA does not quote paths with spaces correctly when forwarding
3402         // this to the host compiler.  Use a relative path to avoid spaces.
3403         // FIXME: We can likely do this even when CUDA is not involved,
3404         // but for now we will make a minimal change.
3405         pdb = this->ConvertPath(pdb, true);
3406       }
3407       ConvertToWindowsSlash(pdb);
3408       e2.Element("ProgramDataBaseFileName", pdb);
3409     }
3410
3411     // add AdditionalUsingDirectories
3412     if (this->AdditionalUsingDirectories.count(configName) > 0) {
3413       std::string dirs;
3414       for (auto u : this->AdditionalUsingDirectories[configName]) {
3415         if (!dirs.empty()) {
3416           dirs.append(";");
3417         }
3418         dirs.append(u);
3419       }
3420       e2.Element("AdditionalUsingDirectories", dirs);
3421     }
3422   }
3423 }
3424
3425 bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
3426 {
3427   for (std::string const& c : this->Configurations) {
3428     if (!this->ComputeRcOptions(c)) {
3429       return false;
3430     }
3431   }
3432   return true;
3433 }
3434
3435 bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
3436   std::string const& configName)
3437 {
3438   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
3439   auto pOptions = cm::make_unique<Options>(
3440     this->LocalGenerator, Options::ResourceCompiler, gg->GetRcFlagTable());
3441   Options& rcOptions = *pOptions;
3442
3443   std::string CONFIG = cmSystemTools::UpperCase(configName);
3444   std::string rcConfigFlagsVar = "CMAKE_RC_FLAGS_" + CONFIG;
3445   std::string flags = this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS") +
3446     " " + this->Makefile->GetSafeDefinition(rcConfigFlagsVar);
3447
3448   rcOptions.Parse(flags);
3449
3450   // For historical reasons, add the C preprocessor defines to RC.
3451   Options& clOptions = *(this->ClOptions[configName]);
3452   rcOptions.AddDefines(clOptions.GetDefines());
3453
3454   // Get includes for this target
3455   rcOptions.AddIncludes(this->GetIncludes(configName, "RC"));
3456
3457   this->RcOptions[configName] = std::move(pOptions);
3458   return true;
3459 }
3460
3461 void cmVisualStudio10TargetGenerator::WriteRCOptions(
3462   Elem& e1, std::string const& configName)
3463 {
3464   if (!this->MSTools) {
3465     return;
3466   }
3467   Elem e2(e1, "ResourceCompile");
3468
3469   OptionsHelper rcOptions(*(this->RcOptions[configName]), e2);
3470   rcOptions.OutputPreprocessorDefinitions("RC");
3471   rcOptions.OutputAdditionalIncludeDirectories("RC");
3472   rcOptions.PrependInheritedString("AdditionalOptions");
3473   rcOptions.OutputFlagMap();
3474 }
3475
3476 bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
3477 {
3478   if (!this->GlobalGenerator->IsCudaEnabled()) {
3479     return true;
3480   }
3481   for (std::string const& c : this->Configurations) {
3482     if (this->GeneratorTarget->IsLanguageUsed("CUDA", c) &&
3483         !this->ComputeCudaOptions(c)) {
3484       return false;
3485     }
3486   }
3487   return true;
3488 }
3489
3490 bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
3491   std::string const& configName)
3492 {
3493   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
3494   auto pOptions = cm::make_unique<Options>(
3495     this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
3496   Options& cudaOptions = *pOptions;
3497
3498   auto cudaVersion = this->GlobalGenerator->GetPlatformToolsetCudaString();
3499
3500   // Get compile flags for CUDA in this directory.
3501   std::string flags;
3502   this->LocalGenerator->AddLanguageFlags(
3503     flags, this->GeneratorTarget, cmBuildStep::Compile, "CUDA", configName);
3504   this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA",
3505                                           configName);
3506
3507   // Get preprocessor definitions for this directory.
3508   std::string defineFlags = this->Makefile->GetDefineFlags();
3509
3510   cudaOptions.Parse(flags);
3511   cudaOptions.Parse(defineFlags);
3512   cudaOptions.ParseFinish();
3513
3514   // If we haven't explicitly enabled GPU debug information
3515   // explicitly disable it
3516   if (!cudaOptions.HasFlag("GPUDebugInfo")) {
3517     cudaOptions.AddFlag("GPUDebugInfo", "false");
3518   }
3519
3520   // The extension on object libraries the CUDA gives isn't
3521   // consistent with how MSVC generates object libraries for C+, so set
3522   // the default to not have any extension
3523   cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).obj");
3524
3525   if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
3526     cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true");
3527   }
3528   bool notPtx = true;
3529   if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
3530     cudaOptions.AddFlag("NvccCompilation", "ptx");
3531     // We drop the %(Extension) component as CMake expects all PTX files
3532     // to not have the source file extension at all
3533     cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).ptx");
3534     notPtx = false;
3535
3536     if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
3537                                       cudaVersion, "9.0") &&
3538         cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, cudaVersion,
3539                                       "11.5")) {
3540       // The DriverApi flag before 11.5 ( verified back to 9.0 ) which controls
3541       // PTX compilation doesn't propagate user defines causing
3542       // target_compile_definitions to behave differently for VS +
3543       // PTX compared to other generators so we patch the rules
3544       // to normalize behavior
3545       cudaOptions.AddFlag("DriverApiCommandLineTemplate",
3546                           "%(BaseCommandLineTemplate) [CompileOut] [FastMath] "
3547                           "[Defines] \"%(FullPath)\"");
3548     }
3549   }
3550
3551   if (notPtx &&
3552       cmSystemTools::VersionCompareGreaterEq(
3553         "8.0", this->GlobalGenerator->GetPlatformToolsetCudaString())) {
3554     // Explicitly state that we want this file to be treated as a
3555     // CUDA file no matter what the file extensions is
3556     // This is only needed for < CUDA 9
3557     cudaOptions.AppendFlagString("AdditionalOptions", "-x cu");
3558   }
3559
3560   // Specify the compiler program database file if configured.
3561   std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
3562   if (!pdb.empty()) {
3563     // CUDA does not make the directory if it is non-standard.
3564     std::string const pdbDir = cmSystemTools::GetFilenamePath(pdb);
3565     cmSystemTools::MakeDirectory(pdbDir);
3566     if (cmSystemTools::VersionCompareGreaterEq(
3567           "9.2", this->GlobalGenerator->GetPlatformToolsetCudaString())) {
3568       // CUDA does not have a field for this and does not honor the
3569       // ProgramDataBaseFileName field in ClCompile.  Work around this
3570       // limitation by creating the directory and passing the flag ourselves.
3571       pdb = this->ConvertPath(pdb, true);
3572       ConvertToWindowsSlash(pdb);
3573       std::string const clFd = "-Xcompiler=\"-Fd\\\"" + pdb + "\\\"\"";
3574       cudaOptions.AppendFlagString("AdditionalOptions", clFd);
3575     }
3576   }
3577
3578   // CUDA automatically passes the proper '--machine' flag to nvcc
3579   // for the current architecture, but does not reflect this default
3580   // in the user-visible IDE settings.  Set it explicitly.
3581   if (this->Platform == "x64") {
3582     cudaOptions.AddFlag("TargetMachinePlatform", "64");
3583   }
3584
3585   // Convert the host compiler options to the toolset's abstractions
3586   // using a secondary flag table.
3587   cudaOptions.ClearTables();
3588   cudaOptions.AddTable(gg->GetCudaHostFlagTable());
3589   cudaOptions.Reparse("AdditionalCompilerOptions");
3590
3591   // `CUDA 8.0.targets` places AdditionalCompilerOptions before nvcc!
3592   // Pass them through -Xcompiler in AdditionalOptions instead.
3593   if (const char* acoPtr = cudaOptions.GetFlag("AdditionalCompilerOptions")) {
3594     std::string aco = acoPtr;
3595     cudaOptions.RemoveFlag("AdditionalCompilerOptions");
3596     if (!aco.empty()) {
3597       aco = this->LocalGenerator->EscapeForShell(aco, false);
3598       cudaOptions.AppendFlagString("AdditionalOptions", "-Xcompiler=" + aco);
3599     }
3600   }
3601
3602   cudaOptions.FixCudaCodeGeneration();
3603
3604   std::vector<std::string> targetDefines;
3605   this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
3606                                                "CUDA");
3607   cudaOptions.AddDefines(targetDefines);
3608
3609   // Add a definition for the configuration name.
3610   std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
3611   cudaOptions.AddDefine(configDefine);
3612   if (const std::string* exportMacro =
3613         this->GeneratorTarget->GetExportMacro()) {
3614     cudaOptions.AddDefine(*exportMacro);
3615   }
3616
3617   // Get includes for this target
3618   cudaOptions.AddIncludes(this->GetIncludes(configName, "CUDA"));
3619   cudaOptions.AddFlag("UseHostInclude", "false");
3620
3621   // Add runtime library selection flag.
3622   std::string const& cudaRuntime =
3623     this->GeneratorTarget->GetRuntimeLinkLibrary("CUDA", configName);
3624   if (cudaRuntime == "STATIC") {
3625     cudaOptions.AddFlag("CudaRuntime", "Static");
3626   } else if (cudaRuntime == "SHARED") {
3627     cudaOptions.AddFlag("CudaRuntime", "Shared");
3628   } else if (cudaRuntime == "NONE") {
3629     cudaOptions.AddFlag("CudaRuntime", "None");
3630   }
3631
3632   this->CudaOptions[configName] = std::move(pOptions);
3633   return true;
3634 }
3635
3636 void cmVisualStudio10TargetGenerator::WriteCudaOptions(
3637   Elem& e1, std::string const& configName)
3638 {
3639   if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled() ||
3640       !this->GeneratorTarget->IsLanguageUsed("CUDA", configName)) {
3641     return;
3642   }
3643   Elem e2(e1, "CudaCompile");
3644
3645   OptionsHelper cudaOptions(*(this->CudaOptions[configName]), e2);
3646   cudaOptions.OutputAdditionalIncludeDirectories("CUDA");
3647   cudaOptions.OutputPreprocessorDefinitions("CUDA");
3648   cudaOptions.PrependInheritedString("AdditionalOptions");
3649   cudaOptions.OutputFlagMap();
3650 }
3651
3652 bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
3653 {
3654   if (!this->GlobalGenerator->IsCudaEnabled()) {
3655     return true;
3656   }
3657   for (std::string const& c : this->Configurations) {
3658     if (!this->ComputeCudaLinkOptions(c)) {
3659       return false;
3660     }
3661   }
3662   return true;
3663 }
3664
3665 bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
3666   std::string const& configName)
3667 {
3668   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
3669   auto pOptions = cm::make_unique<Options>(
3670     this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
3671   Options& cudaLinkOptions = *pOptions;
3672
3673   cmGeneratorTarget::DeviceLinkSetter setter(*this->GeneratorTarget);
3674
3675   // Determine if we need to do a device link
3676   const bool doDeviceLinking = requireDeviceLinking(
3677     *this->GeneratorTarget, *this->LocalGenerator, configName);
3678
3679   cudaLinkOptions.AddFlag("PerformDeviceLink",
3680                           doDeviceLinking ? "true" : "false");
3681
3682   // Add extra flags for device linking
3683   cudaLinkOptions.AppendFlagString(
3684     "AdditionalOptions",
3685     this->Makefile->GetSafeDefinition("_CMAKE_CUDA_EXTRA_FLAGS"));
3686   cudaLinkOptions.AppendFlagString(
3687     "AdditionalOptions",
3688     this->Makefile->GetSafeDefinition("_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS"));
3689
3690   std::vector<std::string> linkOpts;
3691   std::string linkFlags;
3692   this->GeneratorTarget->GetLinkOptions(linkOpts, configName, "CUDA");
3693   // LINK_OPTIONS are escaped.
3694   this->LocalGenerator->AppendCompileOptions(linkFlags, linkOpts);
3695
3696   cmComputeLinkInformation* pcli =
3697     this->GeneratorTarget->GetLinkInformation(configName);
3698   if (doDeviceLinking && pcli) {
3699
3700     cmLinkLineDeviceComputer computer(
3701       this->LocalGenerator,
3702       this->LocalGenerator->GetStateSnapshot().GetDirectory());
3703     std::string ignored_;
3704     this->LocalGenerator->GetDeviceLinkFlags(computer, configName, ignored_,
3705                                              linkFlags, ignored_, ignored_,
3706                                              this->GeneratorTarget);
3707
3708     this->LocalGenerator->AddLanguageFlagsForLinking(
3709       linkFlags, this->GeneratorTarget, "CUDA", configName);
3710   }
3711   cudaLinkOptions.AppendFlagString("AdditionalOptions", linkFlags);
3712
3713   // For static libraries that have device linking enabled compute
3714   // the  libraries
3715   if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY &&
3716       doDeviceLinking) {
3717     cmComputeLinkInformation& cli = *pcli;
3718     cmLinkLineDeviceComputer computer(
3719       this->LocalGenerator,
3720       this->LocalGenerator->GetStateSnapshot().GetDirectory());
3721     std::vector<BT<std::string>> btLibVec;
3722     computer.ComputeLinkLibraries(cli, std::string{}, btLibVec);
3723     std::vector<std::string> libVec;
3724     for (auto const& item : btLibVec) {
3725       libVec.emplace_back(item.Value);
3726     }
3727
3728     cudaLinkOptions.AddFlag("AdditionalDependencies", libVec);
3729   }
3730
3731   this->CudaLinkOptions[configName] = std::move(pOptions);
3732   return true;
3733 }
3734
3735 void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions(
3736   Elem& e1, std::string const& configName)
3737 {
3738   if (this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
3739     return;
3740   }
3741
3742   if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
3743     return;
3744   }
3745
3746   Elem e2(e1, "CudaLink");
3747   OptionsHelper cudaLinkOptions(*(this->CudaLinkOptions[configName]), e2);
3748   cudaLinkOptions.OutputFlagMap();
3749 }
3750
3751 bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
3752 {
3753   if (!this->GlobalGenerator->IsMasmEnabled()) {
3754     return true;
3755   }
3756   for (std::string const& c : this->Configurations) {
3757     if (!this->ComputeMasmOptions(c)) {
3758       return false;
3759     }
3760   }
3761   return true;
3762 }
3763
3764 bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
3765   std::string const& configName)
3766 {
3767   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
3768   auto pOptions = cm::make_unique<Options>(
3769     this->LocalGenerator, Options::MasmCompiler, gg->GetMasmFlagTable());
3770   Options& masmOptions = *pOptions;
3771
3772   std::string flags;
3773   this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
3774                                          cmBuildStep::Compile, "ASM_MASM",
3775                                          configName);
3776
3777   masmOptions.Parse(flags);
3778
3779   // Get includes for this target
3780   masmOptions.AddIncludes(this->GetIncludes(configName, "ASM_MASM"));
3781
3782   this->MasmOptions[configName] = std::move(pOptions);
3783   return true;
3784 }
3785
3786 void cmVisualStudio10TargetGenerator::WriteMasmOptions(
3787   Elem& e1, std::string const& configName)
3788 {
3789   if (!this->MSTools || !this->GlobalGenerator->IsMasmEnabled()) {
3790     return;
3791   }
3792   Elem e2(e1, "MASM");
3793
3794   // Preprocessor definitions and includes are shared with clOptions.
3795   OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
3796   clOptions.OutputPreprocessorDefinitions("ASM_MASM");
3797
3798   OptionsHelper masmOptions(*(this->MasmOptions[configName]), e2);
3799   masmOptions.OutputAdditionalIncludeDirectories("ASM_MASM");
3800   masmOptions.PrependInheritedString("AdditionalOptions");
3801   masmOptions.OutputFlagMap();
3802 }
3803
3804 bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
3805 {
3806   if (!this->GlobalGenerator->IsNasmEnabled()) {
3807     return true;
3808   }
3809   for (std::string const& c : this->Configurations) {
3810     if (!this->ComputeNasmOptions(c)) {
3811       return false;
3812     }
3813   }
3814   return true;
3815 }
3816
3817 bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
3818   std::string const& configName)
3819 {
3820   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
3821   auto pOptions = cm::make_unique<Options>(
3822     this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable());
3823   Options& nasmOptions = *pOptions;
3824
3825   std::string flags;
3826   this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
3827                                          cmBuildStep::Compile, "ASM_NASM",
3828                                          configName);
3829   flags += " -f";
3830   flags += this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT");
3831   nasmOptions.Parse(flags);
3832
3833   // Get includes for this target
3834   nasmOptions.AddIncludes(this->GetIncludes(configName, "ASM_NASM"));
3835
3836   this->NasmOptions[configName] = std::move(pOptions);
3837   return true;
3838 }
3839
3840 void cmVisualStudio10TargetGenerator::WriteNasmOptions(
3841   Elem& e1, std::string const& configName)
3842 {
3843   if (!this->GlobalGenerator->IsNasmEnabled()) {
3844     return;
3845   }
3846   Elem e2(e1, "NASM");
3847
3848   OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2);
3849   nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM");
3850   nasmOptions.OutputFlagMap();
3851   nasmOptions.PrependInheritedString("AdditionalOptions");
3852   nasmOptions.OutputPreprocessorDefinitions("ASM_NASM");
3853
3854   // Preprocessor definitions and includes are shared with clOptions.
3855   OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
3856   clOptions.OutputPreprocessorDefinitions("ASM_NASM");
3857 }
3858
3859 void cmVisualStudio10TargetGenerator::WriteLibOptions(
3860   Elem& e1, std::string const& config)
3861 {
3862   if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY &&
3863       this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
3864     return;
3865   }
3866
3867   const std::string& linkLanguage =
3868     this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage;
3869
3870   std::string libflags;
3871   this->LocalGenerator->GetStaticLibraryFlags(libflags, config, linkLanguage,
3872                                               this->GeneratorTarget);
3873   if (!libflags.empty()) {
3874     Elem e2(e1, "Lib");
3875     cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
3876     cmVS10GeneratorOptions libOptions(this->LocalGenerator,
3877                                       cmVisualStudioGeneratorOptions::Linker,
3878                                       gg->GetLibFlagTable(), this);
3879     libOptions.Parse(libflags);
3880     OptionsHelper oh(libOptions, e2);
3881     oh.PrependInheritedString("AdditionalOptions");
3882     oh.OutputFlagMap();
3883   }
3884
3885   // We cannot generate metadata for static libraries.  WindowsPhone
3886   // and WindowsStore tools look at GenerateWindowsMetadata in the
3887   // Link tool options even for static libraries.
3888   if (this->GlobalGenerator->TargetsWindowsPhone() ||
3889       this->GlobalGenerator->TargetsWindowsStore()) {
3890     Elem e2(e1, "Link");
3891     e2.Element("GenerateWindowsMetadata", "false");
3892   }
3893 }
3894
3895 void cmVisualStudio10TargetGenerator::WriteManifestOptions(
3896   Elem& e1, std::string const& config)
3897 {
3898   if (this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE &&
3899       this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY &&
3900       this->GeneratorTarget->GetType() != cmStateEnums::MODULE_LIBRARY) {
3901     return;
3902   }
3903
3904   std::vector<cmSourceFile const*> manifest_srcs;
3905   this->GeneratorTarget->GetManifests(manifest_srcs, config);
3906
3907   cmValue dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE");
3908
3909   if (!manifest_srcs.empty() || dpiAware) {
3910     Elem e2(e1, "Manifest");
3911     if (!manifest_srcs.empty()) {
3912       std::ostringstream oss;
3913       for (cmSourceFile const* mi : manifest_srcs) {
3914         std::string m = this->ConvertPath(mi->GetFullPath(), false);
3915         ConvertToWindowsSlash(m);
3916         oss << m << ";";
3917       }
3918       e2.Element("AdditionalManifestFiles", oss.str());
3919     }
3920     if (dpiAware) {
3921       if (*dpiAware == "PerMonitor") {
3922         e2.Element("EnableDpiAwareness", "PerMonitorHighDPIAware");
3923       } else if (cmIsOn(*dpiAware)) {
3924         e2.Element("EnableDpiAwareness", "true");
3925       } else if (cmIsOff(*dpiAware)) {
3926         e2.Element("EnableDpiAwareness", "false");
3927       } else {
3928         cmSystemTools::Error("Bad parameter for VS_DPI_AWARE: " + *dpiAware);
3929       }
3930     }
3931   }
3932 }
3933
3934 void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
3935   Elem& e1, std::string const& configName)
3936 {
3937   // Look through the sources for AndroidManifest.xml and use
3938   // its location as the root source directory.
3939   std::string rootDir = this->LocalGenerator->GetCurrentSourceDirectory();
3940   {
3941     for (cmGeneratorTarget::AllConfigSource const& source :
3942          this->GeneratorTarget->GetAllConfigSources()) {
3943       if (source.Kind == cmGeneratorTarget::SourceKindExtra &&
3944           "androidmanifest.xml" ==
3945             cmSystemTools::LowerCase(source.Source->GetLocation().GetName())) {
3946         rootDir = source.Source->GetLocation().GetDirectory();
3947         break;
3948       }
3949     }
3950   }
3951
3952   // Tell MSBuild to launch Ant.
3953   Elem e2(e1, "AntBuild");
3954   {
3955     std::string antBuildPath = rootDir;
3956     ConvertToWindowsSlash(antBuildPath);
3957     e2.Element("AntBuildPath", antBuildPath);
3958   }
3959
3960   if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) {
3961     e2.Element("SkipAntStep", "true");
3962   }
3963
3964   if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_PROGUARD")) {
3965     e2.Element("EnableProGuard", "true");
3966   }
3967
3968   if (cmValue proGuardConfigLocation =
3969         this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) {
3970     e2.Element("ProGuardConfigLocation", *proGuardConfigLocation);
3971   }
3972
3973   if (cmValue securePropertiesLocation =
3974         this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) {
3975     e2.Element("SecurePropertiesLocation", *securePropertiesLocation);
3976   }
3977
3978   if (cmValue nativeLibDirectoriesExpression =
3979         this->GeneratorTarget->GetProperty("ANDROID_NATIVE_LIB_DIRECTORIES")) {
3980     std::string nativeLibDirs = cmGeneratorExpression::Evaluate(
3981       *nativeLibDirectoriesExpression, this->LocalGenerator, configName);
3982     e2.Element("NativeLibDirectories", nativeLibDirs);
3983   }
3984
3985   if (cmValue nativeLibDependenciesExpression =
3986         this->GeneratorTarget->GetProperty(
3987           "ANDROID_NATIVE_LIB_DEPENDENCIES")) {
3988     std::string nativeLibDeps = cmGeneratorExpression::Evaluate(
3989       *nativeLibDependenciesExpression, this->LocalGenerator, configName);
3990     e2.Element("NativeLibDependencies", nativeLibDeps);
3991   }
3992
3993   if (cmValue javaSourceDir =
3994         this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) {
3995     e2.Element("JavaSourceDir", *javaSourceDir);
3996   }
3997
3998   if (cmValue jarDirectoriesExpression =
3999         this->GeneratorTarget->GetProperty("ANDROID_JAR_DIRECTORIES")) {
4000     std::string jarDirectories = cmGeneratorExpression::Evaluate(
4001       *jarDirectoriesExpression, this->LocalGenerator, configName);
4002     e2.Element("JarDirectories", jarDirectories);
4003   }
4004
4005   if (cmValue jarDeps =
4006         this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) {
4007     e2.Element("JarDependencies", *jarDeps);
4008   }
4009
4010   if (cmValue assetsDirectories =
4011         this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) {
4012     e2.Element("AssetsDirectories", *assetsDirectories);
4013   }
4014
4015   {
4016     std::string manifest_xml = rootDir + "/AndroidManifest.xml";
4017     ConvertToWindowsSlash(manifest_xml);
4018     e2.Element("AndroidManifestLocation", manifest_xml);
4019   }
4020
4021   if (cmValue antAdditionalOptions =
4022         this->GeneratorTarget->GetProperty("ANDROID_ANT_ADDITIONAL_OPTIONS")) {
4023     e2.Element("AdditionalOptions",
4024                *antAdditionalOptions + " %(AdditionalOptions)");
4025   }
4026 }
4027
4028 bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
4029 {
4030   if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
4031       this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
4032       this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
4033     for (std::string const& c : this->Configurations) {
4034       if (!this->ComputeLinkOptions(c)) {
4035         return false;
4036       }
4037     }
4038   }
4039   return true;
4040 }
4041
4042 bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
4043   std::string const& config)
4044 {
4045   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
4046   auto pOptions = cm::make_unique<Options>(
4047     this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), this);
4048   Options& linkOptions = *pOptions;
4049
4050   cmGeneratorTarget::LinkClosure const* linkClosure =
4051     this->GeneratorTarget->GetLinkClosure(config);
4052
4053   const std::string& linkLanguage = linkClosure->LinkerLanguage;
4054   if (linkLanguage.empty()) {
4055     cmSystemTools::Error(
4056       "CMake can not determine linker language for target: " + this->Name);
4057     return false;
4058   }
4059
4060   std::string CONFIG = cmSystemTools::UpperCase(config);
4061
4062   const char* linkType = "SHARED";
4063   if (this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
4064     linkType = "MODULE";
4065   }
4066   if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4067     linkType = "EXE";
4068   }
4069   std::string flags;
4070   std::string linkFlagVarBase = cmStrCat("CMAKE_", linkType, "_LINKER_FLAGS");
4071   flags += " ";
4072   flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase);
4073   std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
4074   flags += " ";
4075   flags += this->Makefile->GetRequiredDefinition(linkFlagVar);
4076   cmValue targetLinkFlags = this->GeneratorTarget->GetProperty("LINK_FLAGS");
4077   if (targetLinkFlags) {
4078     flags += " ";
4079     flags += *targetLinkFlags;
4080   }
4081   std::string flagsProp = cmStrCat("LINK_FLAGS_", CONFIG);
4082   if (cmValue flagsConfig = this->GeneratorTarget->GetProperty(flagsProp)) {
4083     flags += " ";
4084     flags += *flagsConfig;
4085   }
4086
4087   std::vector<std::string> opts;
4088   this->GeneratorTarget->GetLinkOptions(opts, config, linkLanguage);
4089   // LINK_OPTIONS are escaped.
4090   this->LocalGenerator->AppendCompileOptions(flags, opts);
4091
4092   cmComputeLinkInformation* pcli =
4093     this->GeneratorTarget->GetLinkInformation(config);
4094   if (!pcli) {
4095     cmSystemTools::Error(
4096       "CMake can not compute cmComputeLinkInformation for target: " +
4097       this->Name);
4098     return false;
4099   }
4100   cmComputeLinkInformation& cli = *pcli;
4101
4102   std::vector<std::string> libVec;
4103   std::vector<std::string> vsTargetVec;
4104   this->AddLibraries(cli, libVec, vsTargetVec, config);
4105   std::string standardLibsVar =
4106     cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES");
4107   std::string const& libs = this->Makefile->GetSafeDefinition(standardLibsVar);
4108   cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec);
4109   linkOptions.AddFlag("AdditionalDependencies", libVec);
4110
4111   // Populate TargetsFileAndConfigsVec
4112   for (std::string const& ti : vsTargetVec) {
4113     this->AddTargetsFileAndConfigPair(ti, config);
4114   }
4115
4116   std::vector<std::string> const& ldirs = cli.GetDirectories();
4117   std::vector<std::string> linkDirs;
4118   for (std::string const& d : ldirs) {
4119     // first just full path
4120     linkDirs.push_back(d);
4121     // next path with configuration type Debug, Release, etc
4122     linkDirs.push_back(d + "/$(Configuration)");
4123   }
4124   linkDirs.push_back("%(AdditionalLibraryDirectories)");
4125   linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs);
4126
4127   cmGeneratorTarget::Names targetNames;
4128   if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4129     targetNames = this->GeneratorTarget->GetExecutableNames(config);
4130   } else {
4131     targetNames = this->GeneratorTarget->GetLibraryNames(config);
4132   }
4133
4134   if (this->MSTools) {
4135     if (this->GeneratorTarget->IsWin32Executable(config)) {
4136       if (this->GlobalGenerator->TargetsWindowsCE()) {
4137         linkOptions.AddFlag("SubSystem", "WindowsCE");
4138         if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4139           if (this->ClOptions[config]->UsingUnicode()) {
4140             linkOptions.AddFlag("EntryPointSymbol", "wWinMainCRTStartup");
4141           } else {
4142             linkOptions.AddFlag("EntryPointSymbol", "WinMainCRTStartup");
4143           }
4144         }
4145       } else {
4146         linkOptions.AddFlag("SubSystem", "Windows");
4147       }
4148     } else {
4149       if (this->GlobalGenerator->TargetsWindowsCE()) {
4150         linkOptions.AddFlag("SubSystem", "WindowsCE");
4151         if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4152           if (this->ClOptions[config]->UsingUnicode()) {
4153             linkOptions.AddFlag("EntryPointSymbol", "mainWCRTStartup");
4154           } else {
4155             linkOptions.AddFlag("EntryPointSymbol", "mainACRTStartup");
4156           }
4157         }
4158       } else {
4159         linkOptions.AddFlag("SubSystem", "Console");
4160       };
4161     }
4162
4163     if (cmValue stackVal = this->Makefile->GetDefinition(
4164           "CMAKE_" + linkLanguage + "_STACK_SIZE")) {
4165       linkOptions.AddFlag("StackReserveSize", *stackVal);
4166     }
4167
4168     linkOptions.AddFlag("GenerateDebugInformation", "false");
4169
4170     std::string pdb = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config),
4171                                '/', targetNames.PDB);
4172     if (!targetNames.ImportLibrary.empty()) {
4173       std::string imLib =
4174         cmStrCat(this->GeneratorTarget->GetDirectory(
4175                    config, cmStateEnums::ImportLibraryArtifact),
4176                  '/', targetNames.ImportLibrary);
4177
4178       linkOptions.AddFlag("ImportLibrary", imLib);
4179     }
4180     linkOptions.AddFlag("ProgramDataBaseFile", pdb);
4181
4182     // A Windows Runtime component uses internal .NET metadata,
4183     // so does not have an import library.
4184     if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") &&
4185         this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE) {
4186       linkOptions.AddFlag("GenerateWindowsMetadata", "true");
4187     } else if (this->GlobalGenerator->TargetsWindowsPhone() ||
4188                this->GlobalGenerator->TargetsWindowsStore()) {
4189       // WindowsPhone and WindowsStore components are in an app container
4190       // and produce WindowsMetadata.  If we are not producing a WINRT
4191       // component, then do not generate the metadata here.
4192       linkOptions.AddFlag("GenerateWindowsMetadata", "false");
4193     }
4194
4195     if (this->GlobalGenerator->TargetsWindowsPhone() &&
4196         this->GlobalGenerator->GetSystemVersion() == "8.0") {
4197       // WindowsPhone 8.0 does not have ole32.
4198       linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "ole32.lib");
4199     }
4200   } else if (this->NsightTegra) {
4201     linkOptions.AddFlag("SoName", targetNames.SharedObject);
4202   }
4203
4204   linkOptions.Parse(flags);
4205   linkOptions.FixManifestUACFlags();
4206
4207   if (this->MSTools) {
4208     cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
4209       this->GeneratorTarget->GetModuleDefinitionInfo(config);
4210     if (mdi && !mdi->DefFile.empty()) {
4211       linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile);
4212     }
4213     linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
4214                            "%(IgnoreSpecificDefaultLibraries)");
4215   }
4216
4217   // VS 2015 without all updates has a v140 toolset whose
4218   // GenerateDebugInformation expects No/Debug instead of false/true.
4219   if (gg->GetPlatformToolsetNeedsDebugEnum()) {
4220     if (const char* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
4221       if (strcmp(debug, "false") == 0) {
4222         linkOptions.AddFlag("GenerateDebugInformation", "No");
4223       } else if (strcmp(debug, "true") == 0) {
4224         linkOptions.AddFlag("GenerateDebugInformation", "Debug");
4225       }
4226     }
4227   }
4228
4229   // Managed code cannot be linked with /DEBUG:FASTLINK
4230   if (this->Managed) {
4231     if (const char* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
4232       if (strcmp(debug, "DebugFastLink") == 0) {
4233         linkOptions.AddFlag("GenerateDebugInformation", "Debug");
4234       }
4235     }
4236   }
4237
4238   this->LinkOptions[config] = std::move(pOptions);
4239   return true;
4240 }
4241
4242 bool cmVisualStudio10TargetGenerator::ComputeLibOptions()
4243 {
4244   if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
4245     for (std::string const& c : this->Configurations) {
4246       if (!this->ComputeLibOptions(c)) {
4247         return false;
4248       }
4249     }
4250   }
4251   return true;
4252 }
4253
4254 bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
4255   std::string const& config)
4256 {
4257   cmComputeLinkInformation* pcli =
4258     this->GeneratorTarget->GetLinkInformation(config);
4259   if (!pcli) {
4260     cmSystemTools::Error(
4261       "CMake can not compute cmComputeLinkInformation for target: " +
4262       this->Name);
4263     return false;
4264   }
4265
4266   cmComputeLinkInformation& cli = *pcli;
4267   using ItemVector = cmComputeLinkInformation::ItemVector;
4268   const ItemVector& libs = cli.GetItems();
4269   for (cmComputeLinkInformation::Item const& l : libs) {
4270     if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes &&
4271         cmVS10IsTargetsFile(l.Value.Value)) {
4272       std::string path =
4273         this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
4274       ConvertToWindowsSlash(path);
4275       this->AddTargetsFileAndConfigPair(path, config);
4276     }
4277   }
4278
4279   return true;
4280 }
4281
4282 void cmVisualStudio10TargetGenerator::WriteLinkOptions(
4283   Elem& e1, std::string const& config)
4284 {
4285   if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
4286       this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
4287     return;
4288   }
4289   if (this->ProjectType == VsProjectType::csproj) {
4290     return;
4291   }
4292
4293   {
4294     Elem e2(e1, "Link");
4295     OptionsHelper linkOptions(*(this->LinkOptions[config]), e2);
4296     linkOptions.PrependInheritedString("AdditionalOptions");
4297     linkOptions.OutputFlagMap();
4298   }
4299
4300   if (!this->GlobalGenerator->NeedLinkLibraryDependencies(
4301         this->GeneratorTarget)) {
4302     Elem e2(e1, "ProjectReference");
4303     e2.Element("LinkLibraryDependencies", "false");
4304   }
4305 }
4306
4307 void cmVisualStudio10TargetGenerator::AddLibraries(
4308   const cmComputeLinkInformation& cli, std::vector<std::string>& libVec,
4309   std::vector<std::string>& vsTargetVec, const std::string& config)
4310 {
4311   using ItemVector = cmComputeLinkInformation::ItemVector;
4312   ItemVector const& libs = cli.GetItems();
4313   for (cmComputeLinkInformation::Item const& l : libs) {
4314     if (l.Target) {
4315       auto managedType = l.Target->GetManagedType(config);
4316       if (managedType != cmGeneratorTarget::ManagedType::Native &&
4317           this->GeneratorTarget->GetManagedType(config) !=
4318             cmGeneratorTarget::ManagedType::Native &&
4319           l.Target->IsImported() &&
4320           l.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
4321         auto location = l.Target->GetFullPath(config);
4322         if (!location.empty()) {
4323           ConvertToWindowsSlash(location);
4324           switch (this->ProjectType) {
4325             case VsProjectType::csproj:
4326               // If the target we want to "link" to is an imported managed
4327               // target and this is a C# project, we add a hint reference. This
4328               // reference is written to project file in
4329               // WriteDotNetReferences().
4330               this->DotNetHintReferences[config].push_back(
4331                 DotNetHintReference(l.Target->GetName(), location));
4332               break;
4333             case VsProjectType::vcxproj:
4334               // Add path of assembly to list of using-directories, so the
4335               // managed assembly can be used by '#using <assembly.dll>' in
4336               // code.
4337               this->AdditionalUsingDirectories[config].insert(
4338                 cmSystemTools::GetFilenamePath(location));
4339               break;
4340             default:
4341               // In .proj files, we wouldn't be referencing libraries.
4342               break;
4343           }
4344         }
4345       }
4346       // Do not allow C# targets to be added to the LIB listing. LIB files are
4347       // used for linking C++ dependencies. C# libraries do not have lib files.
4348       // Instead, they compile down to C# reference libraries (DLL files). The
4349       // `<ProjectReference>` elements added to the vcxproj are enough for the
4350       // IDE to deduce the DLL file required by other C# projects that need its
4351       // reference library.
4352       if (managedType == cmGeneratorTarget::ManagedType::Managed) {
4353         continue;
4354       }
4355     }
4356
4357     if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
4358       std::string path =
4359         this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
4360       ConvertToWindowsSlash(path);
4361       if (cmVS10IsTargetsFile(l.Value.Value)) {
4362         vsTargetVec.push_back(path);
4363       } else {
4364         libVec.push_back(l.HasFeature() ? l.GetFormattedItem(path).Value
4365                                         : path);
4366       }
4367     } else if (!l.Target ||
4368                l.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
4369       libVec.push_back(l.Value.Value);
4370     }
4371   }
4372 }
4373
4374 void cmVisualStudio10TargetGenerator::AddTargetsFileAndConfigPair(
4375   std::string const& targetsFile, std::string const& config)
4376 {
4377   for (TargetsFileAndConfigs& i : this->TargetsFileAndConfigsVec) {
4378     if (cmSystemTools::ComparePath(targetsFile, i.File)) {
4379       if (!cm::contains(i.Configs, config)) {
4380         i.Configs.push_back(config);
4381       }
4382       return;
4383     }
4384   }
4385   TargetsFileAndConfigs entry;
4386   entry.File = targetsFile;
4387   entry.Configs.push_back(config);
4388   this->TargetsFileAndConfigsVec.push_back(entry);
4389 }
4390
4391 void cmVisualStudio10TargetGenerator::WriteMidlOptions(
4392   Elem& e1, std::string const& configName)
4393 {
4394   if (!this->MSTools) {
4395     return;
4396   }
4397   if (this->ProjectType == VsProjectType::csproj) {
4398     return;
4399   }
4400   if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
4401     return;
4402   }
4403
4404   // This processes *any* of the .idl files specified in the project's file
4405   // list (and passed as the item metadata %(Filename) expressing the rule
4406   // input filename) into output files at the per-config *build* dir
4407   // ($(IntDir)) each.
4408   //
4409   // IOW, this MIDL section is intended to provide a fully generic syntax
4410   // content suitable for most cases (read: if you get errors, then it's quite
4411   // probable that the error is on your side of the .idl setup).
4412   //
4413   // Also, note that the marked-as-generated _i.c file in the Visual Studio
4414   // generator case needs to be referred to as $(IntDir)\foo_i.c at the
4415   // project's file list, otherwise the compiler-side processing won't pick it
4416   // up (for non-directory form, it ends up looking in project binary dir
4417   // only).  Perhaps there's something to be done to make this more automatic
4418   // on the CMake side?
4419   std::vector<std::string> const includes =
4420     this->GetIncludes(configName, "MIDL");
4421   std::ostringstream oss;
4422   for (std::string const& i : includes) {
4423     oss << i << ";";
4424   }
4425   oss << "%(AdditionalIncludeDirectories)";
4426
4427   Elem e2(e1, "Midl");
4428   e2.Element("AdditionalIncludeDirectories", oss.str());
4429   e2.Element("OutputDirectory", "$(ProjectDir)/$(IntDir)");
4430   e2.Element("HeaderFileName", "%(Filename).h");
4431   e2.Element("TypeLibraryName", "%(Filename).tlb");
4432   e2.Element("InterfaceIdentifierFileName", "%(Filename)_i.c");
4433   e2.Element("ProxyFileName", "%(Filename)_p.c");
4434 }
4435
4436 void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
4437 {
4438   if (this->ProjectType == VsProjectType::csproj) {
4439     return;
4440   }
4441   for (const std::string& c : this->Configurations) {
4442     Elem e1(e0, "ItemDefinitionGroup");
4443     e1.Attribute("Condition", this->CalcCondition(c));
4444
4445     //    output cl compile flags <ClCompile></ClCompile>
4446     if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
4447       this->WriteClOptions(e1, c);
4448       //    output rc compile flags <ResourceCompile></ResourceCompile>
4449       this->WriteRCOptions(e1, c);
4450       this->WriteCudaOptions(e1, c);
4451       this->WriteMasmOptions(e1, c);
4452       this->WriteNasmOptions(e1, c);
4453     }
4454     //    output midl flags       <Midl></Midl>
4455     this->WriteMidlOptions(e1, c);
4456     // write events
4457     if (this->ProjectType != VsProjectType::csproj) {
4458       this->WriteEvents(e1, c);
4459     }
4460     //    output link flags       <Link></Link>
4461     this->WriteLinkOptions(e1, c);
4462     this->WriteCudaLinkOptions(e1, c);
4463     //    output lib flags       <Lib></Lib>
4464     this->WriteLibOptions(e1, c);
4465     //    output manifest flags  <Manifest></Manifest>
4466     this->WriteManifestOptions(e1, c);
4467     if (this->NsightTegra &&
4468         this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
4469       this->WriteAntBuildOptions(e1, c);
4470     }
4471   }
4472 }
4473
4474 void cmVisualStudio10TargetGenerator::WriteEvents(
4475   Elem& e1, std::string const& configName)
4476 {
4477   bool addedPrelink = false;
4478   cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
4479     this->GeneratorTarget->GetModuleDefinitionInfo(configName);
4480   if (mdi && mdi->DefFileGenerated) {
4481     addedPrelink = true;
4482     std::vector<cmCustomCommand> commands =
4483       this->GeneratorTarget->GetPreLinkCommands();
4484     this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
4485                                                   commands, configName);
4486     this->WriteEvent(e1, "PreLinkEvent", commands, configName);
4487   }
4488   if (!addedPrelink) {
4489     this->WriteEvent(e1, "PreLinkEvent",
4490                      this->GeneratorTarget->GetPreLinkCommands(), configName);
4491   }
4492   this->WriteEvent(e1, "PreBuildEvent",
4493                    this->GeneratorTarget->GetPreBuildCommands(), configName);
4494   this->WriteEvent(e1, "PostBuildEvent",
4495                    this->GeneratorTarget->GetPostBuildCommands(), configName);
4496 }
4497
4498 void cmVisualStudio10TargetGenerator::WriteEvent(
4499   Elem& e1, const std::string& name,
4500   std::vector<cmCustomCommand> const& commands, std::string const& configName)
4501 {
4502   if (commands.empty()) {
4503     return;
4504   }
4505   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
4506   std::string script;
4507   const char* pre = "";
4508   std::string comment;
4509   bool stdPipesUTF8 = false;
4510   for (cmCustomCommand const& cc : commands) {
4511     cmCustomCommandGenerator ccg(cc, configName, lg);
4512     if (!ccg.HasOnlyEmptyCommandLines()) {
4513       comment += pre;
4514       comment += lg->ConstructComment(ccg);
4515       script += pre;
4516       pre = "\n";
4517       script += lg->ConstructScript(ccg);
4518
4519       stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8();
4520     }
4521   }
4522   if (!script.empty()) {
4523     script += lg->FinishConstructScript(this->ProjectType);
4524   }
4525   comment = cmVS10EscapeComment(comment);
4526   if (this->ProjectType != VsProjectType::csproj) {
4527     Elem e2(e1, name);
4528     if (stdPipesUTF8) {
4529       this->WriteStdOutEncodingUtf8(e2);
4530     }
4531     e2.Element("Message", comment);
4532     e2.Element("Command", script);
4533   } else {
4534     std::string strippedComment = comment;
4535     strippedComment.erase(
4536       std::remove(strippedComment.begin(), strippedComment.end(), '\t'),
4537       strippedComment.end());
4538     std::ostringstream oss;
4539     if (!comment.empty() && !strippedComment.empty()) {
4540       oss << "echo " << comment << "\n";
4541     }
4542     oss << script << "\n";
4543     e1.Element(name, oss.str());
4544   }
4545 }
4546
4547 void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
4548 {
4549   cmGlobalGenerator::TargetDependSet const& unordered =
4550     this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
4551   using OrderedTargetDependSet =
4552     cmGlobalVisualStudioGenerator::OrderedTargetDependSet;
4553   OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
4554   Elem e1(e0, "ItemGroup");
4555   e1.SetHasElements();
4556   for (cmGeneratorTarget const* dt : depends) {
4557     if (!dt->IsInBuildSystem()) {
4558       continue;
4559     }
4560     // skip fortran targets as they can not be processed by MSBuild
4561     // the only reference will be in the .sln file
4562     if (this->GlobalGenerator->TargetIsFortranOnly(dt)) {
4563       continue;
4564     }
4565     cmLocalGenerator* lg = dt->GetLocalGenerator();
4566     std::string name = dt->GetName();
4567     std::string path;
4568     if (cmValue p = dt->GetProperty("EXTERNAL_MSPROJECT")) {
4569       path = *p;
4570     } else {
4571       path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(),
4572                       computeProjectFileExtension(dt));
4573     }
4574     ConvertToWindowsSlash(path);
4575     Elem e2(e1, "ProjectReference");
4576     e2.Attribute("Include", path);
4577     e2.Element("Project", "{" + this->GlobalGenerator->GetGUID(name) + "}");
4578     e2.Element("Name", name);
4579     this->WriteDotNetReferenceCustomTags(e2, name);
4580     if (dt->IsCSharpOnly() || cmHasLiteralSuffix(path, "csproj")) {
4581       e2.Element("SkipGetTargetFrameworkProperties", "true");
4582     }
4583     // Don't reference targets that don't produce any output.
4584     else if (this->Configurations.empty() ||
4585              dt->GetManagedType(this->Configurations[0]) ==
4586                cmGeneratorTarget::ManagedType::Undefined) {
4587       e2.Element("ReferenceOutputAssembly", "false");
4588       e2.Element("CopyToOutputDirectory", "Never");
4589     }
4590   }
4591 }
4592
4593 void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1)
4594 {
4595   // This only applies to Windows 10 apps
4596   if (this->GlobalGenerator->TargetsWindowsStore() &&
4597       cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
4598     cmValue desktopExtensionsVersion =
4599       this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
4600     if (desktopExtensionsVersion) {
4601       this->WriteSinglePlatformExtension(e1, "WindowsDesktop",
4602                                          *desktopExtensionsVersion);
4603     }
4604     cmValue mobileExtensionsVersion =
4605       this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
4606     if (mobileExtensionsVersion) {
4607       this->WriteSinglePlatformExtension(e1, "WindowsMobile",
4608                                          *mobileExtensionsVersion);
4609     }
4610   }
4611 }
4612
4613 void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension(
4614   Elem& e1, std::string const& extension, std::string const& version)
4615 {
4616   const std::string s = "$([Microsoft.Build.Utilities.ToolLocationHelper]"
4617                         "::GetPlatformExtensionSDKLocation(`" +
4618     extension + ", Version=" + version +
4619     "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
4620     "$(ExtensionSDKDirectoryRoot), null))"
4621     "\\DesignTime\\CommonConfiguration\\Neutral\\" +
4622     extension + ".props";
4623
4624   Elem e2(e1, "Import");
4625   e2.Attribute("Project", s);
4626   e2.Attribute("Condition", "exists('" + s + "')");
4627 }
4628
4629 void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
4630 {
4631   std::vector<std::string> sdkReferences;
4632   std::unique_ptr<Elem> spe1;
4633   if (cmValue vsSDKReferences =
4634         this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) {
4635     cmExpandList(*vsSDKReferences, sdkReferences);
4636     spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
4637     for (std::string const& ri : sdkReferences) {
4638       Elem(*spe1, "SDKReference").Attribute("Include", ri);
4639     }
4640   }
4641
4642   // This only applies to Windows 10 apps
4643   if (this->GlobalGenerator->TargetsWindowsStore() &&
4644       cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
4645     cmValue desktopExtensionsVersion =
4646       this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
4647     cmValue mobileExtensionsVersion =
4648       this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
4649     cmValue iotExtensionsVersion =
4650       this->GeneratorTarget->GetProperty("VS_IOT_EXTENSIONS_VERSION");
4651
4652     if (desktopExtensionsVersion || mobileExtensionsVersion ||
4653         iotExtensionsVersion) {
4654       if (!spe1) {
4655         spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
4656       }
4657       if (desktopExtensionsVersion) {
4658         this->WriteSingleSDKReference(*spe1, "WindowsDesktop",
4659                                       *desktopExtensionsVersion);
4660       }
4661       if (mobileExtensionsVersion) {
4662         this->WriteSingleSDKReference(*spe1, "WindowsMobile",
4663                                       *mobileExtensionsVersion);
4664       }
4665       if (iotExtensionsVersion) {
4666         this->WriteSingleSDKReference(*spe1, "WindowsIoT",
4667                                       *iotExtensionsVersion);
4668       }
4669     }
4670   }
4671 }
4672
4673 void cmVisualStudio10TargetGenerator::WriteSingleSDKReference(
4674   Elem& e1, std::string const& extension, std::string const& version)
4675 {
4676   Elem(e1, "SDKReference")
4677     .Attribute("Include", extension + ", Version=" + version);
4678 }
4679
4680 void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
4681   Elem& e0)
4682 {
4683   if ((this->GlobalGenerator->TargetsWindowsStore() ||
4684        this->GlobalGenerator->TargetsWindowsPhone()) &&
4685       (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType())) {
4686     std::string pfxFile;
4687     for (cmGeneratorTarget::AllConfigSource const& source :
4688          this->GeneratorTarget->GetAllConfigSources()) {
4689       if (source.Kind == cmGeneratorTarget::SourceKindCertificate) {
4690         pfxFile = this->ConvertPath(source.Source->GetFullPath(), false);
4691         ConvertToWindowsSlash(pfxFile);
4692         break;
4693       }
4694     }
4695
4696     if (this->IsMissingFiles &&
4697         !(this->GlobalGenerator->TargetsWindowsPhone() &&
4698           this->GlobalGenerator->GetSystemVersion() == "8.0")) {
4699       // Move the manifest to a project directory to avoid clashes
4700       std::string artifactDir =
4701         this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
4702       ConvertToWindowsSlash(artifactDir);
4703       Elem e1(e0, "PropertyGroup");
4704       e1.Element("AppxPackageArtifactsDir", artifactDir + "\\");
4705       std::string resourcePriFile =
4706         this->DefaultArtifactDir + "/resources.pri";
4707       ConvertToWindowsSlash(resourcePriFile);
4708       e1.Element("ProjectPriFullPath", resourcePriFile);
4709
4710       // If we are missing files and we don't have a certificate and
4711       // aren't targeting WP8.0, add a default certificate
4712       if (pfxFile.empty()) {
4713         std::string templateFolder =
4714           cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
4715         pfxFile = this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
4716         cmSystemTools::CopyAFile(templateFolder + "/Windows_TemporaryKey.pfx",
4717                                  pfxFile, false);
4718         ConvertToWindowsSlash(pfxFile);
4719         this->AddedFiles.push_back(pfxFile);
4720         this->AddedDefaultCertificate = true;
4721       }
4722
4723       e1.Element("PackageCertificateKeyFile", pfxFile);
4724       std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
4725       if (!thumb.empty()) {
4726         e1.Element("PackageCertificateThumbprint", thumb);
4727       }
4728     } else if (!pfxFile.empty()) {
4729       Elem e1(e0, "PropertyGroup");
4730       e1.Element("PackageCertificateKeyFile", pfxFile);
4731       std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
4732       if (!thumb.empty()) {
4733         e1.Element("PackageCertificateThumbprint", thumb);
4734       }
4735     }
4736   }
4737 }
4738
4739 void cmVisualStudio10TargetGenerator::ClassifyAllConfigSources()
4740 {
4741   for (cmGeneratorTarget::AllConfigSource const& source :
4742        this->GeneratorTarget->GetAllConfigSources()) {
4743     this->ClassifyAllConfigSource(source);
4744   }
4745 }
4746
4747 void cmVisualStudio10TargetGenerator::ClassifyAllConfigSource(
4748   cmGeneratorTarget::AllConfigSource const& acs)
4749 {
4750   switch (acs.Kind) {
4751     case cmGeneratorTarget::SourceKindResx: {
4752       // Build and save the name of the corresponding .h file
4753       // This relationship will be used later when building the project files.
4754       // Both names would have been auto generated from Visual Studio
4755       // where the user supplied the file name and Visual Studio
4756       // appended the suffix.
4757       std::string resx = acs.Source->ResolveFullPath();
4758       std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
4759       this->ExpectedResxHeaders.insert(hFileName);
4760     } break;
4761     case cmGeneratorTarget::SourceKindXaml: {
4762       // Build and save the name of the corresponding .h and .cpp file
4763       // This relationship will be used later when building the project files.
4764       // Both names would have been auto generated from Visual Studio
4765       // where the user supplied the file name and Visual Studio
4766       // appended the suffix.
4767       std::string xaml = acs.Source->ResolveFullPath();
4768       std::string hFileName = xaml + ".h";
4769       std::string cppFileName = xaml + ".cpp";
4770       this->ExpectedXamlHeaders.insert(hFileName);
4771       this->ExpectedXamlSources.insert(cppFileName);
4772     } break;
4773     default:
4774       break;
4775   }
4776 }
4777
4778 bool cmVisualStudio10TargetGenerator::IsResxHeader(
4779   const std::string& headerFile)
4780 {
4781   return this->ExpectedResxHeaders.count(headerFile) > 0;
4782 }
4783
4784 bool cmVisualStudio10TargetGenerator::IsXamlHeader(
4785   const std::string& headerFile)
4786 {
4787   return this->ExpectedXamlHeaders.count(headerFile) > 0;
4788 }
4789
4790 bool cmVisualStudio10TargetGenerator::IsXamlSource(
4791   const std::string& sourceFile)
4792 {
4793   return this->ExpectedXamlSources.count(sourceFile) > 0;
4794 }
4795
4796 void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
4797 {
4798   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
4799   bool isAppContainer = false;
4800   bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
4801   bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
4802   bool const isAndroid = this->GlobalGenerator->TargetsAndroid();
4803   std::string const& rev = this->GlobalGenerator->GetApplicationTypeRevision();
4804   if (isWindowsPhone || isWindowsStore) {
4805     e1.Element("ApplicationType",
4806                (isWindowsPhone ? "Windows Phone" : "Windows Store"));
4807     e1.Element("DefaultLanguage", "en-US");
4808     if (rev == "10.0") {
4809       e1.Element("ApplicationTypeRevision", rev);
4810       // Visual Studio 14.0 is necessary for building 10.0 apps
4811       e1.Element("MinimumVisualStudioVersion", "14.0");
4812
4813       if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
4814         isAppContainer = true;
4815       }
4816     } else if (rev == "8.1") {
4817       e1.Element("ApplicationTypeRevision", rev);
4818       // Visual Studio 12.0 is necessary for building 8.1 apps
4819       e1.Element("MinimumVisualStudioVersion", "12.0");
4820
4821       if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
4822         isAppContainer = true;
4823       }
4824     } else if (rev == "8.0") {
4825       e1.Element("ApplicationTypeRevision", rev);
4826       // Visual Studio 11.0 is necessary for building 8.0 apps
4827       e1.Element("MinimumVisualStudioVersion", "11.0");
4828
4829       if (isWindowsStore &&
4830           this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
4831         isAppContainer = true;
4832       } else if (isWindowsPhone &&
4833                  this->GeneratorTarget->GetType() ==
4834                    cmStateEnums::EXECUTABLE) {
4835         e1.Element("XapOutputs", "true");
4836         e1.Element("XapFilename",
4837                    this->Name + "_$(Configuration)_$(Platform).xap");
4838       }
4839     }
4840   } else if (isAndroid) {
4841     e1.Element("ApplicationType", "Android");
4842     e1.Element("ApplicationTypeRevision",
4843                gg->GetAndroidApplicationTypeRevision());
4844   }
4845   if (isAppContainer) {
4846     e1.Element("AppContainerApplication", "true");
4847   } else if (!isAndroid) {
4848     if (this->Platform == "ARM64") {
4849       e1.Element("WindowsSDKDesktopARM64Support", "true");
4850     } else if (this->Platform == "ARM") {
4851       e1.Element("WindowsSDKDesktopARMSupport", "true");
4852     }
4853   }
4854   std::string const& targetPlatformVersion =
4855     gg->GetWindowsTargetPlatformVersion();
4856   if (!targetPlatformVersion.empty()) {
4857     e1.Element("WindowsTargetPlatformVersion", targetPlatformVersion);
4858   }
4859   cmValue targetPlatformMinVersion = this->GeneratorTarget->GetProperty(
4860     "VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION");
4861   if (targetPlatformMinVersion) {
4862     e1.Element("WindowsTargetPlatformMinVersion", *targetPlatformMinVersion);
4863   } else if (isWindowsStore && rev == "10.0") {
4864     // If the min version is not set, then use the TargetPlatformVersion
4865     if (!targetPlatformVersion.empty()) {
4866       e1.Element("WindowsTargetPlatformMinVersion", targetPlatformVersion);
4867     }
4868   }
4869
4870   // Added IoT Startup Task support
4871   if (this->GeneratorTarget->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) {
4872     e1.Element("ContainsStartupTask", "true");
4873   }
4874 }
4875
4876 void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles()
4877 {
4878   // For Windows and Windows Phone executables, we will assume that if a
4879   // manifest is not present that we need to add all the necessary files
4880   if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4881     std::vector<cmGeneratorTarget::AllConfigSource> manifestSources =
4882       this->GeneratorTarget->GetAllConfigSources(
4883         cmGeneratorTarget::SourceKindAppManifest);
4884     std::string const& v = this->GlobalGenerator->GetSystemVersion();
4885     if (this->GlobalGenerator->TargetsWindowsPhone()) {
4886       if (v == "8.0") {
4887         // Look through the sources for WMAppManifest.xml
4888         bool foundManifest = false;
4889         for (cmGeneratorTarget::AllConfigSource const& source :
4890              this->GeneratorTarget->GetAllConfigSources()) {
4891           if (source.Kind == cmGeneratorTarget::SourceKindExtra &&
4892               "wmappmanifest.xml" ==
4893                 cmSystemTools::LowerCase(
4894                   source.Source->GetLocation().GetName())) {
4895             foundManifest = true;
4896             break;
4897           }
4898         }
4899         if (!foundManifest) {
4900           this->IsMissingFiles = true;
4901         }
4902       } else if (v == "8.1") {
4903         if (manifestSources.empty()) {
4904           this->IsMissingFiles = true;
4905         }
4906       }
4907     } else if (this->GlobalGenerator->TargetsWindowsStore()) {
4908       if (manifestSources.empty()) {
4909         if (v == "8.0") {
4910           this->IsMissingFiles = true;
4911         } else if (v == "8.1" || cmHasLiteralPrefix(v, "10.0")) {
4912           this->IsMissingFiles = true;
4913         }
4914       }
4915     }
4916   }
4917 }
4918
4919 void cmVisualStudio10TargetGenerator::WriteMissingFiles(Elem& e1)
4920 {
4921   std::string const& v = this->GlobalGenerator->GetSystemVersion();
4922   if (this->GlobalGenerator->TargetsWindowsPhone()) {
4923     if (v == "8.0") {
4924       this->WriteMissingFilesWP80(e1);
4925     } else if (v == "8.1") {
4926       this->WriteMissingFilesWP81(e1);
4927     }
4928   } else if (this->GlobalGenerator->TargetsWindowsStore()) {
4929     if (v == "8.0") {
4930       this->WriteMissingFilesWS80(e1);
4931     } else if (v == "8.1") {
4932       this->WriteMissingFilesWS81(e1);
4933     } else if (cmHasLiteralPrefix(v, "10.0")) {
4934       this->WriteMissingFilesWS10_0(e1);
4935     }
4936   }
4937 }
4938
4939 void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1)
4940 {
4941   std::string templateFolder =
4942     cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
4943
4944   // For WP80, the manifest needs to be in the same folder as the project
4945   // this can cause an overwrite problem if projects aren't organized in
4946   // folders
4947   std::string manifestFile =
4948     this->LocalGenerator->GetCurrentBinaryDirectory() + "/WMAppManifest.xml";
4949   std::string artifactDir =
4950     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
4951   ConvertToWindowsSlash(artifactDir);
4952   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
4953   std::string targetNameXML =
4954     cmVS10EscapeXML(this->GeneratorTarget->GetName());
4955
4956   cmGeneratedFileStream fout(manifestFile);
4957   fout.SetCopyIfDifferent(true);
4958
4959   /* clang-format off */
4960   fout <<
4961     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
4962     "<Deployment"
4963     " xmlns=\"http://schemas.microsoft.com/windowsphone/2012/deployment\""
4964     " AppPlatformVersion=\"8.0\">\n"
4965     "\t<DefaultLanguage xmlns=\"\" code=\"en-US\"/>\n"
4966     "\t<App xmlns=\"\" ProductID=\"{" << this->GUID << "}\""
4967     " Title=\"CMake Test Program\" RuntimeType=\"Modern Native\""
4968     " Version=\"1.0.0.0\" Genre=\"apps.normal\"  Author=\"CMake\""
4969     " Description=\"Default CMake App\" Publisher=\"CMake\""
4970     " PublisherID=\"{" << this->GUID << "}\">\n"
4971     "\t\t<IconPath IsRelative=\"true\" IsResource=\"false\">"
4972        << artifactDirXML << "\\ApplicationIcon.png</IconPath>\n"
4973     "\t\t<Capabilities/>\n"
4974     "\t\t<Tasks>\n"
4975     "\t\t\t<DefaultTask Name=\"_default\""
4976     " ImagePath=\"" << targetNameXML << ".exe\" ImageParams=\"\" />\n"
4977     "\t\t</Tasks>\n"
4978     "\t\t<Tokens>\n"
4979     "\t\t\t<PrimaryToken TokenID=\"" << targetNameXML << "Token\""
4980     " TaskName=\"_default\">\n"
4981     "\t\t\t\t<TemplateFlip>\n"
4982     "\t\t\t\t\t<SmallImageURI IsRelative=\"true\" IsResource=\"false\">"
4983        << artifactDirXML << "\\SmallLogo.png</SmallImageURI>\n"
4984     "\t\t\t\t\t<Count>0</Count>\n"
4985     "\t\t\t\t\t<BackgroundImageURI IsRelative=\"true\" IsResource=\"false\">"
4986        << artifactDirXML << "\\Logo.png</BackgroundImageURI>\n"
4987     "\t\t\t\t</TemplateFlip>\n"
4988     "\t\t\t</PrimaryToken>\n"
4989     "\t\t</Tokens>\n"
4990     "\t\t<ScreenResolutions>\n"
4991     "\t\t\t<ScreenResolution Name=\"ID_RESOLUTION_WVGA\" />\n"
4992     "\t\t</ScreenResolutions>\n"
4993     "\t</App>\n"
4994     "</Deployment>\n";
4995   /* clang-format on */
4996
4997   std::string sourceFile = this->ConvertPath(manifestFile, false);
4998   ConvertToWindowsSlash(sourceFile);
4999   {
5000     Elem e2(e1, "Xml");
5001     e2.Attribute("Include", sourceFile);
5002     e2.Element("SubType", "Designer");
5003   }
5004   this->AddedFiles.push_back(sourceFile);
5005
5006   std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
5007   cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
5008                            false);
5009   ConvertToWindowsSlash(smallLogo);
5010   Elem(e1, "Image").Attribute("Include", smallLogo);
5011   this->AddedFiles.push_back(smallLogo);
5012
5013   std::string logo = this->DefaultArtifactDir + "/Logo.png";
5014   cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
5015   ConvertToWindowsSlash(logo);
5016   Elem(e1, "Image").Attribute("Include", logo);
5017   this->AddedFiles.push_back(logo);
5018
5019   std::string applicationIcon =
5020     this->DefaultArtifactDir + "/ApplicationIcon.png";
5021   cmSystemTools::CopyAFile(templateFolder + "/ApplicationIcon.png",
5022                            applicationIcon, false);
5023   ConvertToWindowsSlash(applicationIcon);
5024   Elem(e1, "Image").Attribute("Include", applicationIcon);
5025   this->AddedFiles.push_back(applicationIcon);
5026 }
5027
5028 void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81(Elem& e1)
5029 {
5030   std::string manifestFile =
5031     this->DefaultArtifactDir + "/package.appxManifest";
5032   std::string artifactDir =
5033     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
5034   ConvertToWindowsSlash(artifactDir);
5035   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
5036   std::string targetNameXML =
5037     cmVS10EscapeXML(this->GeneratorTarget->GetName());
5038
5039   cmGeneratedFileStream fout(manifestFile);
5040   fout.SetCopyIfDifferent(true);
5041
5042   /* clang-format off */
5043   fout <<
5044     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
5045     "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\""
5046     " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\""
5047     " xmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\">\n"
5048     "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
5049     " Version=\"1.0.0.0\" />\n"
5050     "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID << "\""
5051     " PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n"
5052     "\t<Properties>\n"
5053     "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
5054     "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
5055     "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
5056     "\t</Properties>\n"
5057     "\t<Prerequisites>\n"
5058     "\t\t<OSMinVersion>6.3.1</OSMinVersion>\n"
5059     "\t\t<OSMaxVersionTested>6.3.1</OSMaxVersionTested>\n"
5060     "\t</Prerequisites>\n"
5061     "\t<Resources>\n"
5062     "\t\t<Resource Language=\"x-generate\" />\n"
5063     "\t</Resources>\n"
5064     "\t<Applications>\n"
5065     "\t\t<Application Id=\"App\""
5066     " Executable=\"" << targetNameXML << ".exe\""
5067     " EntryPoint=\"" << targetNameXML << ".App\">\n"
5068     "\t\t\t<m2:VisualElements\n"
5069     "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
5070     "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
5071     "\t\t\t\tBackgroundColor=\"#336699\"\n"
5072     "\t\t\t\tForegroundText=\"light\"\n"
5073     "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
5074     "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
5075     "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n"
5076     "\t\t\t\t\t<m2:ShowNameOnTiles>\n"
5077     "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n"
5078     "\t\t\t\t\t</m2:ShowNameOnTiles>\n"
5079     "\t\t\t\t</m2:DefaultTile>\n"
5080     "\t\t\t\t<m2:SplashScreen"
5081     " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
5082     "\t\t\t</m2:VisualElements>\n"
5083     "\t\t</Application>\n"
5084     "\t</Applications>\n"
5085     "</Package>\n";
5086   /* clang-format on */
5087
5088   this->WriteCommonMissingFiles(e1, manifestFile);
5089 }
5090
5091 void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80(Elem& e1)
5092 {
5093   std::string manifestFile =
5094     this->DefaultArtifactDir + "/package.appxManifest";
5095   std::string artifactDir =
5096     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
5097   ConvertToWindowsSlash(artifactDir);
5098   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
5099   std::string targetNameXML =
5100     cmVS10EscapeXML(this->GeneratorTarget->GetName());
5101
5102   cmGeneratedFileStream fout(manifestFile);
5103   fout.SetCopyIfDifferent(true);
5104
5105   /* clang-format off */
5106   fout <<
5107     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
5108     "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\">\n"
5109     "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
5110     " Version=\"1.0.0.0\" />\n"
5111     "\t<Properties>\n"
5112     "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
5113     "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
5114     "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
5115     "\t</Properties>\n"
5116     "\t<Prerequisites>\n"
5117     "\t\t<OSMinVersion>6.2.1</OSMinVersion>\n"
5118     "\t\t<OSMaxVersionTested>6.2.1</OSMaxVersionTested>\n"
5119     "\t</Prerequisites>\n"
5120     "\t<Resources>\n"
5121     "\t\t<Resource Language=\"x-generate\" />\n"
5122     "\t</Resources>\n"
5123     "\t<Applications>\n"
5124     "\t\t<Application Id=\"App\""
5125     " Executable=\"" << targetNameXML << ".exe\""
5126     " EntryPoint=\"" << targetNameXML << ".App\">\n"
5127     "\t\t\t<VisualElements"
5128     " DisplayName=\"" << targetNameXML << "\""
5129     " Description=\"" << targetNameXML << "\""
5130     " BackgroundColor=\"#336699\" ForegroundText=\"light\""
5131     " Logo=\"" << artifactDirXML << "\\Logo.png\""
5132     " SmallLogo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
5133     "\t\t\t\t<DefaultTile ShowName=\"allLogos\""
5134     " ShortName=\"" << targetNameXML << "\" />\n"
5135     "\t\t\t\t<SplashScreen"
5136     " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
5137     "\t\t\t</VisualElements>\n"
5138     "\t\t</Application>\n"
5139     "\t</Applications>\n"
5140     "</Package>\n";
5141   /* clang-format on */
5142
5143   this->WriteCommonMissingFiles(e1, manifestFile);
5144 }
5145
5146 void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81(Elem& e1)
5147 {
5148   std::string manifestFile =
5149     this->DefaultArtifactDir + "/package.appxManifest";
5150   std::string artifactDir =
5151     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
5152   ConvertToWindowsSlash(artifactDir);
5153   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
5154   std::string targetNameXML =
5155     cmVS10EscapeXML(this->GeneratorTarget->GetName());
5156
5157   cmGeneratedFileStream fout(manifestFile);
5158   fout.SetCopyIfDifferent(true);
5159
5160   /* clang-format off */
5161   fout <<
5162     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
5163     "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\""
5164     " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\">\n"
5165     "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
5166     " Version=\"1.0.0.0\" />\n"
5167     "\t<Properties>\n"
5168     "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
5169     "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
5170     "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
5171     "\t</Properties>\n"
5172     "\t<Prerequisites>\n"
5173     "\t\t<OSMinVersion>6.3</OSMinVersion>\n"
5174     "\t\t<OSMaxVersionTested>6.3</OSMaxVersionTested>\n"
5175     "\t</Prerequisites>\n"
5176     "\t<Resources>\n"
5177     "\t\t<Resource Language=\"x-generate\" />\n"
5178     "\t</Resources>\n"
5179     "\t<Applications>\n"
5180     "\t\t<Application Id=\"App\""
5181     " Executable=\"" << targetNameXML << ".exe\""
5182     " EntryPoint=\"" << targetNameXML << ".App\">\n"
5183     "\t\t\t<m2:VisualElements\n"
5184     "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
5185     "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
5186     "\t\t\t\tBackgroundColor=\"#336699\"\n"
5187     "\t\t\t\tForegroundText=\"light\"\n"
5188     "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
5189     "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
5190     "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n"
5191     "\t\t\t\t\t<m2:ShowNameOnTiles>\n"
5192     "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n"
5193     "\t\t\t\t\t</m2:ShowNameOnTiles>\n"
5194     "\t\t\t\t</m2:DefaultTile>\n"
5195     "\t\t\t\t<m2:SplashScreen"
5196     " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
5197     "\t\t\t</m2:VisualElements>\n"
5198     "\t\t</Application>\n"
5199     "\t</Applications>\n"
5200     "</Package>\n";
5201   /* clang-format on */
5202
5203   this->WriteCommonMissingFiles(e1, manifestFile);
5204 }
5205
5206 void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0(Elem& e1)
5207 {
5208   std::string manifestFile =
5209     this->DefaultArtifactDir + "/package.appxManifest";
5210   std::string artifactDir =
5211     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
5212   ConvertToWindowsSlash(artifactDir);
5213   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
5214   std::string targetNameXML =
5215     cmVS10EscapeXML(this->GeneratorTarget->GetName());
5216
5217   cmGeneratedFileStream fout(manifestFile);
5218   fout.SetCopyIfDifferent(true);
5219
5220   /* clang-format off */
5221   fout <<
5222     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
5223     "<Package\n\t"
5224     "xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\""
5225     "\txmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\"\n"
5226     "\txmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\""
5227     "\n\tIgnorableNamespaces=\"uap mp\">\n\n"
5228     "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
5229     " Version=\"1.0.0.0\" />\n"
5230     "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID <<
5231     "\" PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n"
5232     "\t<Properties>\n"
5233     "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
5234     "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
5235     "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
5236     "\t</Properties>\n"
5237     "\t<Dependencies>\n"
5238     "\t\t<TargetDeviceFamily Name=\"Windows.Universal\" "
5239     "MinVersion=\"10.0.0.0\" MaxVersionTested=\"10.0.0.0\" />\n"
5240     "\t</Dependencies>\n"
5241
5242     "\t<Resources>\n"
5243     "\t\t<Resource Language=\"x-generate\" />\n"
5244     "\t</Resources>\n"
5245     "\t<Applications>\n"
5246     "\t\t<Application Id=\"App\""
5247     " Executable=\"" << targetNameXML << ".exe\""
5248     " EntryPoint=\"" << targetNameXML << ".App\">\n"
5249     "\t\t\t<uap:VisualElements\n"
5250     "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
5251     "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
5252     "\t\t\t\tBackgroundColor=\"#336699\"\n"
5253     "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
5254     "\t\t\t\tSquare44x44Logo=\"" << artifactDirXML <<
5255     "\\SmallLogo44x44.png\">\n"
5256     "\t\t\t\t<uap:SplashScreen"
5257     " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
5258     "\t\t\t</uap:VisualElements>\n"
5259     "\t\t</Application>\n"
5260     "\t</Applications>\n"
5261     "</Package>\n";
5262   /* clang-format on */
5263
5264   this->WriteCommonMissingFiles(e1, manifestFile);
5265 }
5266
5267 void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
5268   Elem& e1, const std::string& manifestFile)
5269 {
5270   std::string templateFolder =
5271     cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
5272
5273   std::string sourceFile = this->ConvertPath(manifestFile, false);
5274   ConvertToWindowsSlash(sourceFile);
5275   {
5276     Elem e2(e1, "AppxManifest");
5277     e2.Attribute("Include", sourceFile);
5278     e2.Element("SubType", "Designer");
5279   }
5280   this->AddedFiles.push_back(sourceFile);
5281
5282   std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
5283   cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
5284                            false);
5285   ConvertToWindowsSlash(smallLogo);
5286   Elem(e1, "Image").Attribute("Include", smallLogo);
5287   this->AddedFiles.push_back(smallLogo);
5288
5289   std::string smallLogo44 = this->DefaultArtifactDir + "/SmallLogo44x44.png";
5290   cmSystemTools::CopyAFile(templateFolder + "/SmallLogo44x44.png", smallLogo44,
5291                            false);
5292   ConvertToWindowsSlash(smallLogo44);
5293   Elem(e1, "Image").Attribute("Include", smallLogo44);
5294   this->AddedFiles.push_back(smallLogo44);
5295
5296   std::string logo = this->DefaultArtifactDir + "/Logo.png";
5297   cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
5298   ConvertToWindowsSlash(logo);
5299   Elem(e1, "Image").Attribute("Include", logo);
5300   this->AddedFiles.push_back(logo);
5301
5302   std::string storeLogo = this->DefaultArtifactDir + "/StoreLogo.png";
5303   cmSystemTools::CopyAFile(templateFolder + "/StoreLogo.png", storeLogo,
5304                            false);
5305   ConvertToWindowsSlash(storeLogo);
5306   Elem(e1, "Image").Attribute("Include", storeLogo);
5307   this->AddedFiles.push_back(storeLogo);
5308
5309   std::string splashScreen = this->DefaultArtifactDir + "/SplashScreen.png";
5310   cmSystemTools::CopyAFile(templateFolder + "/SplashScreen.png", splashScreen,
5311                            false);
5312   ConvertToWindowsSlash(splashScreen);
5313   Elem(e1, "Image").Attribute("Include", splashScreen);
5314   this->AddedFiles.push_back(splashScreen);
5315
5316   if (this->AddedDefaultCertificate) {
5317     // This file has already been added to the build so don't copy it
5318     std::string keyFile =
5319       this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
5320     ConvertToWindowsSlash(keyFile);
5321     Elem(e1, "None").Attribute("Include", keyFile);
5322   }
5323 }
5324
5325 bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const
5326 {
5327   HANDLE h =
5328     CreateFileW(cmSystemTools::ConvertToWindowsExtendedPath(source).c_str(),
5329                 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING,
5330                 FILE_FLAG_BACKUP_SEMANTICS, 0);
5331   if (!h) {
5332     return false;
5333   }
5334
5335   FILETIME const ftime_20010101 = { 3365781504u, 29389701u };
5336   if (!SetFileTime(h, &ftime_20010101, &ftime_20010101, &ftime_20010101)) {
5337     CloseHandle(h);
5338     return false;
5339   }
5340
5341   CloseHandle(h);
5342   return true;
5343 }
5344
5345 void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties(
5346   cmSourceFile const* sf, std::map<std::string, std::string>& tags)
5347 {
5348   if (this->ProjectType == VsProjectType::csproj) {
5349     const cmPropertyMap& props = sf->GetProperties();
5350     for (const std::string& p : props.GetKeys()) {
5351       static const cm::string_view propNamePrefix = "VS_CSHARP_";
5352       if (cmHasPrefix(p, propNamePrefix)) {
5353         std::string tagName = p.substr(propNamePrefix.length());
5354         if (!tagName.empty()) {
5355           cmValue val = props.GetPropertyValue(p);
5356           if (cmNonempty(val)) {
5357             tags[tagName] = *val;
5358           } else {
5359             tags.erase(tagName);
5360           }
5361         }
5362       }
5363     }
5364   }
5365 }
5366
5367 void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties(
5368   Elem& e2, const std::map<std::string, std::string>& tags)
5369 {
5370   for (const auto& i : tags) {
5371     e2.Element(i.first, i.second);
5372   }
5373 }
5374
5375 std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
5376   cmSourceFile const* source)
5377 {
5378   // For out of source files, we first check if a matching source group
5379   // for this file exists, otherwise we check if the path relative to current
5380   // source- or binary-dir is used within the link and return that.
5381   // In case of .cs files we can't do that automatically for files in the
5382   // binary directory, because this leads to compilation errors.
5383   std::string link;
5384   std::string sourceGroupedFile;
5385   std::string const& fullFileName = source->GetFullPath();
5386   std::string const& srcDir = this->Makefile->GetCurrentSourceDirectory();
5387   std::string const& binDir = this->Makefile->GetCurrentBinaryDirectory();
5388   // unfortunately we have to copy the source groups, because
5389   // FindSourceGroup uses a regex which is modifying the group
5390   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
5391   cmSourceGroup* sourceGroup =
5392     this->Makefile->FindSourceGroup(fullFileName, sourceGroups);
5393   if (sourceGroup && !sourceGroup->GetFullName().empty()) {
5394     sourceGroupedFile = sourceGroup->GetFullName() + "/" +
5395       cmsys::SystemTools::GetFilenameName(fullFileName);
5396     cmsys::SystemTools::ConvertToUnixSlashes(sourceGroupedFile);
5397   }
5398
5399   if (!sourceGroupedFile.empty() &&
5400       cmHasSuffix(fullFileName, sourceGroupedFile)) {
5401     link = sourceGroupedFile;
5402   } else if (cmHasPrefix(fullFileName, srcDir)) {
5403     link = fullFileName.substr(srcDir.length() + 1);
5404   } else if (!cmHasSuffix(fullFileName, ".cs") &&
5405              cmHasPrefix(fullFileName, binDir)) {
5406     link = fullFileName.substr(binDir.length() + 1);
5407   } else if (cmValue l = source->GetProperty("VS_CSHARP_Link")) {
5408     link = *l;
5409   }
5410
5411   ConvertToWindowsSlash(link);
5412   return link;
5413 }
5414
5415 std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
5416   const char* relativeFilePath) const
5417 {
5418   // Always search in the standard modules location.
5419   std::string path =
5420     cmStrCat(cmSystemTools::GetCMakeRoot(), '/', relativeFilePath);
5421   ConvertToWindowsSlash(path);
5422
5423   return path;
5424 }
5425
5426 void cmVisualStudio10TargetGenerator::WriteStdOutEncodingUtf8(Elem& e1)
5427 {
5428   if (this->GlobalGenerator->IsUtf8EncodingSupported()) {
5429     e1.Element("UseUtf8Encoding", "Always");
5430   } else if (this->GlobalGenerator->IsStdOutEncodingSupported()) {
5431     e1.Element("StdOutEncoding", "UTF-8");
5432   }
5433 }
5434
5435 void cmVisualStudio10TargetGenerator::UpdateCache()
5436 {
5437   std::vector<std::string> packageReferences;
5438
5439   if (this->GeneratorTarget->HasPackageReferences()) {
5440     // Store a cache entry that later determines, if a package restore is
5441     // required.
5442     this->GeneratorTarget->Makefile->AddCacheDefinition(
5443       this->GeneratorTarget->GetName() + "_REQUIRES_VS_PACKAGE_RESTORE", "ON",
5444       "Value Computed by CMake", cmStateEnums::STATIC);
5445   } else {
5446     // If there are any dependencies that require package restore, inherit the
5447     // cache variable.
5448     cmGlobalGenerator::TargetDependSet const& unordered =
5449       this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
5450     using OrderedTargetDependSet =
5451       cmGlobalVisualStudioGenerator::OrderedTargetDependSet;
5452     OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
5453
5454     for (cmGeneratorTarget const* dt : depends) {
5455       if (dt->HasPackageReferences()) {
5456         this->GeneratorTarget->Makefile->AddCacheDefinition(
5457           this->GeneratorTarget->GetName() + "_REQUIRES_VS_PACKAGE_RESTORE",
5458           "ON", "Value Computed by CMake", cmStateEnums::STATIC);
5459       }
5460     }
5461   }
5462 }