1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the qmake application of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "msbuild_objectmodel.h"
30 
31 #include "msvc_objectmodel.h"
32 #include "msvc_vcproj.h"
33 #include "msvc_vcxproj.h"
34 #include <qscopedpointer.h>
35 #include <qstringlist.h>
36 #include <qfileinfo.h>
37 #include <qregexp.h>
38 
39 QT_BEGIN_NAMESPACE
40 
41 // XML Tags ---------------------------------------------------------
42 const char _CLCompile[]                         = "ClCompile";
43 const char _ItemGroup[]                         = "ItemGroup";
44 const char _Link[]                              = "Link";
45 const char _Lib[]                               = "Lib";
46 const char _Midl[]                              = "Midl";
47 const char _ResourceCompile[]                   = "ResourceCompile";
48 
49 // XML Properties ---------------------------------------------------
50 const char _AddModuleNamesToAssembly[]          = "AddModuleNamesToAssembly";
51 const char _AdditionalDependencies[]            = "AdditionalDependencies";
52 const char _AdditionalIncludeDirectories[]      = "AdditionalIncludeDirectories";
53 const char _AdditionalLibraryDirectories[]      = "AdditionalLibraryDirectories";
54 const char _AdditionalManifestDependencies[]    = "AdditionalManifestDependencies";
55 const char _AdditionalOptions[]                 = "AdditionalOptions";
56 const char _AdditionalUsingDirectories[]        = "AdditionalUsingDirectories";
57 const char _AllowIsolation[]                    = "AllowIsolation";
58 const char _ApplicationConfigurationMode[]      = "ApplicationConfigurationMode";
59 const char _AssemblerListingLocation[]          = "AssemblerListingLocation";
60 const char _AssemblerOutput[]                   = "AssemblerOutput";
61 const char _AssemblyDebug[]                     = "AssemblyDebug";
62 const char _AssemblyLinkResource[]              = "AssemblyLinkResource";
63 const char _ATLMinimizesCRunTimeLibraryUsage[]  = "ATLMinimizesCRunTimeLibraryUsage";
64 const char _BaseAddress[]                       = "BaseAddress";
65 const char _BasicRuntimeChecks[]                = "BasicRuntimeChecks";
66 const char _BrowseInformation[]                 = "BrowseInformation";
67 const char _BrowseInformationFile[]             = "BrowseInformationFile";
68 const char _BufferSecurityCheck[]               = "BufferSecurityCheck";
69 const char _BuildBrowserInformation[]           = "BuildBrowserInformation";
70 const char _CallingConvention[]                 = "CallingConvention";
71 const char _CharacterSet[]                      = "CharacterSet";
72 const char _ClientStubFile[]                    = "ClientStubFile";
73 const char _CLRImageType[]                      = "CLRImageType";
74 const char _CLRSupportLastError[]               = "CLRSupportLastError";
75 const char _CLRThreadAttribute[]                = "CLRThreadAttribute";
76 const char _CLRUnmanagedCodeCheck[]             = "CLRUnmanagedCodeCheck";
77 const char _Command[]                           = "Command";
78 const char _CompileAs[]                         = "CompileAs";
79 const char _CompileAsManaged[]                  = "CompileAsManaged";
80 const char _CompileAsWinRT[]                    = "CompileAsWinRT";
81 const char _ConfigurationType[]                 = "ConfigurationType";
82 const char _CPreprocessOptions[]                = "CPreprocessOptions";
83 const char _CreateHotpatchableImage[]           = "CreateHotpatchableImage";
84 const char _Culture[]                           = "Culture";
85 const char _DataExecutionPrevention[]           = "DataExecutionPrevention";
86 const char _DebugInformationFormat[]            = "DebugInformationFormat";
87 const char _DefaultCharType[]                   = "DefaultCharType";
88 const char _DelayLoadDLLs[]                     = "DelayLoadDLLs";
89 const char _DelaySign[]                         = "DelaySign";
90 const char _DeleteExtensionsOnClean[]           = "DeleteExtensionsOnClean";
91 const char _DisableLanguageExtensions[]         = "DisableLanguageExtensions";
92 const char _DisableSpecificWarnings[]           = "DisableSpecificWarnings";
93 const char _DLLDataFileName[]                   = "DLLDataFileName";
94 const char _EmbedManagedResourceFile[]          = "EmbedManagedResourceFile";
95 const char _EmbedManifest[]                     = "EmbedManifest";
96 const char _EnableCOMDATFolding[]               = "EnableCOMDATFolding";
97 const char _EnableUAC[]                         = "EnableUAC";
98 const char _EnableErrorChecks[]                 = "EnableErrorChecks";
99 const char _EnableEnhancedInstructionSet[]      = "EnableEnhancedInstructionSet";
100 const char _EnableFiberSafeOptimizations[]      = "EnableFiberSafeOptimizations";
101 const char _EnablePREfast[]                     = "EnablePREfast";
102 const char _EntryPointSymbol[]                  = "EntryPointSymbol";
103 const char _ErrorCheckAllocations[]             = "ErrorCheckAllocations";
104 const char _ErrorCheckBounds[]                  = "ErrorCheckBounds";
105 const char _ErrorCheckEnumRange[]               = "ErrorCheckEnumRange";
106 const char _ErrorCheckRefPointers[]             = "ErrorCheckRefPointers";
107 const char _ErrorCheckStubData[]                = "ErrorCheckStubData";
108 const char _ErrorReporting[]                    = "ErrorReporting";
109 const char _ExceptionHandling[]                 = "ExceptionHandling";
110 const char _ExpandAttributedSource[]            = "ExpandAttributedSource";
111 const char _ExportNamedFunctions[]              = "ExportNamedFunctions";
112 const char _FavorSizeOrSpeed[]                  = "FavorSizeOrSpeed";
113 const char _FloatingPointModel[]                = "FloatingPointModel";
114 const char _FloatingPointExceptions[]           = "FloatingPointExceptions";
115 const char _ForceConformanceInForLoopScope[]    = "ForceConformanceInForLoopScope";
116 const char _ForceSymbolReferences[]             = "ForceSymbolReferences";
117 const char _ForcedIncludeFiles[]                = "ForcedIncludeFiles";
118 const char _ForcedUsingFiles[]                  = "ForcedUsingFiles";
119 const char _FunctionLevelLinking[]              = "FunctionLevelLinking";
120 const char _FunctionOrder[]                     = "FunctionOrder";
121 const char _GenerateClientFiles[]               = "GenerateClientFiles";
122 const char _GenerateDebugInformation[]          = "GenerateDebugInformation";
123 const char _GenerateManifest[]                  = "GenerateManifest";
124 const char _GenerateMapFile[]                   = "GenerateMapFile";
125 const char _GenerateServerFiles[]               = "GenerateServerFiles";
126 const char _GenerateStublessProxies[]           = "GenerateStublessProxies";
127 const char _GenerateTypeLibrary[]               = "GenerateTypeLibrary";
128 const char _GenerateWindowsMetadata[]           = "GenerateWindowsMetadata";
129 const char _GenerateXMLDocumentationFiles[]     = "GenerateXMLDocumentationFiles";
130 const char _HeaderFileName[]                    = "HeaderFileName";
131 const char _HeapCommitSize[]                    = "HeapCommitSize";
132 const char _HeapReserveSize[]                   = "HeapReserveSize";
133 const char _IgnoreAllDefaultLibraries[]         = "IgnoreAllDefaultLibraries";
134 const char _IgnoreEmbeddedIDL[]                 = "IgnoreEmbeddedIDL";
135 const char _IgnoreImportLibrary[]               = "IgnoreImportLibrary";
136 const char _ImageHasSafeExceptionHandlers[]     = "ImageHasSafeExceptionHandlers";
137 const char _IgnoreSpecificDefaultLibraries[]    = "IgnoreSpecificDefaultLibraries";
138 const char _IgnoreStandardIncludePath[]         = "IgnoreStandardIncludePath";
139 const char _ImportLibrary[]                     = "ImportLibrary";
140 const char _InlineFunctionExpansion[]           = "InlineFunctionExpansion";
141 const char _IntrinsicFunctions[]                = "IntrinsicFunctions";
142 const char _InterfaceIdentifierFileName[]       = "InterfaceIdentifierFileName";
143 const char _IntermediateDirectory[]             = "IntermediateDirectory";
144 const char _KeyContainer[]                      = "KeyContainer";
145 const char _KeyFile[]                           = "KeyFile";
146 const char _LanguageStandard[]                  = "LanguageStandard";
147 const char _LargeAddressAware[]                 = "LargeAddressAware";
148 const char _LinkDLL[]                           = "LinkDLL";
149 const char _LinkErrorReporting[]                = "LinkErrorReporting";
150 const char _LinkIncremental[]                   = "LinkIncremental";
151 const char _LinkStatus[]                        = "LinkStatus";
152 const char _LinkTimeCodeGeneration[]            = "LinkTimeCodeGeneration";
153 const char _LocaleID[]                          = "LocaleID";
154 const char _ManifestFile[]                      = "ManifestFile";
155 const char _MapExports[]                        = "MapExports";
156 const char _MapFileName[]                       = "MapFileName";
157 const char _MergedIDLBaseFileName[]             = "MergedIDLBaseFileName";
158 const char _MergeSections[]                     = "MergeSections";
159 const char _Message[]                           = "Message";
160 const char _MidlCommandFile[]                   = "MidlCommandFile";
161 const char _MinimalRebuild[]                    = "MinimalRebuild";
162 const char _MkTypLibCompatible[]                = "MkTypLibCompatible";
163 const char _ModuleDefinitionFile[]              = "ModuleDefinitionFile";
164 const char _MultiProcessorCompilation[]         = "MultiProcessorCompilation";
165 const char _Name[]                              = "Name";
166 const char _NoEntryPoint[]                      = "NoEntryPoint";
167 const char _ObjectFileName[]                    = "ObjectFileName";
168 const char _OmitDefaultLibName[]                = "OmitDefaultLibName";
169 const char _OmitFramePointers[]                 = "OmitFramePointers";
170 const char _OpenMPSupport[]                     = "OpenMPSupport";
171 const char _Optimization[]                      = "Optimization";
172 const char _OptimizeReferences[]                = "OptimizeReferences";
173 const char _OutputDirectory[]                   = "OutputDirectory";
174 const char _OutputFile[]                        = "OutputFile";
175 const char _PlatformToolSet[]                   = "PlatformToolset";
176 const char _PrecompiledHeader[]                 = "PrecompiledHeader";
177 const char _PrecompiledHeaderFile[]             = "PrecompiledHeaderFile";
178 const char _PrecompiledHeaderOutputFile[]       = "PrecompiledHeaderOutputFile";
179 const char _PreprocessorDefinitions[]           = "PreprocessorDefinitions";
180 const char _PreprocessKeepComments[]            = "PreprocessKeepComments";
181 const char _PreprocessOutputPath[]              = "PreprocessOutputPath";
182 const char _PreprocessSuppressLineNumbers[]     = "PreprocessSuppressLineNumbers";
183 const char _PreprocessToFile[]                  = "PreprocessToFile";
184 const char _PreventDllBinding[]                 = "PreventDllBinding";
185 const char _PrimaryOutput[]                     = "PrimaryOutput";
186 const char _ProcessorNumber[]                   = "ProcessorNumber";
187 const char _ProgramDatabase[]                   = "ProgramDatabase";
188 const char _ProgramDataBaseFileName[]           = "ProgramDataBaseFileName";
189 const char _ProgramDatabaseFile[]               = "ProgramDatabaseFile";
190 const char _ProxyFileName[]                     = "ProxyFileName";
191 const char _RandomizedBaseAddress[]             = "RandomizedBaseAddress";
192 const char _RedirectOutputAndErrors[]           = "RedirectOutputAndErrors";
193 const char _RegisterOutput[]                    = "RegisterOutput";
194 const char _ResourceOutputFileName[]            = "ResourceOutputFileName";
195 const char _RuntimeLibrary[]                    = "RuntimeLibrary";
196 const char _RuntimeTypeInfo[]                   = "RuntimeTypeInfo";
197 const char _SectionAlignment[]                  = "SectionAlignment";
198 const char _ServerStubFile[]                    = "ServerStubFile";
199 const char _SetChecksum[]                       = "SetChecksum";
200 const char _ShowIncludes[]                      = "ShowIncludes";
201 const char _ShowProgress[]                      = "ShowProgress";
202 const char _SmallerTypeCheck[]                  = "SmallerTypeCheck";
203 const char _StackCommitSize[]                   = "StackCommitSize";
204 const char _StackReserveSize[]                  = "StackReserveSize";
205 const char _StringPooling[]                     = "StringPooling";
206 const char _StripPrivateSymbols[]               = "StripPrivateSymbols";
207 const char _StructMemberAlignment[]             = "StructMemberAlignment";
208 const char _SubSystem[]                         = "SubSystem";
209 const char _SupportUnloadOfDelayLoadedDLL[]     = "SupportUnloadOfDelayLoadedDLL";
210 const char _SuppressCompilerWarnings[]          = "SuppressCompilerWarnings";
211 const char _SuppressStartupBanner[]             = "SuppressStartupBanner";
212 const char _SwapRunFromCD[]                     = "SwapRunFromCD";
213 const char _SwapRunFromNet[]                    = "SwapRunFromNet";
214 const char _TargetEnvironment[]                 = "TargetEnvironment";
215 const char _TargetMachine[]                     = "TargetMachine";
216 const char _TerminalServerAware[]               = "TerminalServerAware";
217 const char _TreatLinkerWarningAsErrors[]        = "TreatLinkerWarningAsErrors";
218 const char _TreatSpecificWarningsAsErrors[]     = "TreatSpecificWarningsAsErrors";
219 const char _TreatWarningAsError[]               = "TreatWarningAsError";
220 const char _TreatWChar_tAsBuiltInType[]         = "TreatWChar_tAsBuiltInType";
221 const char _TurnOffAssemblyGeneration[]         = "TurnOffAssemblyGeneration";
222 const char _TypeLibFormat[]                     = "TypeLibFormat";
223 const char _TypeLibraryFile[]                   = "TypeLibraryFile";
224 const char _TypeLibraryName[]                   = "TypeLibraryName";
225 const char _TypeLibraryResourceID[]             = "TypeLibraryResourceID";
226 const char _UACExecutionLevel[]                 = "UACExecutionLevel";
227 const char _UACUIAccess[]                       = "UACUIAccess";
228 const char _UndefineAllPreprocessorDefinitions[]= "UndefineAllPreprocessorDefinitions";
229 const char _UndefinePreprocessorDefinitions[]   = "UndefinePreprocessorDefinitions";
230 const char _UseFullPaths[]                      = "UseFullPaths";
231 const char _UseOfATL[]                          = "UseOfATL";
232 const char _UseOfMfc[]                          = "UseOfMfc";
233 const char _UseUnicodeForAssemblerListing[]     = "UseUnicodeForAssemblerListing";
234 const char _ValidateAllParameters[]             = "ValidateAllParameters";
235 const char _Version[]                           = "Version";
236 const char _WarnAsError[]                       = "WarnAsError";
237 const char _WarningLevel[]                      = "WarningLevel";
238 const char _WholeProgramOptimization[]          = "WholeProgramOptimization";
239 const char _WindowsMetadataFile[]               = "WindowsMetadataFile";
240 const char _XMLDocumentationFileName[]          = "XMLDocumentationFileName";
241 
242 
243 // XmlOutput stream functions ------------------------------
attrTagT(const char * name,const triState v)244 inline XmlOutput::xml_output attrTagT(const char *name, const triState v)
245 {
246     if(v == unset)
247         return noxml();
248     return tagValue(name, (v == _True ? "true" : "false"));
249 }
250 
attrTagL(const char * name,qint64 v)251 inline XmlOutput::xml_output attrTagL(const char *name, qint64 v)
252 {
253     return tagValue(name, QString::number(v));
254 }
255 
256 /*ifNot version*/
attrTagL(const char * name,qint64 v,qint64 ifn)257 inline XmlOutput::xml_output attrTagL(const char *name, qint64 v, qint64 ifn)
258 {
259     if (v == ifn)
260         return noxml();
261     return tagValue(name, QString::number(v));
262 }
263 
attrTagS(const char * name,const QString & v)264 inline XmlOutput::xml_output attrTagS(const char *name, const QString &v)
265 {
266     if(v.isEmpty())
267         return noxml();
268     return tagValue(name, v);
269 }
270 
attrTagX(const char * name,const QStringList & v,const char * s=",")271 inline XmlOutput::xml_output attrTagX(const char *name, const QStringList &v, const char *s = ",")
272 {
273     if(v.isEmpty())
274         return noxml();
275     QStringList temp = v;
276     temp.append(QString("%(%1)").arg(name));
277     return tagValue(name, temp.join(s));
278 }
279 
valueTagX(const QStringList & v,const char * s=" ")280 inline XmlOutput::xml_output valueTagX(const QStringList &v, const char *s = " ")
281 {
282     if(v.isEmpty())
283         return noxml();
284     return valueTag(v.join(s));
285 }
286 
valueTagDefX(const QStringList & v,const QString & tagName,const char * s=" ")287 inline XmlOutput::xml_output valueTagDefX(const QStringList &v, const QString &tagName, const char *s = " ")
288 {
289     if(v.isEmpty())
290         return noxml();
291     QStringList temp = v;
292     temp.append(QString("%(%1)").arg(tagName));
293     return valueTag(temp.join(s));
294 }
295 
valueTagT(const triState v)296 inline XmlOutput::xml_output valueTagT( const triState v)
297 {
298     if(v == unset)
299         return noxml();
300     return valueTag(v == _True ? "true" : "false");
301 }
302 
commandLinesForOutput(QStringList commands)303 static QString commandLinesForOutput(QStringList commands)
304 {
305     // MSBuild puts the contents of the custom commands into a batch file and calls it.
306     // As we want every sub-command to be error-checked (as is done by makefile-based
307     // backends), we insert the checks ourselves, using the undocumented jump target.
308     static QString errchk = QStringLiteral("if errorlevel 1 goto VCEnd");
309     for (int i = commands.count() - 2; i >= 0; --i) {
310         if (!commands.at(i).startsWith("rem", Qt::CaseInsensitive))
311             commands.insert(i + 1, errchk);
312     }
313     return commands.join("\r\n");
314 }
315 
unquote(const QString & value)316 static QString unquote(const QString &value)
317 {
318     QString result = value;
319     result.replace(QLatin1String("\\\""), QLatin1String("\""));
320     return result;
321 }
322 
unquote(const QStringList & values)323 static QStringList unquote(const QStringList &values)
324 {
325     QStringList result;
326     result.reserve(values.size());
327     for (int i = 0; i < values.count(); ++i)
328         result << unquote(values.at(i));
329     return result;
330 }
331 
332 // Tree file generation ---------------------------------------------
generateXML(XmlOutput & xml,XmlOutput & xmlFilter,const QString & tagName,VCProject & tool,const QString & filter)333 void XTreeNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName,
334                             VCProject &tool, const QString &filter)
335 {
336     if (children.size()) {
337         // Filter
338         QString tempFilterName;
339         ChildrenMap::ConstIterator it, end = children.constEnd();
340         if (!tagName.isEmpty()) {
341             tempFilterName.append(filter);
342             tempFilterName.append("\\");
343             tempFilterName.append(tagName);
344             xmlFilter << tag(_ItemGroup);
345             xmlFilter << tag("Filter")
346                       << attrTag("Include", tempFilterName)
347                       << closetag();
348             xmlFilter << closetag();
349         }
350         // First round, do nested filters
351         for (it = children.constBegin(); it != end; ++it)
352             if ((*it)->children.size())
353             {
354                 if ( !tempFilterName.isEmpty() )
355                     (*it)->generateXML(xml, xmlFilter, it.key(), tool, tempFilterName);
356                 else
357                     (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter);
358             }
359         // Second round, do leafs
360         for (it = children.constBegin(); it != end; ++it)
361             if (!(*it)->children.size())
362             {
363                 if ( !tempFilterName.isEmpty() )
364                     (*it)->generateXML(xml, xmlFilter, it.key(), tool, tempFilterName);
365                 else
366                     (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter);
367             }
368     } else {
369         // Leaf
370         xml << tag(_ItemGroup);
371         xmlFilter << tag(_ItemGroup);
372         VCXProjectWriter::outputFileConfigs(tool, xml, xmlFilter, info, filter);
373         xmlFilter << closetag();
374         xml << closetag();
375     }
376 }
377 
378 // Flat file generation ---------------------------------------------
generateXML(XmlOutput & xml,XmlOutput & xmlFilter,const QString &,VCProject & tool,const QString & filter)379 void XFlatNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &/*tagName*/,
380                             VCProject &tool, const QString &filter)
381 {
382     if (children.size()) {
383         ChildrenMapFlat::ConstIterator it = children.constBegin();
384         ChildrenMapFlat::ConstIterator end = children.constEnd();
385         xml << tag(_ItemGroup);
386         xmlFilter << tag(_ItemGroup);
387         for (; it != end; ++it) {
388             VCXProjectWriter::outputFileConfigs(tool, xml, xmlFilter, (*it), filter);
389         }
390         xml << closetag();
391         xmlFilter << closetag();
392     }
393 }
394 
write(XmlOutput & xml,VCProjectSingleConfig & tool)395 void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool)
396 {
397     xml.setIndentString("  ");
398 
399     xml << decl("1.0", "utf-8")
400         << tag("Project")
401         << attrTag("DefaultTargets","Build")
402         << attrTagToolsVersion(tool.Configuration)
403         << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")
404         << tag("ItemGroup")
405         << attrTag("Label", "ProjectConfigurations");
406 
407     xml << tag("ProjectConfiguration")
408         << attrTag("Include" , tool.Configuration.Name)
409         << tagValue("Configuration", tool.Configuration.ConfigurationName)
410         << tagValue("Platform", tool.PlatformName)
411         << closetag();
412 
413     xml << closetag()
414         << tag("PropertyGroup")
415         << attrTag("Label", "Globals")
416         << tagValue("ProjectGuid", tool.ProjectGUID)
417         << tagValue("RootNamespace", tool.Name)
418         << tagValue("Keyword", tool.Keyword)
419         << closetag();
420 
421     // config part.
422     xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
423 
424     write(xml, tool.Configuration);
425     const QString condition = generateCondition(tool.Configuration);
426 
427     xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
428 
429     // Extension settings
430     xml << tag("ImportGroup")
431         << attrTag("Label", "ExtensionSettings")
432         << closetag();
433 
434     // PropertySheets
435     xml << tag("ImportGroup")
436         << attrTag("Condition", condition)
437         << attrTag("Label", "PropertySheets");
438 
439     xml << tag("Import")
440         << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props")
441         << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')")
442         << closetag()
443         << closetag();
444 
445     // UserMacros
446     xml << tag("PropertyGroup")
447         << attrTag("Label", "UserMacros")
448         << closetag();
449 
450     xml << tag("PropertyGroup");
451 
452     if ( !tool.Configuration.OutputDirectory.isEmpty() ) {
453         xml<< tag("OutDir")
454             << attrTag("Condition", condition)
455             << valueTag(tool.Configuration.OutputDirectory);
456     }
457     if ( !tool.Configuration.IntermediateDirectory.isEmpty() ) {
458         xml<< tag("IntDir")
459             << attrTag("Condition", condition)
460             << valueTag(tool.Configuration.IntermediateDirectory);
461     }
462     if ( !tool.Configuration.PrimaryOutput.isEmpty() ) {
463         xml<< tag("TargetName")
464             << attrTag("Condition", condition)
465             << valueTag(tool.Configuration.PrimaryOutput);
466     }
467     if (!tool.Configuration.PrimaryOutputExtension.isEmpty()) {
468         xml<< tag("TargetExt")
469             << attrTag("Condition", condition)
470             << valueTag(tool.Configuration.PrimaryOutputExtension);
471     }
472     if ( tool.Configuration.linker.IgnoreImportLibrary != unset) {
473         xml<< tag("IgnoreImportLibrary")
474             << attrTag("Condition", condition)
475             << valueTagT(tool.Configuration.linker.IgnoreImportLibrary);
476     }
477 
478     if ( tool.Configuration.linker.LinkIncremental != linkIncrementalDefault) {
479         const triState ts = (tool.Configuration.linker.LinkIncremental == linkIncrementalYes ? _True : _False);
480         xml<< tag("LinkIncremental")
481             << attrTag("Condition", condition)
482             << valueTagT(ts);
483     }
484 
485     if ( tool.Configuration.preBuild.ExcludedFromBuild != unset )
486     {
487         xml<< tag("PreBuildEventUseInBuild")
488             << attrTag("Condition", condition)
489             << valueTagT(!tool.Configuration.preBuild.ExcludedFromBuild);
490     }
491 
492     if ( tool.Configuration.preLink.ExcludedFromBuild != unset )
493     {
494         xml<< tag("PreLinkEventUseInBuild")
495             << attrTag("Condition", condition)
496             << valueTagT(!tool.Configuration.preLink.ExcludedFromBuild);
497     }
498 
499     if ( tool.Configuration.postBuild.ExcludedFromBuild != unset )
500     {
501         xml<< tag("PostBuildEventUseInBuild")
502             << attrTag("Condition", condition)
503             << valueTagT(!tool.Configuration.postBuild.ExcludedFromBuild);
504     }
505     xml << closetag();
506 
507     xml << tag("ItemDefinitionGroup")
508         << attrTag("Condition", condition);
509 
510     // ClCompile
511     write(xml, tool.Configuration.compiler);
512 
513     // Link
514     write(xml, tool.Configuration.linker);
515 
516     // Midl
517     write(xml, tool.Configuration.idl);
518 
519     // ResourceCompiler
520     write(xml, tool.Configuration.resource);
521 
522     // Post build event
523     if ( tool.Configuration.postBuild.ExcludedFromBuild != unset )
524         write(xml, tool.Configuration.postBuild);
525 
526     // Pre build event
527     if ( tool.Configuration.preBuild.ExcludedFromBuild != unset )
528         write(xml, tool.Configuration.preBuild);
529 
530     // Pre link event
531     if ( tool.Configuration.preLink.ExcludedFromBuild != unset )
532         write(xml, tool.Configuration.preLink);
533 
534     xml << closetag();
535 
536     QFile filterFile;
537     filterFile.setFileName(Option::output.fileName().append(".filters"));
538     filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
539     QTextStream ts(&filterFile);
540     XmlOutput xmlFilter(ts, XmlOutput::NoConversion);
541 
542     xmlFilter.setIndentString("  ");
543 
544     xmlFilter << decl("1.0", "utf-8")
545               << tag("Project")
546               << attrTagToolsVersion(tool.Configuration)
547               << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
548 
549     xmlFilter << tag("ItemGroup");
550 
551     VCProject tempProj;
552     tempProj.SingleProjects += tool;
553 
554     addFilters(tempProj, xmlFilter, "Form Files");
555     addFilters(tempProj, xmlFilter, "Generated Files");
556     addFilters(tempProj, xmlFilter, "Header Files");
557     addFilters(tempProj, xmlFilter, "LexYacc Files");
558     addFilters(tempProj, xmlFilter, "Resource Files");
559     addFilters(tempProj, xmlFilter, "Source Files");
560     addFilters(tempProj, xmlFilter, "Translation Files");
561     addFilters(tempProj, xmlFilter, "Deployment Files");
562     addFilters(tempProj, xmlFilter, "Distribution Files");
563 
564     tempProj.ExtraCompilers.reserve(tool.ExtraCompilersFiles.size());
565     std::transform(tool.ExtraCompilersFiles.cbegin(), tool.ExtraCompilersFiles.cend(),
566                    std::back_inserter(tempProj.ExtraCompilers),
567                    [] (const VCFilter &filter) { return filter.Name; });
568     tempProj.ExtraCompilers.removeDuplicates();
569 
570     for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x)
571         addFilters(tempProj, xmlFilter, tempProj.ExtraCompilers.at(x));
572 
573     xmlFilter << closetag();
574 
575     outputFilter(tempProj, xml, xmlFilter, "Source Files");
576     outputFilter(tempProj, xml, xmlFilter, "Header Files");
577     outputFilter(tempProj, xml, xmlFilter, "Generated Files");
578     outputFilter(tempProj, xml, xmlFilter, "LexYacc Files");
579     outputFilter(tempProj, xml, xmlFilter, "Translation Files");
580     outputFilter(tempProj, xml, xmlFilter, "Form Files");
581     outputFilter(tempProj, xml, xmlFilter, "Resource Files");
582     outputFilter(tempProj, xml, xmlFilter, "Deployment Files");
583     outputFilter(tempProj, xml, xmlFilter, "Distribution Files");
584 
585     for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) {
586         outputFilter(tempProj, xml, xmlFilter, tempProj.ExtraCompilers.at(x));
587     }
588 
589     outputFilter(tempProj, xml, xmlFilter, "Root Files");
590 
591     xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
592 
593     xml << tag("ImportGroup")
594         << attrTag("Label", "ExtensionTargets")
595         << closetag();
596 }
597 
write(XmlOutput & xml,VCProject & tool)598 void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
599 {
600     if (tool.SingleProjects.count() == 0) {
601         warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output");
602         return;
603     }
604 
605     xml.setIndentString("  ");
606 
607     xml << decl("1.0", "utf-8")
608         << tag("Project")
609         << attrTag("DefaultTargets","Build")
610         << attrTagToolsVersion(tool.SingleProjects.first().Configuration)
611         << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")
612         << tag("ItemGroup")
613         << attrTag("Label", "ProjectConfigurations");
614 
615     bool isWinRT = false;
616     for (int i = 0; i < tool.SingleProjects.count(); ++i) {
617         xml << tag("ProjectConfiguration")
618             << attrTag("Include" , tool.SingleProjects.at(i).Configuration.Name)
619             << tagValue("Configuration", tool.SingleProjects.at(i).Configuration.ConfigurationName)
620             << tagValue("Platform", tool.SingleProjects.at(i).PlatformName)
621             << closetag();
622         isWinRT = isWinRT || tool.SingleProjects.at(i).Configuration.WinRT;
623     }
624 
625     xml << closetag()
626         << tag("PropertyGroup")
627         << attrTag("Label", "Globals")
628         << tagValue("ProjectGuid", tool.ProjectGUID)
629         << tagValue("RootNamespace", tool.Name)
630         << tagValue("Keyword", tool.Keyword);
631 
632     if (isWinRT) {
633         xml << tagValue("MinimumVisualStudioVersion", tool.Version)
634             << tagValue("DefaultLanguage", "en")
635             << tagValue("AppContainerApplication", "true")
636             << tagValue("ApplicationType", "Windows Store")
637             << tagValue("ApplicationTypeRevision", tool.SdkVersion);
638     }
639     if (!tool.WindowsTargetPlatformVersion.isEmpty())
640         xml << tagValue("WindowsTargetPlatformVersion", tool.WindowsTargetPlatformVersion);
641     if (!tool.WindowsTargetPlatformMinVersion.isEmpty())
642         xml << tagValue("WindowsTargetPlatformMinVersion", tool.WindowsTargetPlatformMinVersion);
643 
644     xml << closetag();
645 
646     // config part.
647     xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
648     for (int i = 0; i < tool.SingleProjects.count(); ++i)
649         write(xml, tool.SingleProjects.at(i).Configuration);
650     xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
651 
652     // Extension settings
653     xml << tag("ImportGroup")
654         << attrTag("Label", "ExtensionSettings")
655         << closetag();
656 
657     // PropertySheets
658     for (int i = 0; i < tool.SingleProjects.count(); ++i) {
659         xml << tag("ImportGroup")
660             << attrTag("Condition", generateCondition(tool.SingleProjects.at(i).Configuration))
661             << attrTag("Label", "PropertySheets");
662 
663         xml << tag("Import")
664             << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props")
665             << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')")
666             << closetag()
667             << closetag();
668     }
669 
670     // UserMacros
671     xml << tag("PropertyGroup")
672         << attrTag("Label", "UserMacros")
673         << closetag();
674 
675     xml << tag("PropertyGroup");
676     for (int i = 0; i < tool.SingleProjects.count(); ++i) {
677         const VCConfiguration &config = tool.SingleProjects.at(i).Configuration;
678         const QString condition = generateCondition(config);
679 
680         if (!config.OutputDirectory.isEmpty()) {
681             xml << tag("OutDir")
682                 << attrTag("Condition", condition)
683                 << valueTag(config.OutputDirectory);
684         }
685         if (!config.IntermediateDirectory.isEmpty()) {
686             xml << tag("IntDir")
687                 << attrTag("Condition", condition)
688                 << valueTag(config.IntermediateDirectory);
689         }
690         if (!config.PrimaryOutput.isEmpty()) {
691             xml << tag("TargetName")
692                 << attrTag("Condition", condition)
693                 << valueTag(config.PrimaryOutput);
694         }
695         if (!config.PrimaryOutputExtension.isEmpty()) {
696             xml << tag("TargetExt")
697                 << attrTag("Condition", condition)
698                 << valueTag(config.PrimaryOutputExtension);
699         }
700         if (config.linker.IgnoreImportLibrary != unset) {
701             xml << tag("IgnoreImportLibrary")
702                 << attrTag("Condition", condition)
703                 << valueTagT(config.linker.IgnoreImportLibrary);
704         }
705 
706         if (config.linker.LinkIncremental != linkIncrementalDefault) {
707             const triState ts = (config.linker.LinkIncremental == linkIncrementalYes ? _True : _False);
708             xml << tag("LinkIncremental")
709                 << attrTag("Condition", condition)
710                 << valueTagT(ts);
711         }
712 
713         const triState generateManifest = config.linker.GenerateManifest;
714         if (generateManifest != unset) {
715             xml << tag("GenerateManifest")
716                 << attrTag("Condition", condition)
717                 << valueTagT(generateManifest);
718         }
719 
720         if (config.preBuild.ExcludedFromBuild != unset)
721         {
722             xml << tag("PreBuildEventUseInBuild")
723                 << attrTag("Condition", condition)
724                 << valueTagT(!config.preBuild.ExcludedFromBuild);
725         }
726 
727         if (config.preLink.ExcludedFromBuild != unset)
728         {
729             xml << tag("PreLinkEventUseInBuild")
730                 << attrTag("Condition", condition)
731                 << valueTagT(!config.preLink.ExcludedFromBuild);
732         }
733 
734         if (config.postBuild.ExcludedFromBuild != unset)
735         {
736             xml << tag("PostBuildEventUseInBuild")
737                 << attrTag("Condition", condition)
738                 << valueTagT(!config.postBuild.ExcludedFromBuild);
739         }
740     }
741     xml << closetag();
742 
743     for (int i = 0; i < tool.SingleProjects.count(); ++i) {
744         const VCConfiguration &config = tool.SingleProjects.at(i).Configuration;
745 
746         xml << tag("ItemDefinitionGroup")
747             << attrTag("Condition", generateCondition(config));
748 
749         // ClCompile
750         write(xml, config.compiler);
751 
752         // Librarian / Linker
753         if (config.ConfigurationType == typeStaticLibrary)
754             write(xml, config.librarian);
755         else
756             write(xml, config.linker);
757 
758         // Midl
759         write(xml, config.idl);
760 
761         // ResourceCompiler
762         write(xml, config.resource);
763 
764         // Post build event
765         if (config.postBuild.ExcludedFromBuild != unset)
766             write(xml, config.postBuild);
767 
768         // Pre build event
769         if (config.preBuild.ExcludedFromBuild != unset)
770             write(xml, config.preBuild);
771 
772         // Pre link event
773         if (config.preLink.ExcludedFromBuild != unset)
774             write(xml, config.preLink);
775 
776         xml << closetag();
777 
778         // windeployqt
779         if (!config.windeployqt.ExcludedFromBuild)
780             write(xml, config.windeployqt);
781     }
782 
783     // The file filters are added in a separate file for MSBUILD.
784     QFile filterFile;
785     filterFile.setFileName(Option::output.fileName().append(".filters"));
786     filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
787     QTextStream ts(&filterFile);
788     XmlOutput xmlFilter(ts, XmlOutput::NoConversion);
789 
790     xmlFilter.setIndentString("  ");
791 
792     xmlFilter << decl("1.0", "utf-8")
793               << tag("Project")
794               << attrTagToolsVersion(tool.SingleProjects.first().Configuration)
795               << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
796 
797     xmlFilter << tag("ItemGroup");
798 
799     addFilters(tool, xmlFilter, "Form Files");
800     addFilters(tool, xmlFilter, "Generated Files");
801     addFilters(tool, xmlFilter, "Header Files");
802     addFilters(tool, xmlFilter, "LexYacc Files");
803     addFilters(tool, xmlFilter, "Resource Files");
804     addFilters(tool, xmlFilter, "Source Files");
805     addFilters(tool, xmlFilter, "Translation Files");
806     addFilters(tool, xmlFilter, "Deployment Files");
807     addFilters(tool, xmlFilter, "Distribution Files");
808 
809     for (int x = 0; x < tool.ExtraCompilers.count(); ++x)
810         addFilters(tool, xmlFilter, tool.ExtraCompilers.at(x));
811 
812     xmlFilter << closetag();
813 
814     outputFilter(tool, xml, xmlFilter, "Source Files");
815     outputFilter(tool, xml, xmlFilter, "Header Files");
816     outputFilter(tool, xml, xmlFilter, "Generated Files");
817     outputFilter(tool, xml, xmlFilter, "LexYacc Files");
818     outputFilter(tool, xml, xmlFilter, "Translation Files");
819     outputFilter(tool, xml, xmlFilter, "Form Files");
820     outputFilter(tool, xml, xmlFilter, "Resource Files");
821     outputFilter(tool, xml, xmlFilter, "Deployment Files");
822     outputFilter(tool, xml, xmlFilter, "Distribution Files");
823     for (int x = 0; x < tool.ExtraCompilers.count(); ++x) {
824         outputFilter(tool, xml, xmlFilter, tool.ExtraCompilers.at(x));
825     }
826     outputFilter(tool, xml, xmlFilter, "Root Files");
827 
828     // App manifest
829     if (isWinRT) {
830         const QString manifest = QStringLiteral("Package.appxmanifest");
831 
832         // Find all icons referenced in the manifest
833         QSet<QString> icons;
834         QFile manifestFile(Option::output_dir + QLatin1Char('/') + manifest);
835         if (manifestFile.open(QFile::ReadOnly)) {
836             const QString contents = manifestFile.readAll();
837             QRegExp regexp("[\\\\/a-zA-Z0-9_\\-\\!]*\\.(png|jpg|jpeg)");
838             int pos = 0;
839             while (pos > -1) {
840                 pos = regexp.indexIn(contents, pos);
841                 if (pos >= 0) {
842                     const QString match = regexp.cap(0);
843                     icons.insert(match);
844                     pos += match.length();
845                 }
846             }
847         }
848 
849         // Write out manifest + icons as content items
850         xml << tag(_ItemGroup)
851             << tag("AppxManifest")
852             << attrTag("Include", manifest)
853             << closetag();
854         for (const QString &icon : qAsConst(icons)) {
855             xml << tag("Image")
856                 << attrTag("Include", icon)
857                 << closetag();
858         }
859         xml << closetag();
860     }
861 
862     xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets")
863         << tag("ImportGroup")
864         << attrTag("Label", "ExtensionTargets")
865         << closetag();
866 }
867 
toString(asmListingOption option)868 static inline QString toString(asmListingOption option)
869 {
870     switch (option) {
871     case asmListingNone:
872         break;
873     case asmListingAsmMachine:
874         return "AssemblyAndMachineCode";
875     case asmListingAsmMachineSrc:
876         return "All";
877     case asmListingAsmSrc:
878         return "AssemblyAndSourceCode";
879     case asmListingAssemblyOnly:
880         return "AssemblyCode";
881     }
882     return QString();
883 }
884 
toString(basicRuntimeCheckOption option)885 static inline QString toString(basicRuntimeCheckOption option)
886 {
887     switch (option) {
888     case runtimeBasicCheckNone:
889         return "";
890     case runtimeCheckStackFrame:
891         return "StackFrameRuntimeCheck";
892     case runtimeCheckUninitVariables:
893         return "UninitializedLocalUsageCheck";
894     case runtimeBasicCheckAll:
895         return "EnableFastChecks";
896     }
897     return QString();
898 }
899 
toString(callingConventionOption option)900 static inline QString toString(callingConventionOption option)
901 {
902     switch (option) {
903     case callConventionDefault:
904         break;
905     case callConventionCDecl:
906         return "Cdecl";
907     case callConventionFastCall:
908         return "FastCall";
909     case callConventionStdCall:
910         return "StdCall";
911     }
912     return QString();
913 }
914 
toString(CompileAsOptions option)915 static inline QString toString(CompileAsOptions option)
916 {
917     switch (option) {
918     case compileAsDefault:
919         break;
920     case compileAsC:
921         return "CompileAsC";
922     case compileAsCPlusPlus:
923         return "CompileAsCpp";
924     }
925     return QString();
926 }
927 
toString(compileAsManagedOptions option)928 static inline QString toString(compileAsManagedOptions option)
929 {
930     switch (option) {
931     case managedDefault:
932     case managedAssemblySafe:
933         break;
934     case managedAssembly:
935         return "true";
936     case managedAssemblyPure:
937         return "Safe";
938     case managedAssemblyOldSyntax:
939         return "OldSyntax";
940     }
941     return QString();
942 }
943 
toString(debugOption option,DotNET compilerVersion)944 static inline QString toString(debugOption option, DotNET compilerVersion)
945 {
946     switch (option) {
947     case debugUnknown:
948     case debugLineInfoOnly:
949         break;
950     case debugDisabled:
951         if (compilerVersion <= NET2010)
952             break;
953         return "None";
954     case debugOldStyleInfo:
955         return "OldStyle";
956     case debugEditAndContinue:
957         return "EditAndContinue";
958     case debugEnabled:
959         return "ProgramDatabase";
960     }
961     return QString();
962 }
963 
toString(enhancedInstructionSetOption option)964 static inline QString toString(enhancedInstructionSetOption option)
965 {
966     switch (option) {
967     case archNotSet:
968         break;
969     case archSSE:
970         return "StreamingSIMDExtensions";
971     case archSSE2:
972         return "StreamingSIMDExtensions2";
973     }
974     return QString();
975 }
976 
toString(exceptionHandling option)977 static inline QString toString(exceptionHandling option)
978 {
979     switch (option) {
980     case ehDefault:
981         break;
982     case ehNone:
983         return "false";
984     case ehNoSEH:
985         return "Sync";
986     case ehSEH:
987         return "Async";
988     }
989     return QString();
990 }
991 
toString(favorSizeOrSpeedOption option)992 static inline QString toString(favorSizeOrSpeedOption option)
993 {
994     switch (option) {
995     case favorNone:
996         break;
997     case favorSize:
998         return "Size";
999     case favorSpeed:
1000         return "Speed";
1001     }
1002     return QString();
1003 }
1004 
toString(floatingPointModel option)1005 static inline QString toString(floatingPointModel option)
1006 {
1007     switch (option) {
1008     case floatingPointNotSet:
1009         break;
1010     case floatingPointFast:
1011         return "Fast";
1012     case floatingPointPrecise:
1013         return "Precise";
1014     case floatingPointStrict:
1015         return "Strict";
1016     }
1017     return QString();
1018 }
1019 
toString(inlineExpansionOption option)1020 static inline QString toString(inlineExpansionOption option)
1021 {
1022     switch (option) {
1023     case expandDefault:
1024         break;
1025     case expandDisable:
1026         return "Disabled";
1027     case expandOnlyInline:
1028         return "OnlyExplicitInline";
1029     case expandAnySuitable:
1030         return "AnySuitable";
1031     }
1032     return QString();
1033 }
1034 
toString(optimizeOption option)1035 static inline QString toString(optimizeOption option)
1036 {
1037     switch (option) {
1038     case optimizeCustom:
1039     case optimizeDefault:
1040         break;
1041     case optimizeDisabled:
1042         return "Disabled";
1043     case optimizeMinSpace:
1044         return "MinSpace";
1045     case optimizeMaxSpeed:
1046         return "MaxSpeed";
1047     case optimizeFull:
1048         return "Full";
1049     }
1050     return QString();
1051 }
1052 
toString(pchOption option)1053 static inline QString toString(pchOption option)
1054 {
1055     switch (option) {
1056     case pchUnset:
1057     case pchGenerateAuto:
1058         break;
1059     case pchNone:
1060          return "NotUsing";
1061     case pchCreateUsingSpecific:
1062         return "Create";
1063     case pchUseUsingSpecific:
1064         return "Use";
1065     }
1066     return QString();
1067 }
1068 
toString(runtimeLibraryOption option)1069 static inline QString toString(runtimeLibraryOption option)
1070 {
1071     switch (option) {
1072     case rtUnknown:
1073     case rtSingleThreaded:
1074     case rtSingleThreadedDebug:
1075         break;
1076     case rtMultiThreaded:
1077         return "MultiThreaded";
1078     case rtMultiThreadedDLL:
1079         return "MultiThreadedDLL";
1080     case rtMultiThreadedDebug:
1081         return "MultiThreadedDebug";
1082     case rtMultiThreadedDebugDLL:
1083         return "MultiThreadedDebugDLL";
1084     }
1085     return QString();
1086 }
1087 
toString(structMemberAlignOption option)1088 static inline QString toString(structMemberAlignOption option)
1089 {
1090     switch (option) {
1091     case alignNotSet:
1092         break;
1093     case alignSingleByte:
1094         return "1Byte";
1095     case alignTwoBytes:
1096         return "2Bytes";
1097     case alignFourBytes:
1098         return "4Bytes";
1099     case alignEightBytes:
1100         return "8Bytes";
1101     case alignSixteenBytes:
1102         return "16Bytes";
1103     }
1104     return QString();
1105 }
1106 
toString(warningLevelOption option)1107 static inline QString toString(warningLevelOption option)
1108 {
1109     switch (option) {
1110     case warningLevelUnknown:
1111         break;
1112     case warningLevel_0:
1113         return "TurnOffAllWarnings";
1114     case warningLevel_1:
1115         return "Level1";
1116     case warningLevel_2:
1117         return "Level2";
1118     case warningLevel_3:
1119         return "Level3";
1120     case warningLevel_4:
1121         return "Level4";
1122     }
1123     return QString();
1124 }
1125 
toString(optLinkTimeCodeGenType option)1126 static inline QString toString(optLinkTimeCodeGenType option)
1127 {
1128     switch (option) {
1129     case optLTCGDefault:
1130         break;
1131     case optLTCGEnabled:
1132         return "UseLinkTimeCodeGeneration";
1133     case optLTCGInstrument:
1134         return "PGInstrument";
1135     case optLTCGOptimize:
1136         return "PGOptimization";
1137     case optLTCGUpdate:
1138         return "PGUpdate";
1139     }
1140     return QString();
1141 }
1142 
toString(subSystemOption option)1143 static inline QString toString(subSystemOption option)
1144 {
1145     switch (option) {
1146     case subSystemNotSet:
1147         break;
1148     case subSystemConsole:
1149         return "Console";
1150     case subSystemWindows:
1151         return "Windows";
1152     }
1153     return QString();
1154 }
1155 
toString(triState genDebugInfo,linkerDebugOption option)1156 static inline QString toString(triState genDebugInfo, linkerDebugOption option)
1157 {
1158     switch (genDebugInfo) {
1159     case unset:
1160         break;
1161     case _False:
1162         return "false";
1163     case _True:
1164         if (option == linkerDebugOptionFastLink)
1165             return "DebugFastLink";
1166         return "true";
1167     }
1168     return QString();
1169 }
1170 
toString(machineTypeOption option)1171 static inline QString toString(machineTypeOption option)
1172 {
1173     switch (option) {
1174     case machineNotSet:
1175         break;
1176     case machineX86:
1177         return "MachineX86";
1178     case machineX64:
1179         return "MachineX64";
1180     }
1181     return QString();
1182 }
1183 
toString(midlCharOption option)1184 static inline QString toString(midlCharOption option)
1185 {
1186     switch (option) {
1187     case midlCharUnsigned:
1188         return "Unsigned";
1189     case midlCharSigned:
1190         return "Signed";
1191     case midlCharAscii7:
1192         return "Ascii";
1193     }
1194     return QString();
1195 }
1196 
toString(midlErrorCheckOption option)1197 static inline QString toString(midlErrorCheckOption option)
1198 {
1199     switch (option) {
1200     case midlEnableCustom:
1201         break;
1202     case midlDisableAll:
1203         return "None";
1204     case midlEnableAll:
1205         return "All";
1206     }
1207     return QString();
1208 }
1209 
toString(midlStructMemberAlignOption option)1210 static inline QString toString(midlStructMemberAlignOption option)
1211 {
1212     switch (option) {
1213     case midlAlignNotSet:
1214         break;
1215     case midlAlignSingleByte:
1216         return "1";
1217     case midlAlignTwoBytes:
1218         return "2";
1219     case midlAlignFourBytes:
1220         return "4";
1221     case midlAlignEightBytes:
1222         return "8";
1223     case midlAlignSixteenBytes:
1224         return "16";
1225     }
1226     return QString();
1227 }
1228 
toString(midlTargetEnvironment option)1229 static inline QString toString(midlTargetEnvironment option)
1230 {
1231     switch (option) {
1232     case midlTargetNotSet:
1233         break;
1234     case midlTargetWin32:
1235         return "Win32";
1236     case midlTargetWin64:
1237         return "X64";
1238     }
1239     return QString();
1240 }
1241 
toString(midlWarningLevelOption option)1242 static inline QString toString(midlWarningLevelOption option)
1243 {
1244     switch (option) {
1245     case midlWarningLevel_0:
1246         return "0";
1247     case midlWarningLevel_1:
1248         return "1";
1249     case midlWarningLevel_2:
1250         return "2";
1251     case midlWarningLevel_3:
1252         return "3";
1253     case midlWarningLevel_4:
1254         return "4";
1255     }
1256     return QString();
1257 }
1258 
toString(enumResourceLangID option)1259 static inline QString toString(enumResourceLangID option)
1260 {
1261     if (option == 0)
1262         return QString();
1263     else
1264         return QString::number(qlonglong(option));
1265 }
1266 
toString(charSet option)1267 static inline QString toString(charSet option)
1268 {
1269     switch (option) {
1270     case charSetNotSet:
1271         return "NotSet";
1272     case charSetUnicode:
1273         return "Unicode";
1274     case charSetMBCS:
1275         return "MultiByte";
1276     }
1277     return QString();
1278 }
1279 
toString(ConfigurationTypes option)1280 static inline QString toString(ConfigurationTypes option)
1281 {
1282     switch (option) {
1283     case typeUnknown:
1284     case typeGeneric:
1285         break;
1286     case typeApplication:
1287         return "Application";
1288     case typeDynamicLibrary:
1289         return "DynamicLibrary";
1290     case typeStaticLibrary:
1291         return "StaticLibrary";
1292     }
1293     return QString();
1294 }
1295 
toString(useOfATL option)1296 static inline QString toString(useOfATL option)
1297 {
1298     switch (option) {
1299     case useATLNotSet:
1300         break;
1301     case useATLStatic:
1302         return "Static";
1303     case useATLDynamic:
1304         return "Dynamic";
1305     }
1306     return QString();
1307 }
1308 
toString(useOfMfc option)1309 static inline QString toString(useOfMfc option)
1310 {
1311     switch (option) {
1312     case useMfcStdWin:
1313         break;
1314     case useMfcStatic:
1315         return "Static";
1316     case useMfcDynamic:
1317         return "Dynamic";
1318     }
1319     return QString();
1320 }
1321 
toTriState(browseInfoOption option)1322 static inline triState toTriState(browseInfoOption option)
1323 {
1324     switch (option)
1325     {
1326     case brInfoNone:
1327         return _False;
1328     case brAllInfo:
1329     case brNoLocalSymbols:
1330         return _True;
1331     }
1332     return unset;
1333 }
1334 
toTriState(preprocessOption option)1335 static inline triState toTriState(preprocessOption option)
1336 {
1337     switch (option)
1338     {
1339     case preprocessUnknown:
1340         break;
1341     case preprocessNo:
1342         return _False;
1343     case preprocessNoLineNumbers:
1344     case preprocessYes:
1345         return _True;
1346     }
1347     return unset;
1348 }
1349 
toTriState(optFoldingType option)1350 static inline triState toTriState(optFoldingType option)
1351 {
1352     switch (option)
1353     {
1354     case optFoldingDefault:
1355         break;
1356     case optNoFolding:
1357         return _False;
1358     case optFolding:
1359         return _True;
1360     }
1361     return unset;
1362 }
1363 
toTriState(addressAwarenessType option)1364 static inline triState toTriState(addressAwarenessType option)
1365 {
1366     switch (option)
1367     {
1368     case addrAwareDefault:
1369         return unset;
1370     case addrAwareNoLarge:
1371         return _False;
1372     case addrAwareLarge:
1373         return _True;
1374     }
1375     return unset;
1376 }
1377 
toTriState(linkIncrementalType option)1378 static inline triState toTriState(linkIncrementalType option)
1379 {
1380     switch (option)
1381     {
1382     case linkIncrementalDefault:
1383         return unset;
1384     case linkIncrementalNo:
1385         return _False;
1386     case linkIncrementalYes:
1387         return _True;
1388     }
1389     return unset;
1390 }
1391 
toTriState(linkProgressOption option)1392 static inline triState toTriState(linkProgressOption option)
1393 {
1394     switch (option)
1395     {
1396     case linkProgressNotSet:
1397         return unset;
1398     case linkProgressAll:
1399     case linkProgressLibs:
1400         return _True;
1401     }
1402     return unset;
1403 }
1404 
toTriState(optRefType option)1405 static inline triState toTriState(optRefType option)
1406 {
1407     switch (option)
1408     {
1409     case optReferencesDefault:
1410         return unset;
1411     case optNoReferences:
1412         return _False;
1413     case optReferences:
1414         return _True;
1415     }
1416     return unset;
1417 }
1418 
toTriState(termSvrAwarenessType option)1419 static inline triState toTriState(termSvrAwarenessType option)
1420 {
1421     switch (option)
1422     {
1423     case termSvrAwareDefault:
1424         return unset;
1425     case termSvrAwareNo:
1426         return _False;
1427     case termSvrAwareYes:
1428         return _True;
1429     }
1430     return unset;
1431 }
1432 
fixedProgramDataBaseFileNameOutput(const VCCLCompilerTool & tool)1433 static XmlOutput::xml_output fixedProgramDataBaseFileNameOutput(const VCCLCompilerTool &tool)
1434 {
1435     if (tool.config->CompilerVersion >= NET2012
1436             && tool.DebugInformationFormat == debugDisabled
1437             && tool.ProgramDataBaseFileName.isEmpty()) {
1438         // Force the creation of an empty tag to work-around Visual Studio bug. See QTBUG-35570.
1439         return tagValue(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName);
1440     }
1441     return attrTagS(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName);
1442 }
1443 
write(XmlOutput & xml,const VCCLCompilerTool & tool)1444 void VCXProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool)
1445 {
1446     xml
1447         << tag(_CLCompile)
1448             << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";")
1449             << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
1450             << attrTagX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories, ";")
1451             << attrTagS(_AssemblerListingLocation, tool.AssemblerListingLocation)
1452             << attrTagS(_AssemblerOutput, toString(tool.AssemblerOutput))
1453             << attrTagS(_BasicRuntimeChecks, toString(tool.BasicRuntimeChecks))
1454             << attrTagT(_BrowseInformation, toTriState(tool.BrowseInformation))
1455             << attrTagS(_BrowseInformationFile, tool.BrowseInformationFile)
1456             << attrTagT(_BufferSecurityCheck, tool.BufferSecurityCheck)
1457             << attrTagS(_CallingConvention, toString(tool.CallingConvention))
1458             << attrTagS(_CompileAs, toString(tool.CompileAs))
1459             << attrTagS(_CompileAsManaged, toString(tool.CompileAsManaged))
1460             << attrTagT(_CompileAsWinRT, tool.CompileAsWinRT)
1461             << attrTagT(_CreateHotpatchableImage, tool.CreateHotpatchableImage)
1462             << attrTagS(_DebugInformationFormat, toString(tool.DebugInformationFormat,
1463                                                           tool.config->CompilerVersion))
1464             << attrTagT(_DisableLanguageExtensions, tool.DisableLanguageExtensions)
1465             << attrTagX(_DisableSpecificWarnings, tool.DisableSpecificWarnings, ";")
1466             << attrTagS(_EnableEnhancedInstructionSet, toString(tool.EnableEnhancedInstructionSet))
1467             << attrTagT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations)
1468             << attrTagT(_EnablePREfast, tool.EnablePREfast)
1469             << attrTagS(_ErrorReporting, tool.ErrorReporting)
1470             << attrTagS(_ExceptionHandling, toString(tool.ExceptionHandling))
1471             << attrTagT(_ExpandAttributedSource, tool.ExpandAttributedSource)
1472             << attrTagS(_FavorSizeOrSpeed, toString(tool.FavorSizeOrSpeed))
1473             << attrTagT(_FloatingPointExceptions, tool.FloatingPointExceptions)
1474             << attrTagS(_FloatingPointModel, toString(tool.FloatingPointModel))
1475             << attrTagT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope)
1476             << attrTagX(_ForcedIncludeFiles, tool.ForcedIncludeFiles, ";")
1477             << attrTagX(_ForcedUsingFiles, tool.ForcedUsingFiles, ";")
1478             << attrTagT(_FunctionLevelLinking, tool.EnableFunctionLevelLinking)
1479             << attrTagT(_GenerateXMLDocumentationFiles, tool.GenerateXMLDocumentationFiles)
1480             << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
1481             << attrTagS(_InlineFunctionExpansion, toString(tool.InlineFunctionExpansion))
1482             << attrTagT(_IntrinsicFunctions, tool.EnableIntrinsicFunctions)
1483             << attrTagT(_MinimalRebuild, tool.MinimalRebuild)
1484             << attrTagT(_MultiProcessorCompilation, tool.MultiProcessorCompilation)
1485             << attrTagS(_LanguageStandard, tool.LanguageStandard)
1486             << attrTagS(_ObjectFileName, tool.ObjectFile)
1487             << attrTagT(_OmitDefaultLibName, tool.OmitDefaultLibName)
1488             << attrTagT(_OmitFramePointers, tool.OmitFramePointers)
1489             << attrTagT(_OpenMPSupport, tool.OpenMP)
1490             << attrTagS(_Optimization, toString(tool.Optimization))
1491             << attrTagS(_PrecompiledHeader, toString(tool.UsePrecompiledHeader))
1492             << attrTagS(_PrecompiledHeaderFile, tool.PrecompiledHeaderThrough)
1493             << attrTagS(_PrecompiledHeaderOutputFile, tool.PrecompiledHeaderFile)
1494             << attrTagT(_PreprocessKeepComments, tool.KeepComments)
1495             << attrTagX(_PreprocessorDefinitions, unquote(tool.PreprocessorDefinitions), ";")
1496             << attrTagS(_PreprocessOutputPath, tool.PreprocessOutputPath)
1497             << attrTagT(_PreprocessSuppressLineNumbers, tool.PreprocessSuppressLineNumbers)
1498             << attrTagT(_PreprocessToFile, toTriState(tool.GeneratePreprocessedFile))
1499             << fixedProgramDataBaseFileNameOutput(tool)
1500             << attrTagS(_ProcessorNumber, tool.MultiProcessorCompilationProcessorCount)
1501             << attrTagS(_RuntimeLibrary, toString(tool.RuntimeLibrary))
1502             << attrTagT(_RuntimeTypeInfo, tool.RuntimeTypeInfo)
1503             << attrTagT(_ShowIncludes, tool.ShowIncludes)
1504             << attrTagT(_SmallerTypeCheck, tool.SmallerTypeCheck)
1505             << attrTagT(_StringPooling, tool.StringPooling)
1506             << attrTagS(_StructMemberAlignment, toString(tool.StructMemberAlignment))
1507             << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
1508             << attrTagX(_TreatSpecificWarningsAsErrors, tool.TreatSpecificWarningsAsErrors, ";")
1509             << attrTagT(_TreatWarningAsError, tool.WarnAsError)
1510             << attrTagT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType)
1511             << attrTagT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions)
1512             << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";")
1513             << attrTagT(_UseFullPaths, tool.DisplayFullPaths)
1514             << attrTagT(_UseUnicodeForAssemblerListing, tool.UseUnicodeForAssemblerListing)
1515             << attrTagS(_WarningLevel, toString(tool.WarningLevel))
1516             << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization)
1517             << attrTagS(_XMLDocumentationFileName, tool.XMLDocumentationFileName)
1518         << closetag(_CLCompile);
1519 }
1520 
write(XmlOutput & xml,const VCLinkerTool & tool)1521 void VCXProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool)
1522 {
1523     xml
1524         << tag(_Link)
1525             << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";")
1526             << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";")
1527             << attrTagX(_AdditionalManifestDependencies, tool.AdditionalManifestDependencies, ";")
1528             << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
1529             << attrTagX(_AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly, ";")
1530             << attrTagT(_AllowIsolation, tool.AllowIsolation)
1531             << attrTagT(_AssemblyDebug, tool.AssemblyDebug)
1532             << attrTagX(_AssemblyLinkResource, tool.AssemblyLinkResource, ";")
1533             << attrTagS(_BaseAddress, tool.BaseAddress)
1534             << attrTagS(_CLRImageType, tool.CLRImageType)
1535             << attrTagS(_CLRSupportLastError, tool.CLRSupportLastError)
1536             << attrTagS(_CLRThreadAttribute, tool.CLRThreadAttribute)
1537             << attrTagT(_CLRUnmanagedCodeCheck, tool.CLRUnmanagedCodeCheck)
1538             << attrTagT(_DataExecutionPrevention, tool.DataExecutionPrevention)
1539             << attrTagX(_DelayLoadDLLs, tool.DelayLoadDLLs, ";")
1540             << attrTagT(_DelaySign, tool.DelaySign)
1541             << attrTagS(_EmbedManagedResourceFile, tool.LinkToManagedResourceFile)
1542             << attrTagT(_EnableCOMDATFolding, toTriState(tool.EnableCOMDATFolding))
1543             << attrTagT(_EnableUAC, tool.EnableUAC)
1544             << attrTagS(_EntryPointSymbol, tool.EntryPointSymbol)
1545             << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";")
1546             << attrTagS(_FunctionOrder, tool.FunctionOrder)
1547             << attrTagS(_GenerateDebugInformation, toString(tool.GenerateDebugInformation, tool.DebugInfoOption))
1548             << attrTagT(_GenerateManifest, tool.GenerateManifest)
1549             << attrTagT(_GenerateWindowsMetadata, tool.GenerateWindowsMetadata)
1550             << attrTagS(_WindowsMetadataFile, tool.GenerateWindowsMetadata == _True ? tool.WindowsMetadataFile : QString())
1551             << attrTagT(_GenerateMapFile, tool.GenerateMapFile)
1552             << attrTagL(_HeapCommitSize, tool.HeapCommitSize, /*ifNot*/ -1)
1553             << attrTagL(_HeapReserveSize, tool.HeapReserveSize, /*ifNot*/ -1)
1554             << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries)
1555             << attrTagT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL)
1556             << attrTagT(_IgnoreImportLibrary, tool.IgnoreImportLibrary)
1557             << attrTagT(_ImageHasSafeExceptionHandlers, tool.ImageHasSafeExceptionHandlers)
1558             << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreDefaultLibraryNames, ";")
1559             << attrTagS(_ImportLibrary, tool.ImportLibrary)
1560             << attrTagS(_KeyContainer, tool.KeyContainer)
1561             << attrTagS(_KeyFile, tool.KeyFile)
1562             << attrTagT(_LargeAddressAware, toTriState(tool.LargeAddressAware))
1563             << attrTagT(_LinkDLL, (tool.config->ConfigurationType == typeDynamicLibrary ? _True : unset))
1564             << attrTagS(_LinkErrorReporting, tool.LinkErrorReporting)
1565             << attrTagT(_LinkIncremental, toTriState(tool.LinkIncremental))
1566             << attrTagT(_LinkStatus, toTriState(tool.ShowProgress))
1567             << attrTagS(_LinkTimeCodeGeneration, toString(tool.LinkTimeCodeGeneration))
1568             << attrTagS(_ManifestFile, tool.ManifestFile)
1569             << attrTagT(_MapExports, tool.MapExports)
1570             << attrTagS(_MapFileName, tool.MapFileName)
1571             << attrTagS(_MergedIDLBaseFileName, tool.MergedIDLBaseFileName)
1572             << attrTagS(_MergeSections, tool.MergeSections)
1573             << attrTagS(_MidlCommandFile, tool.MidlCommandFile)
1574             << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile)
1575             << attrTagT(_NoEntryPoint, tool.ResourceOnlyDLL)
1576             << attrTagT(_OptimizeReferences, toTriState(tool.OptimizeReferences))
1577             << attrTagS(_OutputFile, tool.OutputFile)
1578             << attrTagT(_PreventDllBinding, tool.PreventDllBinding)
1579             << attrTagS(_ProgramDatabaseFile, tool.ProgramDatabaseFile)
1580             << attrTagT(_RandomizedBaseAddress, tool.RandomizedBaseAddress)
1581             << attrTagT(_RegisterOutput, tool.RegisterOutput)
1582             << attrTagL(_SectionAlignment, tool.SectionAlignment, /*ifNot*/ -1)
1583             << attrTagT(_SetChecksum, tool.SetChecksum)
1584             << attrTagL(_StackCommitSize, tool.StackCommitSize, /*ifNot*/ -1)
1585             << attrTagL(_StackReserveSize, tool.StackReserveSize, /*ifNot*/ -1)
1586             << attrTagS(_StripPrivateSymbols, tool.StripPrivateSymbols)
1587             << attrTagS(_SubSystem, toString(tool.SubSystem))
1588 //            << attrTagT(_SupportNobindOfDelayLoadedDLL, tool.SupportNobindOfDelayLoadedDLL)
1589             << attrTagT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL)
1590             << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
1591             << attrTagT(_SwapRunFromCD, tool.SwapRunFromCD)
1592             << attrTagT(_SwapRunFromNet, tool.SwapRunFromNet)
1593             << attrTagS(_TargetMachine, toString(tool.TargetMachine))
1594             << attrTagT(_TerminalServerAware, toTriState(tool.TerminalServerAware))
1595             << attrTagT(_TreatLinkerWarningAsErrors, tool.TreatWarningsAsErrors)
1596             << attrTagT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration)
1597             << attrTagS(_TypeLibraryFile, tool.TypeLibraryFile)
1598             << attrTagL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ 0)
1599             << attrTagS(_UACExecutionLevel, tool.UACExecutionLevel)
1600             << attrTagT(_UACUIAccess, tool.UACUIAccess)
1601             << attrTagS(_Version, tool.Version)
1602         << closetag(_Link);
1603 }
1604 
write(XmlOutput & xml,const VCMIDLTool & tool)1605 void VCXProjectWriter::write(XmlOutput &xml, const VCMIDLTool &tool)
1606 {
1607     xml
1608         << tag(_Midl)
1609             << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";")
1610             << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
1611             << attrTagT(_ApplicationConfigurationMode, tool.ApplicationConfigurationMode)
1612             << attrTagS(_ClientStubFile, tool.ClientStubFile)
1613             << attrTagX(_CPreprocessOptions, tool.CPreprocessOptions, " ")
1614             << attrTagS(_DefaultCharType, toString(tool.DefaultCharType))
1615             << attrTagS(_DLLDataFileName, tool.DLLDataFileName)
1616             << attrTagS(_EnableErrorChecks, toString(tool.EnableErrorChecks))
1617             << attrTagT(_ErrorCheckAllocations, tool.ErrorCheckAllocations)
1618             << attrTagT(_ErrorCheckBounds, tool.ErrorCheckBounds)
1619             << attrTagT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange)
1620             << attrTagT(_ErrorCheckRefPointers, tool.ErrorCheckRefPointers)
1621             << attrTagT(_ErrorCheckStubData, tool.ErrorCheckStubData)
1622             << attrTagS(_GenerateClientFiles, tool.GenerateClientFiles)
1623             << attrTagS(_GenerateServerFiles, tool.GenerateServerFiles)
1624             << attrTagT(_GenerateStublessProxies, tool.GenerateStublessProxies)
1625             << attrTagT(_GenerateTypeLibrary, tool.GenerateTypeLibrary)
1626             << attrTagS(_HeaderFileName, tool.HeaderFileName)
1627             << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
1628             << attrTagS(_InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName)
1629             << attrTagL(_LocaleID, tool.LocaleID, /*ifNot*/ -1)
1630             << attrTagT(_MkTypLibCompatible, tool.MkTypLibCompatible)
1631             << attrTagS(_OutputDirectory, tool.OutputDirectory)
1632             << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";")
1633             << attrTagS(_ProxyFileName, tool.ProxyFileName)
1634             << attrTagS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors)
1635             << attrTagS(_ServerStubFile, tool.ServerStubFile)
1636             << attrTagS(_StructMemberAlignment, toString(tool.StructMemberAlignment))
1637             << attrTagT(_SuppressCompilerWarnings, tool.SuppressCompilerWarnings)
1638             << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
1639             << attrTagS(_TargetEnvironment, toString(tool.TargetEnvironment))
1640             << attrTagS(_TypeLibFormat, tool.TypeLibFormat)
1641             << attrTagS(_TypeLibraryName, tool.TypeLibraryName)
1642             << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";")
1643             << attrTagT(_ValidateAllParameters, tool.ValidateAllParameters)
1644             << attrTagT(_WarnAsError, tool.WarnAsError)
1645             << attrTagS(_WarningLevel, toString(tool.WarningLevel))
1646         << closetag(_Midl);
1647 }
1648 
write(XmlOutput & xml,const VCCustomBuildTool & tool)1649 void VCXProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool)
1650 {
1651     const QString condition = generateCondition(*tool.config);
1652 
1653     if ( !tool.AdditionalDependencies.isEmpty() )
1654     {
1655         xml << tag("AdditionalInputs")
1656             << attrTag("Condition", condition)
1657             << valueTagDefX(tool.AdditionalDependencies, "AdditionalInputs", ";");
1658     }
1659 
1660     if( !tool.CommandLine.isEmpty() )
1661     {
1662         xml << tag("Command")
1663             << attrTag("Condition", condition)
1664             << valueTag(commandLinesForOutput(tool.CommandLine));
1665     }
1666 
1667     if ( !tool.Description.isEmpty() )
1668     {
1669         xml << tag("Message")
1670             << attrTag("Condition", condition)
1671             << valueTag(tool.Description);
1672     }
1673 
1674     if ( !tool.Outputs.isEmpty() )
1675     {
1676         xml << tag("Outputs")
1677             << attrTag("Condition", condition)
1678             << valueTagDefX(tool.Outputs, "Outputs", ";");
1679     }
1680 }
1681 
write(XmlOutput & xml,const VCLibrarianTool & tool)1682 void VCXProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool)
1683 {
1684     xml
1685         << tag(_Lib)
1686             << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";")
1687             << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";")
1688             << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
1689             << attrTagX(_ExportNamedFunctions, tool.ExportNamedFunctions, ";")
1690             << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";")
1691             << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries)
1692             << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreDefaultLibraryNames, ";")
1693             << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile)
1694             << attrTagS(_OutputFile, tool.OutputFile)
1695             << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
1696         << closetag(_Lib);
1697 }
1698 
write(XmlOutput & xml,const VCResourceCompilerTool & tool)1699 void VCXProjectWriter::write(XmlOutput &xml, const VCResourceCompilerTool &tool)
1700 {
1701     xml
1702         << tag(_ResourceCompile)
1703             << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";")
1704             << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ")
1705             << attrTagS(_Culture, toString(tool.Culture))
1706             << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
1707             << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";")
1708             << attrTagS(_ResourceOutputFileName, tool.ResourceOutputFileName)
1709             << attrTagT(_ShowProgress, toTriState(tool.ShowProgress))
1710             << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner)
1711         << closetag(_ResourceCompile);
1712 }
1713 
write(XmlOutput & xml,const VCEventTool & tool)1714 void VCXProjectWriter::write(XmlOutput &xml, const VCEventTool &tool)
1715 {
1716     xml
1717         << tag(tool.EventName)
1718             << tag(_Command) << valueTag(commandLinesForOutput(tool.CommandLine))
1719             << tag(_Message) << valueTag(tool.Description)
1720         << closetag(tool.EventName);
1721 }
1722 
write(XmlOutput & xml,const VCDeploymentTool & tool)1723 void VCXProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool)
1724 {
1725     Q_UNUSED(xml);
1726     Q_UNUSED(tool);
1727     // SmartDevice deployment not supported in VS 2010
1728 }
1729 
write(XmlOutput & xml,const VCWinDeployQtTool & tool)1730 void VCXProjectWriter::write(XmlOutput &xml, const VCWinDeployQtTool &tool)
1731 {
1732     const QString name = QStringLiteral("WinDeployQt_") + tool.config->Name;
1733     xml << tag("Target")
1734            << attrTag(_Name, name)
1735            << attrTag("Condition", generateCondition(*tool.config))
1736            << attrTag("Inputs", "$(OutDir)\\$(TargetName).exe")
1737            << attrTag("Outputs", tool.Record)
1738            << tag(_Message)
1739               << attrTag("Text", tool.CommandLine)
1740            << closetag()
1741            << tag("Exec")
1742              << attrTag("Command", tool.CommandLine)
1743            << closetag()
1744         << closetag()
1745         << tag("Target")
1746            << attrTag(_Name, QStringLiteral("PopulateWinDeployQtItems_") + tool.config->Name)
1747            << attrTag("Condition", generateCondition(*tool.config))
1748            << attrTag("AfterTargets", "Link")
1749            << attrTag("DependsOnTargets", name)
1750            << tag("ReadLinesFromFile")
1751               << attrTag("File", tool.Record)
1752               << tag("Output")
1753                  << attrTag("TaskParameter", "Lines")
1754                  << attrTag("ItemName", "DeploymentItems")
1755               << closetag()
1756            << closetag()
1757            << tag(_ItemGroup)
1758               << tag("None")
1759                  << attrTag("Include", "@(DeploymentItems)")
1760                  << attrTagT("DeploymentContent", _True)
1761               << closetag()
1762            << closetag()
1763         << closetag();
1764 }
1765 
write(XmlOutput & xml,const VCConfiguration & tool)1766 void VCXProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool)
1767 {
1768         xml << tag("PropertyGroup")
1769             << attrTag("Condition", generateCondition(tool))
1770             << attrTag("Label", "Configuration")
1771             << attrTagS(_PlatformToolSet, tool.PlatformToolSet)
1772             << attrTagS(_OutputDirectory, tool.OutputDirectory)
1773             << attrTagT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage)
1774             << attrTagT(_BuildBrowserInformation, tool.BuildBrowserInformation)
1775             << attrTagS(_CharacterSet, toString(tool.CharacterSet))
1776             << attrTagS(_ConfigurationType, toString(tool.ConfigurationType))
1777             << attrTagS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean)
1778             << attrTagS(_ImportLibrary, tool.ImportLibrary)
1779             << attrTagS(_IntermediateDirectory, tool.IntermediateDirectory)
1780             << attrTagS(_PrimaryOutput, tool.PrimaryOutput)
1781             << attrTagS(_ProgramDatabase, tool.ProgramDatabase)
1782             << attrTagT(_RegisterOutput, tool.RegisterOutput)
1783             << attrTagS(_UseOfATL, toString(tool.UseOfATL))
1784             << attrTagS(_UseOfMfc, toString(tool.UseOfMfc))
1785             << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization)
1786             << attrTagT(_EmbedManifest, tool.manifestTool.EmbedManifest)
1787         << closetag();
1788 }
1789 
write(XmlOutput & xml,VCFilter & tool)1790 void VCXProjectWriter::write(XmlOutput &xml, VCFilter &tool)
1791 {
1792     Q_UNUSED(xml);
1793     Q_UNUSED(tool);
1794     // unused in this generator
1795 }
1796 
addFilters(VCProject & project,XmlOutput & xmlFilter,const QString & filtername)1797 void VCXProjectWriter::addFilters(VCProject &project, XmlOutput &xmlFilter, const QString &filtername)
1798 {
1799     bool added = false;
1800 
1801     for (int i = 0; i < project.SingleProjects.count(); ++i) {
1802         const VCFilter filter = project.SingleProjects.at(i).filterByName(filtername);
1803         if(!filter.Files.isEmpty() && !added) {
1804             xmlFilter << tag("Filter")
1805                       << attrTag("Include", filtername)
1806                       << attrTagS("UniqueIdentifier", filter.Guid)
1807                       << attrTagS("Extensions", filter.Filter)
1808                       << attrTagT("ParseFiles", filter.ParseFiles)
1809                       << closetag();
1810         }
1811     }
1812 }
1813 
1814 // outputs a given filter for all existing configurations of a project
outputFilter(VCProject & project,XmlOutput & xml,XmlOutput & xmlFilter,const QString & filtername)1815 void VCXProjectWriter::outputFilter(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filtername)
1816 {
1817     QScopedPointer<XNode> root;
1818     if (project.SingleProjects.at(0).flat_files)
1819         root.reset(new XFlatNode);
1820     else
1821         root.reset(new XTreeNode);
1822 
1823     for (int i = 0; i < project.SingleProjects.count(); ++i) {
1824         const VCFilter filter = project.SingleProjects.at(i).filterByName(filtername);
1825         // Merge all files in this filter to root tree
1826         for (int x = 0; x < filter.Files.count(); ++x)
1827             root->addElement(filter.Files.at(x));
1828     }
1829 
1830     if (!root->hasElements())
1831         return;
1832 
1833     root->generateXML(xml, xmlFilter, "", project, filtername); // output root tree
1834 }
1835 
stringBeforeFirstBackslash(const QString & str)1836 static QString stringBeforeFirstBackslash(const QString &str)
1837 {
1838     int idx = str.indexOf(QLatin1Char('\\'));
1839     return idx == -1 ? str : str.left(idx);
1840 }
1841 
1842 // Output all configurations (by filtername) for a file (by info)
1843 // A filters config output is in VCFilter.outputFileConfig()
outputFileConfigs(VCProject & project,XmlOutput & xml,XmlOutput & xmlFilter,const VCFilterFile & info,const QString & filtername)1844 void VCXProjectWriter::outputFileConfigs(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter,
1845                                          const VCFilterFile &info, const QString &filtername)
1846 {
1847     // In non-flat mode the filter names have directory suffixes, e.g. "Generated Files\subdir".
1848     const QString cleanFilterName = stringBeforeFirstBackslash(filtername);
1849 
1850     // We need to check if the file has any custom build step.
1851     // If there is one then it has to be included with "CustomBuild Include"
1852     bool hasCustomBuildStep = false;
1853     QVarLengthArray<OutputFilterData> data(project.SingleProjects.count());
1854     for (int i = 0; i < project.SingleProjects.count(); ++i) {
1855         data[i].filter = project.SingleProjects.at(i).filterByName(cleanFilterName);
1856         if (!data[i].filter.Config) // only if the filter is not empty
1857             continue;
1858         VCFilter &filter = data[i].filter;
1859 
1860         // Clearing each filter tool
1861         filter.useCustomBuildTool = false;
1862         filter.useCompilerTool = false;
1863         filter.CustomBuildTool = VCCustomBuildTool();
1864         filter.CustomBuildTool.config = filter.Config;
1865         filter.CompilerTool = VCCLCompilerTool();
1866         filter.CompilerTool.config = filter.Config;
1867 
1868         VCFilterFile fileInFilter = filter.findFile(info.file, &data[i].inBuild);
1869         data[i].info = fileInFilter;
1870         data[i].inBuild &= !fileInFilter.excludeFromBuild;
1871         if (data[i].inBuild && filter.addExtraCompiler(fileInFilter))
1872             hasCustomBuildStep = true;
1873     }
1874 
1875     bool fileAdded = false;
1876     for (int i = 0; i < project.SingleProjects.count(); ++i) {
1877         OutputFilterData *d = &data[i];
1878         if (!d->filter.Config) // only if the filter is not empty
1879             continue;
1880         if (outputFileConfig(d, xml, xmlFilter, info.file, filtername, fileAdded,
1881                              hasCustomBuildStep)) {
1882             fileAdded = true;
1883         }
1884     }
1885 
1886     if ( !fileAdded )
1887         outputFileConfig(xml, xmlFilter, info.file, filtername);
1888 
1889     xml << closetag();
1890     xmlFilter << closetag();
1891 }
1892 
outputFileConfig(OutputFilterData * d,XmlOutput & xml,XmlOutput & xmlFilter,const QString & filename,const QString & fullFilterName,bool fileAdded,bool hasCustomBuildStep)1893 bool VCXProjectWriter::outputFileConfig(OutputFilterData *d, XmlOutput &xml, XmlOutput &xmlFilter,
1894                                         const QString &filename, const QString &fullFilterName,
1895                                         bool fileAdded, bool hasCustomBuildStep)
1896 {
1897     VCFilter &filter = d->filter;
1898     if (d->inBuild) {
1899         if (filter.Project->usePCH)
1900             filter.modifyPCHstage(filename);
1901     } else {
1902         // Excluded files uses an empty compiler stage
1903         if (d->info.excludeFromBuild)
1904             filter.useCompilerTool = true;
1905     }
1906 
1907     // Actual XML output ----------------------------------
1908     if (hasCustomBuildStep || filter.useCustomBuildTool || filter.useCompilerTool
1909             || !d->inBuild || filter.Name.startsWith("Deployment Files")) {
1910 
1911         if (hasCustomBuildStep || filter.useCustomBuildTool)
1912         {
1913             if (!fileAdded) {
1914                 fileAdded = true;
1915 
1916                 xmlFilter << tag("CustomBuild")
1917                     << attrTag("Include", Option::fixPathToTargetOS(filename))
1918                     << attrTagS("Filter", fullFilterName);
1919 
1920                 xml << tag("CustomBuild")
1921                     << attrTag("Include", Option::fixPathToTargetOS(filename));
1922 
1923                 if (filter.Name.startsWith("Form Files")
1924                         || filter.Name.startsWith("Generated Files")
1925                         || filter.Name.startsWith("Resource Files")
1926                         || filter.Name.startsWith("Deployment Files"))
1927                     xml << attrTagS("FileType", "Document");
1928             }
1929 
1930             filter.Project->projectWriter->write(xml, filter.CustomBuildTool);
1931         }
1932 
1933         if (!fileAdded)
1934         {
1935             fileAdded = true;
1936             outputFileConfig(xml, xmlFilter, filename, fullFilterName);
1937         }
1938 
1939         const QString condition = generateCondition(*filter.Config);
1940         if (!d->inBuild) {
1941             xml << tag("ExcludedFromBuild")
1942                 << attrTag("Condition", condition)
1943                 << valueTag("true");
1944         }
1945 
1946         if (filter.Name.startsWith("Deployment Files") && d->inBuild) {
1947             xml << tag("DeploymentContent")
1948                 << attrTag("Condition", condition)
1949                 << valueTag("true");
1950         }
1951 
1952         if (filter.useCompilerTool) {
1953 
1954             if ( !filter.CompilerTool.ForcedIncludeFiles.isEmpty() ) {
1955                 xml << tag("ForcedIncludeFiles")
1956                     << attrTag("Condition", condition)
1957                     << valueTagX(filter.CompilerTool.ForcedIncludeFiles);
1958             }
1959 
1960             if ( !filter.CompilerTool.PrecompiledHeaderThrough.isEmpty() ) {
1961                 xml << tag("PrecompiledHeaderFile")
1962                     << attrTag("Condition", condition)
1963                     << valueTag(filter.CompilerTool.PrecompiledHeaderThrough);
1964             }
1965 
1966             if (filter.CompilerTool.UsePrecompiledHeader != pchUnset) {
1967                 xml << tag("PrecompiledHeader")
1968                     << attrTag("Condition", condition)
1969                     << valueTag(toString(filter.CompilerTool.UsePrecompiledHeader));
1970             }
1971         }
1972     }
1973 
1974     return fileAdded;
1975 }
1976 
isFileClCompatible(const QString & filePath)1977 static bool isFileClCompatible(const QString &filePath)
1978 {
1979     auto filePathEndsWith = [&filePath] (const QString &ext) {
1980         return filePath.endsWith(ext, Qt::CaseInsensitive);
1981     };
1982     return std::any_of(Option::cpp_ext.cbegin(), Option::cpp_ext.cend(), filePathEndsWith)
1983             || std::any_of(Option::c_ext.cbegin(), Option::c_ext.cend(), filePathEndsWith);
1984 }
1985 
outputFileConfig(XmlOutput & xml,XmlOutput & xmlFilter,const QString & filePath,const QString & filterName)1986 void VCXProjectWriter::outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter,
1987                                         const QString &filePath, const QString &filterName)
1988 {
1989     const QString nativeFilePath = Option::fixPathToTargetOS(filePath);
1990     if (filterName.startsWith("Source Files")) {
1991         xmlFilter << tag("ClCompile")
1992                   << attrTag("Include", nativeFilePath)
1993                   << attrTagS("Filter", filterName);
1994         xml << tag("ClCompile")
1995             << attrTag("Include", nativeFilePath);
1996     } else if (filterName.startsWith("Header Files")) {
1997         xmlFilter << tag("ClInclude")
1998                   << attrTag("Include", nativeFilePath)
1999                   << attrTagS("Filter", filterName);
2000         xml << tag("ClInclude")
2001             << attrTag("Include", nativeFilePath);
2002     } else if (filterName.startsWith("Generated Files") || filterName.startsWith("Form Files")) {
2003         if (filePath.endsWith(".h")) {
2004             xmlFilter << tag("ClInclude")
2005                       << attrTag("Include", nativeFilePath)
2006                       << attrTagS("Filter", filterName);
2007             xml << tag("ClInclude")
2008                 << attrTag("Include", nativeFilePath);
2009         } else if (isFileClCompatible(filePath)) {
2010             xmlFilter << tag("ClCompile")
2011                       << attrTag("Include", nativeFilePath)
2012                       << attrTagS("Filter", filterName);
2013             xml << tag("ClCompile")
2014                 << attrTag("Include", nativeFilePath);
2015         } else if (filePath.endsWith(".res")) {
2016             xmlFilter << tag("CustomBuild")
2017                       << attrTag("Include", nativeFilePath)
2018                       << attrTagS("Filter", filterName);
2019             xml << tag("CustomBuild")
2020                 << attrTag("Include", nativeFilePath);
2021         } else {
2022             xmlFilter << tag("CustomBuild")
2023                       << attrTag("Include", nativeFilePath)
2024                       << attrTagS("Filter", filterName);
2025             xml << tag("CustomBuild")
2026                 << attrTag("Include", nativeFilePath);
2027         }
2028     } else if (filterName.startsWith("Root Files")) {
2029         if (filePath.endsWith(".rc")) {
2030             xmlFilter << tag("ResourceCompile")
2031                       << attrTag("Include", nativeFilePath);
2032             xml << tag("ResourceCompile")
2033                 << attrTag("Include", nativeFilePath);
2034         }
2035     } else {
2036         xmlFilter << tag("None")
2037                   << attrTag("Include", nativeFilePath)
2038                   << attrTagS("Filter", filterName);
2039         xml << tag("None")
2040             << attrTag("Include", nativeFilePath);
2041     }
2042 }
2043 
generateCondition(const VCConfiguration & config)2044 QString VCXProjectWriter::generateCondition(const VCConfiguration &config)
2045 {
2046     return QStringLiteral("'$(Configuration)|$(Platform)'=='") + config.Name + QLatin1Char('\'');
2047 }
2048 
attrTagToolsVersion(const VCConfiguration & config)2049 XmlOutput::xml_output VCXProjectWriter::attrTagToolsVersion(const VCConfiguration &config)
2050 {
2051     if (config.CompilerVersion >= NET2013)
2052         return noxml();
2053     return attrTag("ToolsVersion", "4.0");
2054 }
2055 
2056 QT_END_NAMESPACE
2057