resolve cyclic dependency with zstd
[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   // MSBuild enables debug information by default.
3773   // Disable it explicitly unless a flag parsed below re-enables it.
3774   masmOptions.AddFlag("GenerateDebugInformation", "false");
3775
3776   std::string flags;
3777   this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
3778                                          cmBuildStep::Compile, "ASM_MASM",
3779                                          configName);
3780
3781   masmOptions.Parse(flags);
3782
3783   // Get includes for this target
3784   masmOptions.AddIncludes(this->GetIncludes(configName, "ASM_MASM"));
3785
3786   this->MasmOptions[configName] = std::move(pOptions);
3787   return true;
3788 }
3789
3790 void cmVisualStudio10TargetGenerator::WriteMasmOptions(
3791   Elem& e1, std::string const& configName)
3792 {
3793   if (!this->MSTools || !this->GlobalGenerator->IsMasmEnabled()) {
3794     return;
3795   }
3796   Elem e2(e1, "MASM");
3797
3798   // Preprocessor definitions and includes are shared with clOptions.
3799   OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
3800   clOptions.OutputPreprocessorDefinitions("ASM_MASM");
3801
3802   OptionsHelper masmOptions(*(this->MasmOptions[configName]), e2);
3803   masmOptions.OutputAdditionalIncludeDirectories("ASM_MASM");
3804   masmOptions.PrependInheritedString("AdditionalOptions");
3805   masmOptions.OutputFlagMap();
3806 }
3807
3808 bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
3809 {
3810   if (!this->GlobalGenerator->IsNasmEnabled()) {
3811     return true;
3812   }
3813   for (std::string const& c : this->Configurations) {
3814     if (!this->ComputeNasmOptions(c)) {
3815       return false;
3816     }
3817   }
3818   return true;
3819 }
3820
3821 bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
3822   std::string const& configName)
3823 {
3824   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
3825   auto pOptions = cm::make_unique<Options>(
3826     this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable());
3827   Options& nasmOptions = *pOptions;
3828
3829   std::string flags;
3830   this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
3831                                          cmBuildStep::Compile, "ASM_NASM",
3832                                          configName);
3833   flags += " -f";
3834   flags += this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT");
3835   nasmOptions.Parse(flags);
3836
3837   // Get includes for this target
3838   nasmOptions.AddIncludes(this->GetIncludes(configName, "ASM_NASM"));
3839
3840   this->NasmOptions[configName] = std::move(pOptions);
3841   return true;
3842 }
3843
3844 void cmVisualStudio10TargetGenerator::WriteNasmOptions(
3845   Elem& e1, std::string const& configName)
3846 {
3847   if (!this->GlobalGenerator->IsNasmEnabled()) {
3848     return;
3849   }
3850   Elem e2(e1, "NASM");
3851
3852   OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2);
3853   nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM");
3854   nasmOptions.OutputFlagMap();
3855   nasmOptions.PrependInheritedString("AdditionalOptions");
3856   nasmOptions.OutputPreprocessorDefinitions("ASM_NASM");
3857
3858   // Preprocessor definitions and includes are shared with clOptions.
3859   OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
3860   clOptions.OutputPreprocessorDefinitions("ASM_NASM");
3861 }
3862
3863 void cmVisualStudio10TargetGenerator::WriteLibOptions(
3864   Elem& e1, std::string const& config)
3865 {
3866   if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY &&
3867       this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
3868     return;
3869   }
3870
3871   const std::string& linkLanguage =
3872     this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage;
3873
3874   std::string libflags;
3875   this->LocalGenerator->GetStaticLibraryFlags(libflags, config, linkLanguage,
3876                                               this->GeneratorTarget);
3877   if (!libflags.empty()) {
3878     Elem e2(e1, "Lib");
3879     cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
3880     cmVS10GeneratorOptions libOptions(this->LocalGenerator,
3881                                       cmVisualStudioGeneratorOptions::Linker,
3882                                       gg->GetLibFlagTable(), this);
3883     libOptions.Parse(libflags);
3884     OptionsHelper oh(libOptions, e2);
3885     oh.PrependInheritedString("AdditionalOptions");
3886     oh.OutputFlagMap();
3887   }
3888
3889   // We cannot generate metadata for static libraries.  WindowsPhone
3890   // and WindowsStore tools look at GenerateWindowsMetadata in the
3891   // Link tool options even for static libraries.
3892   if (this->GlobalGenerator->TargetsWindowsPhone() ||
3893       this->GlobalGenerator->TargetsWindowsStore()) {
3894     Elem e2(e1, "Link");
3895     e2.Element("GenerateWindowsMetadata", "false");
3896   }
3897 }
3898
3899 void cmVisualStudio10TargetGenerator::WriteManifestOptions(
3900   Elem& e1, std::string const& config)
3901 {
3902   if (this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE &&
3903       this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY &&
3904       this->GeneratorTarget->GetType() != cmStateEnums::MODULE_LIBRARY) {
3905     return;
3906   }
3907
3908   std::vector<cmSourceFile const*> manifest_srcs;
3909   this->GeneratorTarget->GetManifests(manifest_srcs, config);
3910
3911   cmValue dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE");
3912
3913   if (!manifest_srcs.empty() || dpiAware) {
3914     Elem e2(e1, "Manifest");
3915     if (!manifest_srcs.empty()) {
3916       std::ostringstream oss;
3917       for (cmSourceFile const* mi : manifest_srcs) {
3918         std::string m = this->ConvertPath(mi->GetFullPath(), false);
3919         ConvertToWindowsSlash(m);
3920         oss << m << ";";
3921       }
3922       e2.Element("AdditionalManifestFiles", oss.str());
3923     }
3924     if (dpiAware) {
3925       if (*dpiAware == "PerMonitor") {
3926         e2.Element("EnableDpiAwareness", "PerMonitorHighDPIAware");
3927       } else if (cmIsOn(*dpiAware)) {
3928         e2.Element("EnableDpiAwareness", "true");
3929       } else if (cmIsOff(*dpiAware)) {
3930         e2.Element("EnableDpiAwareness", "false");
3931       } else {
3932         cmSystemTools::Error("Bad parameter for VS_DPI_AWARE: " + *dpiAware);
3933       }
3934     }
3935   }
3936 }
3937
3938 void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
3939   Elem& e1, std::string const& configName)
3940 {
3941   // Look through the sources for AndroidManifest.xml and use
3942   // its location as the root source directory.
3943   std::string rootDir = this->LocalGenerator->GetCurrentSourceDirectory();
3944   {
3945     for (cmGeneratorTarget::AllConfigSource const& source :
3946          this->GeneratorTarget->GetAllConfigSources()) {
3947       if (source.Kind == cmGeneratorTarget::SourceKindExtra &&
3948           "androidmanifest.xml" ==
3949             cmSystemTools::LowerCase(source.Source->GetLocation().GetName())) {
3950         rootDir = source.Source->GetLocation().GetDirectory();
3951         break;
3952       }
3953     }
3954   }
3955
3956   // Tell MSBuild to launch Ant.
3957   Elem e2(e1, "AntBuild");
3958   {
3959     std::string antBuildPath = rootDir;
3960     ConvertToWindowsSlash(antBuildPath);
3961     e2.Element("AntBuildPath", antBuildPath);
3962   }
3963
3964   if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) {
3965     e2.Element("SkipAntStep", "true");
3966   }
3967
3968   if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_PROGUARD")) {
3969     e2.Element("EnableProGuard", "true");
3970   }
3971
3972   if (cmValue proGuardConfigLocation =
3973         this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) {
3974     e2.Element("ProGuardConfigLocation", *proGuardConfigLocation);
3975   }
3976
3977   if (cmValue securePropertiesLocation =
3978         this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) {
3979     e2.Element("SecurePropertiesLocation", *securePropertiesLocation);
3980   }
3981
3982   if (cmValue nativeLibDirectoriesExpression =
3983         this->GeneratorTarget->GetProperty("ANDROID_NATIVE_LIB_DIRECTORIES")) {
3984     std::string nativeLibDirs = cmGeneratorExpression::Evaluate(
3985       *nativeLibDirectoriesExpression, this->LocalGenerator, configName);
3986     e2.Element("NativeLibDirectories", nativeLibDirs);
3987   }
3988
3989   if (cmValue nativeLibDependenciesExpression =
3990         this->GeneratorTarget->GetProperty(
3991           "ANDROID_NATIVE_LIB_DEPENDENCIES")) {
3992     std::string nativeLibDeps = cmGeneratorExpression::Evaluate(
3993       *nativeLibDependenciesExpression, this->LocalGenerator, configName);
3994     e2.Element("NativeLibDependencies", nativeLibDeps);
3995   }
3996
3997   if (cmValue javaSourceDir =
3998         this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) {
3999     e2.Element("JavaSourceDir", *javaSourceDir);
4000   }
4001
4002   if (cmValue jarDirectoriesExpression =
4003         this->GeneratorTarget->GetProperty("ANDROID_JAR_DIRECTORIES")) {
4004     std::string jarDirectories = cmGeneratorExpression::Evaluate(
4005       *jarDirectoriesExpression, this->LocalGenerator, configName);
4006     e2.Element("JarDirectories", jarDirectories);
4007   }
4008
4009   if (cmValue jarDeps =
4010         this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) {
4011     e2.Element("JarDependencies", *jarDeps);
4012   }
4013
4014   if (cmValue assetsDirectories =
4015         this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) {
4016     e2.Element("AssetsDirectories", *assetsDirectories);
4017   }
4018
4019   {
4020     std::string manifest_xml = rootDir + "/AndroidManifest.xml";
4021     ConvertToWindowsSlash(manifest_xml);
4022     e2.Element("AndroidManifestLocation", manifest_xml);
4023   }
4024
4025   if (cmValue antAdditionalOptions =
4026         this->GeneratorTarget->GetProperty("ANDROID_ANT_ADDITIONAL_OPTIONS")) {
4027     e2.Element("AdditionalOptions",
4028                *antAdditionalOptions + " %(AdditionalOptions)");
4029   }
4030 }
4031
4032 bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
4033 {
4034   if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
4035       this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
4036       this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
4037     for (std::string const& c : this->Configurations) {
4038       if (!this->ComputeLinkOptions(c)) {
4039         return false;
4040       }
4041     }
4042   }
4043   return true;
4044 }
4045
4046 bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
4047   std::string const& config)
4048 {
4049   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
4050   auto pOptions = cm::make_unique<Options>(
4051     this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), this);
4052   Options& linkOptions = *pOptions;
4053
4054   cmGeneratorTarget::LinkClosure const* linkClosure =
4055     this->GeneratorTarget->GetLinkClosure(config);
4056
4057   const std::string& linkLanguage = linkClosure->LinkerLanguage;
4058   if (linkLanguage.empty()) {
4059     cmSystemTools::Error(
4060       "CMake can not determine linker language for target: " + this->Name);
4061     return false;
4062   }
4063
4064   std::string CONFIG = cmSystemTools::UpperCase(config);
4065
4066   const char* linkType = "SHARED";
4067   if (this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
4068     linkType = "MODULE";
4069   }
4070   if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4071     linkType = "EXE";
4072   }
4073   std::string flags;
4074   std::string linkFlagVarBase = cmStrCat("CMAKE_", linkType, "_LINKER_FLAGS");
4075   flags += " ";
4076   flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase);
4077   std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
4078   flags += " ";
4079   flags += this->Makefile->GetRequiredDefinition(linkFlagVar);
4080   cmValue targetLinkFlags = this->GeneratorTarget->GetProperty("LINK_FLAGS");
4081   if (targetLinkFlags) {
4082     flags += " ";
4083     flags += *targetLinkFlags;
4084   }
4085   std::string flagsProp = cmStrCat("LINK_FLAGS_", CONFIG);
4086   if (cmValue flagsConfig = this->GeneratorTarget->GetProperty(flagsProp)) {
4087     flags += " ";
4088     flags += *flagsConfig;
4089   }
4090
4091   std::vector<std::string> opts;
4092   this->GeneratorTarget->GetLinkOptions(opts, config, linkLanguage);
4093   // LINK_OPTIONS are escaped.
4094   this->LocalGenerator->AppendCompileOptions(flags, opts);
4095
4096   cmComputeLinkInformation* pcli =
4097     this->GeneratorTarget->GetLinkInformation(config);
4098   if (!pcli) {
4099     cmSystemTools::Error(
4100       "CMake can not compute cmComputeLinkInformation for target: " +
4101       this->Name);
4102     return false;
4103   }
4104   cmComputeLinkInformation& cli = *pcli;
4105
4106   std::vector<std::string> libVec;
4107   std::vector<std::string> vsTargetVec;
4108   this->AddLibraries(cli, libVec, vsTargetVec, config);
4109   std::string standardLibsVar =
4110     cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES");
4111   std::string const& libs = this->Makefile->GetSafeDefinition(standardLibsVar);
4112   cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec);
4113   linkOptions.AddFlag("AdditionalDependencies", libVec);
4114
4115   // Populate TargetsFileAndConfigsVec
4116   for (std::string const& ti : vsTargetVec) {
4117     this->AddTargetsFileAndConfigPair(ti, config);
4118   }
4119
4120   std::vector<std::string> const& ldirs = cli.GetDirectories();
4121   std::vector<std::string> linkDirs;
4122   for (std::string const& d : ldirs) {
4123     // first just full path
4124     linkDirs.push_back(d);
4125     // next path with configuration type Debug, Release, etc
4126     linkDirs.push_back(d + "/$(Configuration)");
4127   }
4128   linkDirs.push_back("%(AdditionalLibraryDirectories)");
4129   linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs);
4130
4131   cmGeneratorTarget::Names targetNames;
4132   if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4133     targetNames = this->GeneratorTarget->GetExecutableNames(config);
4134   } else {
4135     targetNames = this->GeneratorTarget->GetLibraryNames(config);
4136   }
4137
4138   if (this->MSTools) {
4139     if (this->GeneratorTarget->IsWin32Executable(config)) {
4140       if (this->GlobalGenerator->TargetsWindowsCE()) {
4141         linkOptions.AddFlag("SubSystem", "WindowsCE");
4142         if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4143           if (this->ClOptions[config]->UsingUnicode()) {
4144             linkOptions.AddFlag("EntryPointSymbol", "wWinMainCRTStartup");
4145           } else {
4146             linkOptions.AddFlag("EntryPointSymbol", "WinMainCRTStartup");
4147           }
4148         }
4149       } else {
4150         linkOptions.AddFlag("SubSystem", "Windows");
4151       }
4152     } else {
4153       if (this->GlobalGenerator->TargetsWindowsCE()) {
4154         linkOptions.AddFlag("SubSystem", "WindowsCE");
4155         if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4156           if (this->ClOptions[config]->UsingUnicode()) {
4157             linkOptions.AddFlag("EntryPointSymbol", "mainWCRTStartup");
4158           } else {
4159             linkOptions.AddFlag("EntryPointSymbol", "mainACRTStartup");
4160           }
4161         }
4162       } else {
4163         linkOptions.AddFlag("SubSystem", "Console");
4164       };
4165     }
4166
4167     if (cmValue stackVal = this->Makefile->GetDefinition(
4168           "CMAKE_" + linkLanguage + "_STACK_SIZE")) {
4169       linkOptions.AddFlag("StackReserveSize", *stackVal);
4170     }
4171
4172     linkOptions.AddFlag("GenerateDebugInformation", "false");
4173
4174     std::string pdb = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config),
4175                                '/', targetNames.PDB);
4176     if (!targetNames.ImportLibrary.empty()) {
4177       std::string imLib =
4178         cmStrCat(this->GeneratorTarget->GetDirectory(
4179                    config, cmStateEnums::ImportLibraryArtifact),
4180                  '/', targetNames.ImportLibrary);
4181
4182       linkOptions.AddFlag("ImportLibrary", imLib);
4183     }
4184     linkOptions.AddFlag("ProgramDataBaseFile", pdb);
4185
4186     // A Windows Runtime component uses internal .NET metadata,
4187     // so does not have an import library.
4188     if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") &&
4189         this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE) {
4190       linkOptions.AddFlag("GenerateWindowsMetadata", "true");
4191     } else if (this->GlobalGenerator->TargetsWindowsPhone() ||
4192                this->GlobalGenerator->TargetsWindowsStore()) {
4193       // WindowsPhone and WindowsStore components are in an app container
4194       // and produce WindowsMetadata.  If we are not producing a WINRT
4195       // component, then do not generate the metadata here.
4196       linkOptions.AddFlag("GenerateWindowsMetadata", "false");
4197     }
4198
4199     if (this->GlobalGenerator->TargetsWindowsPhone() &&
4200         this->GlobalGenerator->GetSystemVersion() == "8.0") {
4201       // WindowsPhone 8.0 does not have ole32.
4202       linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "ole32.lib");
4203     }
4204   } else if (this->NsightTegra) {
4205     linkOptions.AddFlag("SoName", targetNames.SharedObject);
4206   }
4207
4208   linkOptions.Parse(flags);
4209   linkOptions.FixManifestUACFlags();
4210
4211   if (this->MSTools) {
4212     cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
4213       this->GeneratorTarget->GetModuleDefinitionInfo(config);
4214     if (mdi && !mdi->DefFile.empty()) {
4215       linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile);
4216     }
4217     linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
4218                            "%(IgnoreSpecificDefaultLibraries)");
4219   }
4220
4221   // VS 2015 without all updates has a v140 toolset whose
4222   // GenerateDebugInformation expects No/Debug instead of false/true.
4223   if (gg->GetPlatformToolsetNeedsDebugEnum()) {
4224     if (const char* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
4225       if (strcmp(debug, "false") == 0) {
4226         linkOptions.AddFlag("GenerateDebugInformation", "No");
4227       } else if (strcmp(debug, "true") == 0) {
4228         linkOptions.AddFlag("GenerateDebugInformation", "Debug");
4229       }
4230     }
4231   }
4232
4233   // Managed code cannot be linked with /DEBUG:FASTLINK
4234   if (this->Managed) {
4235     if (const char* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
4236       if (strcmp(debug, "DebugFastLink") == 0) {
4237         linkOptions.AddFlag("GenerateDebugInformation", "Debug");
4238       }
4239     }
4240   }
4241
4242   this->LinkOptions[config] = std::move(pOptions);
4243   return true;
4244 }
4245
4246 bool cmVisualStudio10TargetGenerator::ComputeLibOptions()
4247 {
4248   if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
4249     for (std::string const& c : this->Configurations) {
4250       if (!this->ComputeLibOptions(c)) {
4251         return false;
4252       }
4253     }
4254   }
4255   return true;
4256 }
4257
4258 bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
4259   std::string const& config)
4260 {
4261   cmComputeLinkInformation* pcli =
4262     this->GeneratorTarget->GetLinkInformation(config);
4263   if (!pcli) {
4264     cmSystemTools::Error(
4265       "CMake can not compute cmComputeLinkInformation for target: " +
4266       this->Name);
4267     return false;
4268   }
4269
4270   cmComputeLinkInformation& cli = *pcli;
4271   using ItemVector = cmComputeLinkInformation::ItemVector;
4272   const ItemVector& libs = cli.GetItems();
4273   for (cmComputeLinkInformation::Item const& l : libs) {
4274     if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes &&
4275         cmVS10IsTargetsFile(l.Value.Value)) {
4276       std::string path =
4277         this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
4278       ConvertToWindowsSlash(path);
4279       this->AddTargetsFileAndConfigPair(path, config);
4280     }
4281   }
4282
4283   return true;
4284 }
4285
4286 void cmVisualStudio10TargetGenerator::WriteLinkOptions(
4287   Elem& e1, std::string const& config)
4288 {
4289   if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
4290       this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
4291     return;
4292   }
4293   if (this->ProjectType == VsProjectType::csproj) {
4294     return;
4295   }
4296
4297   {
4298     Elem e2(e1, "Link");
4299     OptionsHelper linkOptions(*(this->LinkOptions[config]), e2);
4300     linkOptions.PrependInheritedString("AdditionalOptions");
4301     linkOptions.OutputFlagMap();
4302   }
4303
4304   if (!this->GlobalGenerator->NeedLinkLibraryDependencies(
4305         this->GeneratorTarget)) {
4306     Elem e2(e1, "ProjectReference");
4307     e2.Element("LinkLibraryDependencies", "false");
4308   }
4309 }
4310
4311 void cmVisualStudio10TargetGenerator::AddLibraries(
4312   const cmComputeLinkInformation& cli, std::vector<std::string>& libVec,
4313   std::vector<std::string>& vsTargetVec, const std::string& config)
4314 {
4315   using ItemVector = cmComputeLinkInformation::ItemVector;
4316   ItemVector const& libs = cli.GetItems();
4317   for (cmComputeLinkInformation::Item const& l : libs) {
4318     if (l.Target) {
4319       auto managedType = l.Target->GetManagedType(config);
4320       if (managedType != cmGeneratorTarget::ManagedType::Native &&
4321           this->GeneratorTarget->GetManagedType(config) !=
4322             cmGeneratorTarget::ManagedType::Native &&
4323           l.Target->IsImported() &&
4324           l.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
4325         auto location = l.Target->GetFullPath(config);
4326         if (!location.empty()) {
4327           ConvertToWindowsSlash(location);
4328           switch (this->ProjectType) {
4329             case VsProjectType::csproj:
4330               // If the target we want to "link" to is an imported managed
4331               // target and this is a C# project, we add a hint reference. This
4332               // reference is written to project file in
4333               // WriteDotNetReferences().
4334               this->DotNetHintReferences[config].push_back(
4335                 DotNetHintReference(l.Target->GetName(), location));
4336               break;
4337             case VsProjectType::vcxproj:
4338               // Add path of assembly to list of using-directories, so the
4339               // managed assembly can be used by '#using <assembly.dll>' in
4340               // code.
4341               this->AdditionalUsingDirectories[config].insert(
4342                 cmSystemTools::GetFilenamePath(location));
4343               break;
4344             default:
4345               // In .proj files, we wouldn't be referencing libraries.
4346               break;
4347           }
4348         }
4349       }
4350       // Do not allow C# targets to be added to the LIB listing. LIB files are
4351       // used for linking C++ dependencies. C# libraries do not have lib files.
4352       // Instead, they compile down to C# reference libraries (DLL files). The
4353       // `<ProjectReference>` elements added to the vcxproj are enough for the
4354       // IDE to deduce the DLL file required by other C# projects that need its
4355       // reference library.
4356       if (managedType == cmGeneratorTarget::ManagedType::Managed) {
4357         continue;
4358       }
4359     }
4360
4361     if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
4362       std::string path =
4363         this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
4364       ConvertToWindowsSlash(path);
4365       if (cmVS10IsTargetsFile(l.Value.Value)) {
4366         vsTargetVec.push_back(path);
4367       } else {
4368         libVec.push_back(l.HasFeature() ? l.GetFormattedItem(path).Value
4369                                         : path);
4370       }
4371     } else if (!l.Target ||
4372                l.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
4373       libVec.push_back(l.Value.Value);
4374     }
4375   }
4376 }
4377
4378 void cmVisualStudio10TargetGenerator::AddTargetsFileAndConfigPair(
4379   std::string const& targetsFile, std::string const& config)
4380 {
4381   for (TargetsFileAndConfigs& i : this->TargetsFileAndConfigsVec) {
4382     if (cmSystemTools::ComparePath(targetsFile, i.File)) {
4383       if (!cm::contains(i.Configs, config)) {
4384         i.Configs.push_back(config);
4385       }
4386       return;
4387     }
4388   }
4389   TargetsFileAndConfigs entry;
4390   entry.File = targetsFile;
4391   entry.Configs.push_back(config);
4392   this->TargetsFileAndConfigsVec.push_back(entry);
4393 }
4394
4395 void cmVisualStudio10TargetGenerator::WriteMidlOptions(
4396   Elem& e1, std::string const& configName)
4397 {
4398   if (!this->MSTools) {
4399     return;
4400   }
4401   if (this->ProjectType == VsProjectType::csproj) {
4402     return;
4403   }
4404   if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
4405     return;
4406   }
4407
4408   // This processes *any* of the .idl files specified in the project's file
4409   // list (and passed as the item metadata %(Filename) expressing the rule
4410   // input filename) into output files at the per-config *build* dir
4411   // ($(IntDir)) each.
4412   //
4413   // IOW, this MIDL section is intended to provide a fully generic syntax
4414   // content suitable for most cases (read: if you get errors, then it's quite
4415   // probable that the error is on your side of the .idl setup).
4416   //
4417   // Also, note that the marked-as-generated _i.c file in the Visual Studio
4418   // generator case needs to be referred to as $(IntDir)\foo_i.c at the
4419   // project's file list, otherwise the compiler-side processing won't pick it
4420   // up (for non-directory form, it ends up looking in project binary dir
4421   // only).  Perhaps there's something to be done to make this more automatic
4422   // on the CMake side?
4423   std::vector<std::string> const includes =
4424     this->GetIncludes(configName, "MIDL");
4425   std::ostringstream oss;
4426   for (std::string const& i : includes) {
4427     oss << i << ";";
4428   }
4429   oss << "%(AdditionalIncludeDirectories)";
4430
4431   Elem e2(e1, "Midl");
4432   e2.Element("AdditionalIncludeDirectories", oss.str());
4433   e2.Element("OutputDirectory", "$(ProjectDir)/$(IntDir)");
4434   e2.Element("HeaderFileName", "%(Filename).h");
4435   e2.Element("TypeLibraryName", "%(Filename).tlb");
4436   e2.Element("InterfaceIdentifierFileName", "%(Filename)_i.c");
4437   e2.Element("ProxyFileName", "%(Filename)_p.c");
4438 }
4439
4440 void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
4441 {
4442   if (this->ProjectType == VsProjectType::csproj) {
4443     return;
4444   }
4445   for (const std::string& c : this->Configurations) {
4446     Elem e1(e0, "ItemDefinitionGroup");
4447     e1.Attribute("Condition", this->CalcCondition(c));
4448
4449     //    output cl compile flags <ClCompile></ClCompile>
4450     if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
4451       this->WriteClOptions(e1, c);
4452       //    output rc compile flags <ResourceCompile></ResourceCompile>
4453       this->WriteRCOptions(e1, c);
4454       this->WriteCudaOptions(e1, c);
4455       this->WriteMasmOptions(e1, c);
4456       this->WriteNasmOptions(e1, c);
4457     }
4458     //    output midl flags       <Midl></Midl>
4459     this->WriteMidlOptions(e1, c);
4460     // write events
4461     if (this->ProjectType != VsProjectType::csproj) {
4462       this->WriteEvents(e1, c);
4463     }
4464     //    output link flags       <Link></Link>
4465     this->WriteLinkOptions(e1, c);
4466     this->WriteCudaLinkOptions(e1, c);
4467     //    output lib flags       <Lib></Lib>
4468     this->WriteLibOptions(e1, c);
4469     //    output manifest flags  <Manifest></Manifest>
4470     this->WriteManifestOptions(e1, c);
4471     if (this->NsightTegra &&
4472         this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
4473       this->WriteAntBuildOptions(e1, c);
4474     }
4475   }
4476 }
4477
4478 void cmVisualStudio10TargetGenerator::WriteEvents(
4479   Elem& e1, std::string const& configName)
4480 {
4481   bool addedPrelink = false;
4482   cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
4483     this->GeneratorTarget->GetModuleDefinitionInfo(configName);
4484   if (mdi && mdi->DefFileGenerated) {
4485     addedPrelink = true;
4486     std::vector<cmCustomCommand> commands =
4487       this->GeneratorTarget->GetPreLinkCommands();
4488     this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
4489                                                   commands, configName);
4490     this->WriteEvent(e1, "PreLinkEvent", commands, configName);
4491   }
4492   if (!addedPrelink) {
4493     this->WriteEvent(e1, "PreLinkEvent",
4494                      this->GeneratorTarget->GetPreLinkCommands(), configName);
4495   }
4496   this->WriteEvent(e1, "PreBuildEvent",
4497                    this->GeneratorTarget->GetPreBuildCommands(), configName);
4498   this->WriteEvent(e1, "PostBuildEvent",
4499                    this->GeneratorTarget->GetPostBuildCommands(), configName);
4500 }
4501
4502 void cmVisualStudio10TargetGenerator::WriteEvent(
4503   Elem& e1, const std::string& name,
4504   std::vector<cmCustomCommand> const& commands, std::string const& configName)
4505 {
4506   if (commands.empty()) {
4507     return;
4508   }
4509   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
4510   std::string script;
4511   const char* pre = "";
4512   std::string comment;
4513   bool stdPipesUTF8 = false;
4514   for (cmCustomCommand const& cc : commands) {
4515     cmCustomCommandGenerator ccg(cc, configName, lg);
4516     if (!ccg.HasOnlyEmptyCommandLines()) {
4517       comment += pre;
4518       comment += lg->ConstructComment(ccg);
4519       script += pre;
4520       pre = "\n";
4521       script += lg->ConstructScript(ccg);
4522
4523       stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8();
4524     }
4525   }
4526   if (!script.empty()) {
4527     script += lg->FinishConstructScript(this->ProjectType);
4528   }
4529   comment = cmVS10EscapeComment(comment);
4530   if (this->ProjectType != VsProjectType::csproj) {
4531     Elem e2(e1, name);
4532     if (stdPipesUTF8) {
4533       this->WriteStdOutEncodingUtf8(e2);
4534     }
4535     e2.Element("Message", comment);
4536     e2.Element("Command", script);
4537   } else {
4538     std::string strippedComment = comment;
4539     strippedComment.erase(
4540       std::remove(strippedComment.begin(), strippedComment.end(), '\t'),
4541       strippedComment.end());
4542     std::ostringstream oss;
4543     if (!comment.empty() && !strippedComment.empty()) {
4544       oss << "echo " << comment << "\n";
4545     }
4546     oss << script << "\n";
4547     e1.Element(name, oss.str());
4548   }
4549 }
4550
4551 void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
4552 {
4553   cmGlobalGenerator::TargetDependSet const& unordered =
4554     this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
4555   using OrderedTargetDependSet =
4556     cmGlobalVisualStudioGenerator::OrderedTargetDependSet;
4557   OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
4558   Elem e1(e0, "ItemGroup");
4559   e1.SetHasElements();
4560   for (cmGeneratorTarget const* dt : depends) {
4561     if (!dt->IsInBuildSystem()) {
4562       continue;
4563     }
4564     // skip fortran targets as they can not be processed by MSBuild
4565     // the only reference will be in the .sln file
4566     if (this->GlobalGenerator->TargetIsFortranOnly(dt)) {
4567       continue;
4568     }
4569     cmLocalGenerator* lg = dt->GetLocalGenerator();
4570     std::string name = dt->GetName();
4571     std::string path;
4572     if (cmValue p = dt->GetProperty("EXTERNAL_MSPROJECT")) {
4573       path = *p;
4574     } else {
4575       path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(),
4576                       computeProjectFileExtension(dt));
4577     }
4578     ConvertToWindowsSlash(path);
4579     Elem e2(e1, "ProjectReference");
4580     e2.Attribute("Include", path);
4581     e2.Element("Project", "{" + this->GlobalGenerator->GetGUID(name) + "}");
4582     e2.Element("Name", name);
4583     this->WriteDotNetReferenceCustomTags(e2, name);
4584     if (dt->IsCSharpOnly() || cmHasLiteralSuffix(path, "csproj")) {
4585       e2.Element("SkipGetTargetFrameworkProperties", "true");
4586     }
4587     // Don't reference targets that don't produce any output.
4588     else if (this->Configurations.empty() ||
4589              dt->GetManagedType(this->Configurations[0]) ==
4590                cmGeneratorTarget::ManagedType::Undefined) {
4591       e2.Element("ReferenceOutputAssembly", "false");
4592       e2.Element("CopyToOutputDirectory", "Never");
4593     }
4594   }
4595 }
4596
4597 void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1)
4598 {
4599   // This only applies to Windows 10 apps
4600   if (this->GlobalGenerator->TargetsWindowsStore() &&
4601       cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
4602     cmValue desktopExtensionsVersion =
4603       this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
4604     if (desktopExtensionsVersion) {
4605       this->WriteSinglePlatformExtension(e1, "WindowsDesktop",
4606                                          *desktopExtensionsVersion);
4607     }
4608     cmValue mobileExtensionsVersion =
4609       this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
4610     if (mobileExtensionsVersion) {
4611       this->WriteSinglePlatformExtension(e1, "WindowsMobile",
4612                                          *mobileExtensionsVersion);
4613     }
4614   }
4615 }
4616
4617 void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension(
4618   Elem& e1, std::string const& extension, std::string const& version)
4619 {
4620   const std::string s = "$([Microsoft.Build.Utilities.ToolLocationHelper]"
4621                         "::GetPlatformExtensionSDKLocation(`" +
4622     extension + ", Version=" + version +
4623     "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
4624     "$(ExtensionSDKDirectoryRoot), null))"
4625     "\\DesignTime\\CommonConfiguration\\Neutral\\" +
4626     extension + ".props";
4627
4628   Elem e2(e1, "Import");
4629   e2.Attribute("Project", s);
4630   e2.Attribute("Condition", "exists('" + s + "')");
4631 }
4632
4633 void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
4634 {
4635   std::vector<std::string> sdkReferences;
4636   std::unique_ptr<Elem> spe1;
4637   if (cmValue vsSDKReferences =
4638         this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) {
4639     cmExpandList(*vsSDKReferences, sdkReferences);
4640     spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
4641     for (std::string const& ri : sdkReferences) {
4642       Elem(*spe1, "SDKReference").Attribute("Include", ri);
4643     }
4644   }
4645
4646   // This only applies to Windows 10 apps
4647   if (this->GlobalGenerator->TargetsWindowsStore() &&
4648       cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
4649     cmValue desktopExtensionsVersion =
4650       this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
4651     cmValue mobileExtensionsVersion =
4652       this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
4653     cmValue iotExtensionsVersion =
4654       this->GeneratorTarget->GetProperty("VS_IOT_EXTENSIONS_VERSION");
4655
4656     if (desktopExtensionsVersion || mobileExtensionsVersion ||
4657         iotExtensionsVersion) {
4658       if (!spe1) {
4659         spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
4660       }
4661       if (desktopExtensionsVersion) {
4662         this->WriteSingleSDKReference(*spe1, "WindowsDesktop",
4663                                       *desktopExtensionsVersion);
4664       }
4665       if (mobileExtensionsVersion) {
4666         this->WriteSingleSDKReference(*spe1, "WindowsMobile",
4667                                       *mobileExtensionsVersion);
4668       }
4669       if (iotExtensionsVersion) {
4670         this->WriteSingleSDKReference(*spe1, "WindowsIoT",
4671                                       *iotExtensionsVersion);
4672       }
4673     }
4674   }
4675 }
4676
4677 void cmVisualStudio10TargetGenerator::WriteSingleSDKReference(
4678   Elem& e1, std::string const& extension, std::string const& version)
4679 {
4680   Elem(e1, "SDKReference")
4681     .Attribute("Include", extension + ", Version=" + version);
4682 }
4683
4684 void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
4685   Elem& e0)
4686 {
4687   if ((this->GlobalGenerator->TargetsWindowsStore() ||
4688        this->GlobalGenerator->TargetsWindowsPhone()) &&
4689       (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType())) {
4690     std::string pfxFile;
4691     for (cmGeneratorTarget::AllConfigSource const& source :
4692          this->GeneratorTarget->GetAllConfigSources()) {
4693       if (source.Kind == cmGeneratorTarget::SourceKindCertificate) {
4694         pfxFile = this->ConvertPath(source.Source->GetFullPath(), false);
4695         ConvertToWindowsSlash(pfxFile);
4696         break;
4697       }
4698     }
4699
4700     if (this->IsMissingFiles &&
4701         !(this->GlobalGenerator->TargetsWindowsPhone() &&
4702           this->GlobalGenerator->GetSystemVersion() == "8.0")) {
4703       // Move the manifest to a project directory to avoid clashes
4704       std::string artifactDir =
4705         this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
4706       ConvertToWindowsSlash(artifactDir);
4707       Elem e1(e0, "PropertyGroup");
4708       e1.Element("AppxPackageArtifactsDir", artifactDir + "\\");
4709       std::string resourcePriFile =
4710         this->DefaultArtifactDir + "/resources.pri";
4711       ConvertToWindowsSlash(resourcePriFile);
4712       e1.Element("ProjectPriFullPath", resourcePriFile);
4713
4714       // If we are missing files and we don't have a certificate and
4715       // aren't targeting WP8.0, add a default certificate
4716       if (pfxFile.empty()) {
4717         std::string templateFolder =
4718           cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
4719         pfxFile = this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
4720         cmSystemTools::CopyAFile(templateFolder + "/Windows_TemporaryKey.pfx",
4721                                  pfxFile, false);
4722         ConvertToWindowsSlash(pfxFile);
4723         this->AddedFiles.push_back(pfxFile);
4724         this->AddedDefaultCertificate = true;
4725       }
4726
4727       e1.Element("PackageCertificateKeyFile", pfxFile);
4728       std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
4729       if (!thumb.empty()) {
4730         e1.Element("PackageCertificateThumbprint", thumb);
4731       }
4732     } else if (!pfxFile.empty()) {
4733       Elem e1(e0, "PropertyGroup");
4734       e1.Element("PackageCertificateKeyFile", pfxFile);
4735       std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
4736       if (!thumb.empty()) {
4737         e1.Element("PackageCertificateThumbprint", thumb);
4738       }
4739     }
4740   }
4741 }
4742
4743 void cmVisualStudio10TargetGenerator::ClassifyAllConfigSources()
4744 {
4745   for (cmGeneratorTarget::AllConfigSource const& source :
4746        this->GeneratorTarget->GetAllConfigSources()) {
4747     this->ClassifyAllConfigSource(source);
4748   }
4749 }
4750
4751 void cmVisualStudio10TargetGenerator::ClassifyAllConfigSource(
4752   cmGeneratorTarget::AllConfigSource const& acs)
4753 {
4754   switch (acs.Kind) {
4755     case cmGeneratorTarget::SourceKindResx: {
4756       // Build and save the name of the corresponding .h file
4757       // This relationship will be used later when building the project files.
4758       // Both names would have been auto generated from Visual Studio
4759       // where the user supplied the file name and Visual Studio
4760       // appended the suffix.
4761       std::string resx = acs.Source->ResolveFullPath();
4762       std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
4763       this->ExpectedResxHeaders.insert(hFileName);
4764     } break;
4765     case cmGeneratorTarget::SourceKindXaml: {
4766       // Build and save the name of the corresponding .h and .cpp file
4767       // This relationship will be used later when building the project files.
4768       // Both names would have been auto generated from Visual Studio
4769       // where the user supplied the file name and Visual Studio
4770       // appended the suffix.
4771       std::string xaml = acs.Source->ResolveFullPath();
4772       std::string hFileName = xaml + ".h";
4773       std::string cppFileName = xaml + ".cpp";
4774       this->ExpectedXamlHeaders.insert(hFileName);
4775       this->ExpectedXamlSources.insert(cppFileName);
4776     } break;
4777     default:
4778       break;
4779   }
4780 }
4781
4782 bool cmVisualStudio10TargetGenerator::IsResxHeader(
4783   const std::string& headerFile)
4784 {
4785   return this->ExpectedResxHeaders.count(headerFile) > 0;
4786 }
4787
4788 bool cmVisualStudio10TargetGenerator::IsXamlHeader(
4789   const std::string& headerFile)
4790 {
4791   return this->ExpectedXamlHeaders.count(headerFile) > 0;
4792 }
4793
4794 bool cmVisualStudio10TargetGenerator::IsXamlSource(
4795   const std::string& sourceFile)
4796 {
4797   return this->ExpectedXamlSources.count(sourceFile) > 0;
4798 }
4799
4800 void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
4801 {
4802   cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
4803   bool isAppContainer = false;
4804   bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
4805   bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
4806   bool const isAndroid = this->GlobalGenerator->TargetsAndroid();
4807   std::string const& rev = this->GlobalGenerator->GetApplicationTypeRevision();
4808   if (isWindowsPhone || isWindowsStore) {
4809     e1.Element("ApplicationType",
4810                (isWindowsPhone ? "Windows Phone" : "Windows Store"));
4811     e1.Element("DefaultLanguage", "en-US");
4812     if (rev == "10.0") {
4813       e1.Element("ApplicationTypeRevision", rev);
4814       // Visual Studio 14.0 is necessary for building 10.0 apps
4815       e1.Element("MinimumVisualStudioVersion", "14.0");
4816
4817       if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
4818         isAppContainer = true;
4819       }
4820     } else if (rev == "8.1") {
4821       e1.Element("ApplicationTypeRevision", rev);
4822       // Visual Studio 12.0 is necessary for building 8.1 apps
4823       e1.Element("MinimumVisualStudioVersion", "12.0");
4824
4825       if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
4826         isAppContainer = true;
4827       }
4828     } else if (rev == "8.0") {
4829       e1.Element("ApplicationTypeRevision", rev);
4830       // Visual Studio 11.0 is necessary for building 8.0 apps
4831       e1.Element("MinimumVisualStudioVersion", "11.0");
4832
4833       if (isWindowsStore &&
4834           this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
4835         isAppContainer = true;
4836       } else if (isWindowsPhone &&
4837                  this->GeneratorTarget->GetType() ==
4838                    cmStateEnums::EXECUTABLE) {
4839         e1.Element("XapOutputs", "true");
4840         e1.Element("XapFilename",
4841                    this->Name + "_$(Configuration)_$(Platform).xap");
4842       }
4843     }
4844   } else if (isAndroid) {
4845     e1.Element("ApplicationType", "Android");
4846     e1.Element("ApplicationTypeRevision",
4847                gg->GetAndroidApplicationTypeRevision());
4848   }
4849   if (isAppContainer) {
4850     e1.Element("AppContainerApplication", "true");
4851   } else if (!isAndroid) {
4852     if (this->Platform == "ARM64") {
4853       e1.Element("WindowsSDKDesktopARM64Support", "true");
4854     } else if (this->Platform == "ARM") {
4855       e1.Element("WindowsSDKDesktopARMSupport", "true");
4856     }
4857   }
4858   std::string const& targetPlatformVersion =
4859     gg->GetWindowsTargetPlatformVersion();
4860   if (!targetPlatformVersion.empty()) {
4861     e1.Element("WindowsTargetPlatformVersion", targetPlatformVersion);
4862   }
4863   cmValue targetPlatformMinVersion = this->GeneratorTarget->GetProperty(
4864     "VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION");
4865   if (targetPlatformMinVersion) {
4866     e1.Element("WindowsTargetPlatformMinVersion", *targetPlatformMinVersion);
4867   } else if (isWindowsStore && rev == "10.0") {
4868     // If the min version is not set, then use the TargetPlatformVersion
4869     if (!targetPlatformVersion.empty()) {
4870       e1.Element("WindowsTargetPlatformMinVersion", targetPlatformVersion);
4871     }
4872   }
4873
4874   // Added IoT Startup Task support
4875   if (this->GeneratorTarget->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) {
4876     e1.Element("ContainsStartupTask", "true");
4877   }
4878 }
4879
4880 void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles()
4881 {
4882   // For Windows and Windows Phone executables, we will assume that if a
4883   // manifest is not present that we need to add all the necessary files
4884   if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
4885     std::vector<cmGeneratorTarget::AllConfigSource> manifestSources =
4886       this->GeneratorTarget->GetAllConfigSources(
4887         cmGeneratorTarget::SourceKindAppManifest);
4888     std::string const& v = this->GlobalGenerator->GetSystemVersion();
4889     if (this->GlobalGenerator->TargetsWindowsPhone()) {
4890       if (v == "8.0") {
4891         // Look through the sources for WMAppManifest.xml
4892         bool foundManifest = false;
4893         for (cmGeneratorTarget::AllConfigSource const& source :
4894              this->GeneratorTarget->GetAllConfigSources()) {
4895           if (source.Kind == cmGeneratorTarget::SourceKindExtra &&
4896               "wmappmanifest.xml" ==
4897                 cmSystemTools::LowerCase(
4898                   source.Source->GetLocation().GetName())) {
4899             foundManifest = true;
4900             break;
4901           }
4902         }
4903         if (!foundManifest) {
4904           this->IsMissingFiles = true;
4905         }
4906       } else if (v == "8.1") {
4907         if (manifestSources.empty()) {
4908           this->IsMissingFiles = true;
4909         }
4910       }
4911     } else if (this->GlobalGenerator->TargetsWindowsStore()) {
4912       if (manifestSources.empty()) {
4913         if (v == "8.0") {
4914           this->IsMissingFiles = true;
4915         } else if (v == "8.1" || cmHasLiteralPrefix(v, "10.0")) {
4916           this->IsMissingFiles = true;
4917         }
4918       }
4919     }
4920   }
4921 }
4922
4923 void cmVisualStudio10TargetGenerator::WriteMissingFiles(Elem& e1)
4924 {
4925   std::string const& v = this->GlobalGenerator->GetSystemVersion();
4926   if (this->GlobalGenerator->TargetsWindowsPhone()) {
4927     if (v == "8.0") {
4928       this->WriteMissingFilesWP80(e1);
4929     } else if (v == "8.1") {
4930       this->WriteMissingFilesWP81(e1);
4931     }
4932   } else if (this->GlobalGenerator->TargetsWindowsStore()) {
4933     if (v == "8.0") {
4934       this->WriteMissingFilesWS80(e1);
4935     } else if (v == "8.1") {
4936       this->WriteMissingFilesWS81(e1);
4937     } else if (cmHasLiteralPrefix(v, "10.0")) {
4938       this->WriteMissingFilesWS10_0(e1);
4939     }
4940   }
4941 }
4942
4943 void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1)
4944 {
4945   std::string templateFolder =
4946     cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
4947
4948   // For WP80, the manifest needs to be in the same folder as the project
4949   // this can cause an overwrite problem if projects aren't organized in
4950   // folders
4951   std::string manifestFile =
4952     this->LocalGenerator->GetCurrentBinaryDirectory() + "/WMAppManifest.xml";
4953   std::string artifactDir =
4954     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
4955   ConvertToWindowsSlash(artifactDir);
4956   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
4957   std::string targetNameXML =
4958     cmVS10EscapeXML(this->GeneratorTarget->GetName());
4959
4960   cmGeneratedFileStream fout(manifestFile);
4961   fout.SetCopyIfDifferent(true);
4962
4963   /* clang-format off */
4964   fout <<
4965     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
4966     "<Deployment"
4967     " xmlns=\"http://schemas.microsoft.com/windowsphone/2012/deployment\""
4968     " AppPlatformVersion=\"8.0\">\n"
4969     "\t<DefaultLanguage xmlns=\"\" code=\"en-US\"/>\n"
4970     "\t<App xmlns=\"\" ProductID=\"{" << this->GUID << "}\""
4971     " Title=\"CMake Test Program\" RuntimeType=\"Modern Native\""
4972     " Version=\"1.0.0.0\" Genre=\"apps.normal\"  Author=\"CMake\""
4973     " Description=\"Default CMake App\" Publisher=\"CMake\""
4974     " PublisherID=\"{" << this->GUID << "}\">\n"
4975     "\t\t<IconPath IsRelative=\"true\" IsResource=\"false\">"
4976        << artifactDirXML << "\\ApplicationIcon.png</IconPath>\n"
4977     "\t\t<Capabilities/>\n"
4978     "\t\t<Tasks>\n"
4979     "\t\t\t<DefaultTask Name=\"_default\""
4980     " ImagePath=\"" << targetNameXML << ".exe\" ImageParams=\"\" />\n"
4981     "\t\t</Tasks>\n"
4982     "\t\t<Tokens>\n"
4983     "\t\t\t<PrimaryToken TokenID=\"" << targetNameXML << "Token\""
4984     " TaskName=\"_default\">\n"
4985     "\t\t\t\t<TemplateFlip>\n"
4986     "\t\t\t\t\t<SmallImageURI IsRelative=\"true\" IsResource=\"false\">"
4987        << artifactDirXML << "\\SmallLogo.png</SmallImageURI>\n"
4988     "\t\t\t\t\t<Count>0</Count>\n"
4989     "\t\t\t\t\t<BackgroundImageURI IsRelative=\"true\" IsResource=\"false\">"
4990        << artifactDirXML << "\\Logo.png</BackgroundImageURI>\n"
4991     "\t\t\t\t</TemplateFlip>\n"
4992     "\t\t\t</PrimaryToken>\n"
4993     "\t\t</Tokens>\n"
4994     "\t\t<ScreenResolutions>\n"
4995     "\t\t\t<ScreenResolution Name=\"ID_RESOLUTION_WVGA\" />\n"
4996     "\t\t</ScreenResolutions>\n"
4997     "\t</App>\n"
4998     "</Deployment>\n";
4999   /* clang-format on */
5000
5001   std::string sourceFile = this->ConvertPath(manifestFile, false);
5002   ConvertToWindowsSlash(sourceFile);
5003   {
5004     Elem e2(e1, "Xml");
5005     e2.Attribute("Include", sourceFile);
5006     e2.Element("SubType", "Designer");
5007   }
5008   this->AddedFiles.push_back(sourceFile);
5009
5010   std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
5011   cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
5012                            false);
5013   ConvertToWindowsSlash(smallLogo);
5014   Elem(e1, "Image").Attribute("Include", smallLogo);
5015   this->AddedFiles.push_back(smallLogo);
5016
5017   std::string logo = this->DefaultArtifactDir + "/Logo.png";
5018   cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
5019   ConvertToWindowsSlash(logo);
5020   Elem(e1, "Image").Attribute("Include", logo);
5021   this->AddedFiles.push_back(logo);
5022
5023   std::string applicationIcon =
5024     this->DefaultArtifactDir + "/ApplicationIcon.png";
5025   cmSystemTools::CopyAFile(templateFolder + "/ApplicationIcon.png",
5026                            applicationIcon, false);
5027   ConvertToWindowsSlash(applicationIcon);
5028   Elem(e1, "Image").Attribute("Include", applicationIcon);
5029   this->AddedFiles.push_back(applicationIcon);
5030 }
5031
5032 void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81(Elem& e1)
5033 {
5034   std::string manifestFile =
5035     this->DefaultArtifactDir + "/package.appxManifest";
5036   std::string artifactDir =
5037     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
5038   ConvertToWindowsSlash(artifactDir);
5039   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
5040   std::string targetNameXML =
5041     cmVS10EscapeXML(this->GeneratorTarget->GetName());
5042
5043   cmGeneratedFileStream fout(manifestFile);
5044   fout.SetCopyIfDifferent(true);
5045
5046   /* clang-format off */
5047   fout <<
5048     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
5049     "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\""
5050     " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\""
5051     " xmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\">\n"
5052     "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
5053     " Version=\"1.0.0.0\" />\n"
5054     "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID << "\""
5055     " PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n"
5056     "\t<Properties>\n"
5057     "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
5058     "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
5059     "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
5060     "\t</Properties>\n"
5061     "\t<Prerequisites>\n"
5062     "\t\t<OSMinVersion>6.3.1</OSMinVersion>\n"
5063     "\t\t<OSMaxVersionTested>6.3.1</OSMaxVersionTested>\n"
5064     "\t</Prerequisites>\n"
5065     "\t<Resources>\n"
5066     "\t\t<Resource Language=\"x-generate\" />\n"
5067     "\t</Resources>\n"
5068     "\t<Applications>\n"
5069     "\t\t<Application Id=\"App\""
5070     " Executable=\"" << targetNameXML << ".exe\""
5071     " EntryPoint=\"" << targetNameXML << ".App\">\n"
5072     "\t\t\t<m2:VisualElements\n"
5073     "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
5074     "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
5075     "\t\t\t\tBackgroundColor=\"#336699\"\n"
5076     "\t\t\t\tForegroundText=\"light\"\n"
5077     "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
5078     "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
5079     "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n"
5080     "\t\t\t\t\t<m2:ShowNameOnTiles>\n"
5081     "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n"
5082     "\t\t\t\t\t</m2:ShowNameOnTiles>\n"
5083     "\t\t\t\t</m2:DefaultTile>\n"
5084     "\t\t\t\t<m2:SplashScreen"
5085     " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
5086     "\t\t\t</m2:VisualElements>\n"
5087     "\t\t</Application>\n"
5088     "\t</Applications>\n"
5089     "</Package>\n";
5090   /* clang-format on */
5091
5092   this->WriteCommonMissingFiles(e1, manifestFile);
5093 }
5094
5095 void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80(Elem& e1)
5096 {
5097   std::string manifestFile =
5098     this->DefaultArtifactDir + "/package.appxManifest";
5099   std::string artifactDir =
5100     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
5101   ConvertToWindowsSlash(artifactDir);
5102   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
5103   std::string targetNameXML =
5104     cmVS10EscapeXML(this->GeneratorTarget->GetName());
5105
5106   cmGeneratedFileStream fout(manifestFile);
5107   fout.SetCopyIfDifferent(true);
5108
5109   /* clang-format off */
5110   fout <<
5111     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
5112     "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\">\n"
5113     "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
5114     " Version=\"1.0.0.0\" />\n"
5115     "\t<Properties>\n"
5116     "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
5117     "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
5118     "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
5119     "\t</Properties>\n"
5120     "\t<Prerequisites>\n"
5121     "\t\t<OSMinVersion>6.2.1</OSMinVersion>\n"
5122     "\t\t<OSMaxVersionTested>6.2.1</OSMaxVersionTested>\n"
5123     "\t</Prerequisites>\n"
5124     "\t<Resources>\n"
5125     "\t\t<Resource Language=\"x-generate\" />\n"
5126     "\t</Resources>\n"
5127     "\t<Applications>\n"
5128     "\t\t<Application Id=\"App\""
5129     " Executable=\"" << targetNameXML << ".exe\""
5130     " EntryPoint=\"" << targetNameXML << ".App\">\n"
5131     "\t\t\t<VisualElements"
5132     " DisplayName=\"" << targetNameXML << "\""
5133     " Description=\"" << targetNameXML << "\""
5134     " BackgroundColor=\"#336699\" ForegroundText=\"light\""
5135     " Logo=\"" << artifactDirXML << "\\Logo.png\""
5136     " SmallLogo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
5137     "\t\t\t\t<DefaultTile ShowName=\"allLogos\""
5138     " ShortName=\"" << targetNameXML << "\" />\n"
5139     "\t\t\t\t<SplashScreen"
5140     " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
5141     "\t\t\t</VisualElements>\n"
5142     "\t\t</Application>\n"
5143     "\t</Applications>\n"
5144     "</Package>\n";
5145   /* clang-format on */
5146
5147   this->WriteCommonMissingFiles(e1, manifestFile);
5148 }
5149
5150 void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81(Elem& e1)
5151 {
5152   std::string manifestFile =
5153     this->DefaultArtifactDir + "/package.appxManifest";
5154   std::string artifactDir =
5155     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
5156   ConvertToWindowsSlash(artifactDir);
5157   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
5158   std::string targetNameXML =
5159     cmVS10EscapeXML(this->GeneratorTarget->GetName());
5160
5161   cmGeneratedFileStream fout(manifestFile);
5162   fout.SetCopyIfDifferent(true);
5163
5164   /* clang-format off */
5165   fout <<
5166     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
5167     "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\""
5168     " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\">\n"
5169     "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
5170     " Version=\"1.0.0.0\" />\n"
5171     "\t<Properties>\n"
5172     "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
5173     "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
5174     "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
5175     "\t</Properties>\n"
5176     "\t<Prerequisites>\n"
5177     "\t\t<OSMinVersion>6.3</OSMinVersion>\n"
5178     "\t\t<OSMaxVersionTested>6.3</OSMaxVersionTested>\n"
5179     "\t</Prerequisites>\n"
5180     "\t<Resources>\n"
5181     "\t\t<Resource Language=\"x-generate\" />\n"
5182     "\t</Resources>\n"
5183     "\t<Applications>\n"
5184     "\t\t<Application Id=\"App\""
5185     " Executable=\"" << targetNameXML << ".exe\""
5186     " EntryPoint=\"" << targetNameXML << ".App\">\n"
5187     "\t\t\t<m2:VisualElements\n"
5188     "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
5189     "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
5190     "\t\t\t\tBackgroundColor=\"#336699\"\n"
5191     "\t\t\t\tForegroundText=\"light\"\n"
5192     "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
5193     "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
5194     "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n"
5195     "\t\t\t\t\t<m2:ShowNameOnTiles>\n"
5196     "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n"
5197     "\t\t\t\t\t</m2:ShowNameOnTiles>\n"
5198     "\t\t\t\t</m2:DefaultTile>\n"
5199     "\t\t\t\t<m2:SplashScreen"
5200     " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
5201     "\t\t\t</m2:VisualElements>\n"
5202     "\t\t</Application>\n"
5203     "\t</Applications>\n"
5204     "</Package>\n";
5205   /* clang-format on */
5206
5207   this->WriteCommonMissingFiles(e1, manifestFile);
5208 }
5209
5210 void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0(Elem& e1)
5211 {
5212   std::string manifestFile =
5213     this->DefaultArtifactDir + "/package.appxManifest";
5214   std::string artifactDir =
5215     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
5216   ConvertToWindowsSlash(artifactDir);
5217   std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
5218   std::string targetNameXML =
5219     cmVS10EscapeXML(this->GeneratorTarget->GetName());
5220
5221   cmGeneratedFileStream fout(manifestFile);
5222   fout.SetCopyIfDifferent(true);
5223
5224   /* clang-format off */
5225   fout <<
5226     "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
5227     "<Package\n\t"
5228     "xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\""
5229     "\txmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\"\n"
5230     "\txmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\""
5231     "\n\tIgnorableNamespaces=\"uap mp\">\n\n"
5232     "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
5233     " Version=\"1.0.0.0\" />\n"
5234     "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID <<
5235     "\" PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n"
5236     "\t<Properties>\n"
5237     "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
5238     "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
5239     "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
5240     "\t</Properties>\n"
5241     "\t<Dependencies>\n"
5242     "\t\t<TargetDeviceFamily Name=\"Windows.Universal\" "
5243     "MinVersion=\"10.0.0.0\" MaxVersionTested=\"10.0.0.0\" />\n"
5244     "\t</Dependencies>\n"
5245
5246     "\t<Resources>\n"
5247     "\t\t<Resource Language=\"x-generate\" />\n"
5248     "\t</Resources>\n"
5249     "\t<Applications>\n"
5250     "\t\t<Application Id=\"App\""
5251     " Executable=\"" << targetNameXML << ".exe\""
5252     " EntryPoint=\"" << targetNameXML << ".App\">\n"
5253     "\t\t\t<uap:VisualElements\n"
5254     "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
5255     "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
5256     "\t\t\t\tBackgroundColor=\"#336699\"\n"
5257     "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
5258     "\t\t\t\tSquare44x44Logo=\"" << artifactDirXML <<
5259     "\\SmallLogo44x44.png\">\n"
5260     "\t\t\t\t<uap:SplashScreen"
5261     " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
5262     "\t\t\t</uap:VisualElements>\n"
5263     "\t\t</Application>\n"
5264     "\t</Applications>\n"
5265     "</Package>\n";
5266   /* clang-format on */
5267
5268   this->WriteCommonMissingFiles(e1, manifestFile);
5269 }
5270
5271 void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
5272   Elem& e1, const std::string& manifestFile)
5273 {
5274   std::string templateFolder =
5275     cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
5276
5277   std::string sourceFile = this->ConvertPath(manifestFile, false);
5278   ConvertToWindowsSlash(sourceFile);
5279   {
5280     Elem e2(e1, "AppxManifest");
5281     e2.Attribute("Include", sourceFile);
5282     e2.Element("SubType", "Designer");
5283   }
5284   this->AddedFiles.push_back(sourceFile);
5285
5286   std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
5287   cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
5288                            false);
5289   ConvertToWindowsSlash(smallLogo);
5290   Elem(e1, "Image").Attribute("Include", smallLogo);
5291   this->AddedFiles.push_back(smallLogo);
5292
5293   std::string smallLogo44 = this->DefaultArtifactDir + "/SmallLogo44x44.png";
5294   cmSystemTools::CopyAFile(templateFolder + "/SmallLogo44x44.png", smallLogo44,
5295                            false);
5296   ConvertToWindowsSlash(smallLogo44);
5297   Elem(e1, "Image").Attribute("Include", smallLogo44);
5298   this->AddedFiles.push_back(smallLogo44);
5299
5300   std::string logo = this->DefaultArtifactDir + "/Logo.png";
5301   cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
5302   ConvertToWindowsSlash(logo);
5303   Elem(e1, "Image").Attribute("Include", logo);
5304   this->AddedFiles.push_back(logo);
5305
5306   std::string storeLogo = this->DefaultArtifactDir + "/StoreLogo.png";
5307   cmSystemTools::CopyAFile(templateFolder + "/StoreLogo.png", storeLogo,
5308                            false);
5309   ConvertToWindowsSlash(storeLogo);
5310   Elem(e1, "Image").Attribute("Include", storeLogo);
5311   this->AddedFiles.push_back(storeLogo);
5312
5313   std::string splashScreen = this->DefaultArtifactDir + "/SplashScreen.png";
5314   cmSystemTools::CopyAFile(templateFolder + "/SplashScreen.png", splashScreen,
5315                            false);
5316   ConvertToWindowsSlash(splashScreen);
5317   Elem(e1, "Image").Attribute("Include", splashScreen);
5318   this->AddedFiles.push_back(splashScreen);
5319
5320   if (this->AddedDefaultCertificate) {
5321     // This file has already been added to the build so don't copy it
5322     std::string keyFile =
5323       this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
5324     ConvertToWindowsSlash(keyFile);
5325     Elem(e1, "None").Attribute("Include", keyFile);
5326   }
5327 }
5328
5329 bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const
5330 {
5331   HANDLE h =
5332     CreateFileW(cmSystemTools::ConvertToWindowsExtendedPath(source).c_str(),
5333                 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING,
5334                 FILE_FLAG_BACKUP_SEMANTICS, 0);
5335   if (!h) {
5336     return false;
5337   }
5338
5339   FILETIME const ftime_20010101 = { 3365781504u, 29389701u };
5340   if (!SetFileTime(h, &ftime_20010101, &ftime_20010101, &ftime_20010101)) {
5341     CloseHandle(h);
5342     return false;
5343   }
5344
5345   CloseHandle(h);
5346   return true;
5347 }
5348
5349 void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties(
5350   cmSourceFile const* sf, std::map<std::string, std::string>& tags)
5351 {
5352   if (this->ProjectType == VsProjectType::csproj) {
5353     const cmPropertyMap& props = sf->GetProperties();
5354     for (const std::string& p : props.GetKeys()) {
5355       static const cm::string_view propNamePrefix = "VS_CSHARP_";
5356       if (cmHasPrefix(p, propNamePrefix)) {
5357         std::string tagName = p.substr(propNamePrefix.length());
5358         if (!tagName.empty()) {
5359           cmValue val = props.GetPropertyValue(p);
5360           if (cmNonempty(val)) {
5361             tags[tagName] = *val;
5362           } else {
5363             tags.erase(tagName);
5364           }
5365         }
5366       }
5367     }
5368   }
5369 }
5370
5371 void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties(
5372   Elem& e2, const std::map<std::string, std::string>& tags)
5373 {
5374   for (const auto& i : tags) {
5375     e2.Element(i.first, i.second);
5376   }
5377 }
5378
5379 std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
5380   cmSourceFile const* source)
5381 {
5382   // For out of source files, we first check if a matching source group
5383   // for this file exists, otherwise we check if the path relative to current
5384   // source- or binary-dir is used within the link and return that.
5385   // In case of .cs files we can't do that automatically for files in the
5386   // binary directory, because this leads to compilation errors.
5387   std::string link;
5388   std::string sourceGroupedFile;
5389   std::string const& fullFileName = source->GetFullPath();
5390   std::string const& srcDir = this->Makefile->GetCurrentSourceDirectory();
5391   std::string const& binDir = this->Makefile->GetCurrentBinaryDirectory();
5392   // unfortunately we have to copy the source groups, because
5393   // FindSourceGroup uses a regex which is modifying the group
5394   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
5395   cmSourceGroup* sourceGroup =
5396     this->Makefile->FindSourceGroup(fullFileName, sourceGroups);
5397   if (sourceGroup && !sourceGroup->GetFullName().empty()) {
5398     sourceGroupedFile = sourceGroup->GetFullName() + "/" +
5399       cmsys::SystemTools::GetFilenameName(fullFileName);
5400     cmsys::SystemTools::ConvertToUnixSlashes(sourceGroupedFile);
5401   }
5402
5403   if (!sourceGroupedFile.empty() &&
5404       cmHasSuffix(fullFileName, sourceGroupedFile)) {
5405     link = sourceGroupedFile;
5406   } else if (cmHasPrefix(fullFileName, srcDir)) {
5407     link = fullFileName.substr(srcDir.length() + 1);
5408   } else if (!cmHasSuffix(fullFileName, ".cs") &&
5409              cmHasPrefix(fullFileName, binDir)) {
5410     link = fullFileName.substr(binDir.length() + 1);
5411   } else if (cmValue l = source->GetProperty("VS_CSHARP_Link")) {
5412     link = *l;
5413   }
5414
5415   ConvertToWindowsSlash(link);
5416   return link;
5417 }
5418
5419 std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
5420   const char* relativeFilePath) const
5421 {
5422   // Always search in the standard modules location.
5423   std::string path =
5424     cmStrCat(cmSystemTools::GetCMakeRoot(), '/', relativeFilePath);
5425   ConvertToWindowsSlash(path);
5426
5427   return path;
5428 }
5429
5430 void cmVisualStudio10TargetGenerator::WriteStdOutEncodingUtf8(Elem& e1)
5431 {
5432   if (this->GlobalGenerator->IsUtf8EncodingSupported()) {
5433     e1.Element("UseUtf8Encoding", "Always");
5434   } else if (this->GlobalGenerator->IsStdOutEncodingSupported()) {
5435     e1.Element("StdOutEncoding", "UTF-8");
5436   }
5437 }
5438
5439 void cmVisualStudio10TargetGenerator::UpdateCache()
5440 {
5441   std::vector<std::string> packageReferences;
5442
5443   if (this->GeneratorTarget->HasPackageReferences()) {
5444     // Store a cache entry that later determines, if a package restore is
5445     // required.
5446     this->GeneratorTarget->Makefile->AddCacheDefinition(
5447       this->GeneratorTarget->GetName() + "_REQUIRES_VS_PACKAGE_RESTORE", "ON",
5448       "Value Computed by CMake", cmStateEnums::STATIC);
5449   } else {
5450     // If there are any dependencies that require package restore, inherit the
5451     // cache variable.
5452     cmGlobalGenerator::TargetDependSet const& unordered =
5453       this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
5454     using OrderedTargetDependSet =
5455       cmGlobalVisualStudioGenerator::OrderedTargetDependSet;
5456     OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
5457
5458     for (cmGeneratorTarget const* dt : depends) {
5459       if (dt->HasPackageReferences()) {
5460         this->GeneratorTarget->Makefile->AddCacheDefinition(
5461           this->GeneratorTarget->GetName() + "_REQUIRES_VS_PACKAGE_RESTORE",
5462           "ON", "Value Computed by CMake", cmStateEnums::STATIC);
5463       }
5464     }
5465   }
5466 }