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 "msvc_objectmodel.h"
30 #include "msvc_vcproj.h"
31 #include "msvc_vcxproj.h"
32 
33 #include <ioutils.h>
34 
35 #include <qscopedpointer.h>
36 #include <qfileinfo.h>
37 #include <qregexp.h>
38 
39 using namespace QMakeInternal;
40 
41 QT_BEGIN_NAMESPACE
42 
vsVersionFromString(const char * versionString)43 static DotNET vsVersionFromString(const char *versionString)
44 {
45     struct VSVersionMapping
46     {
47         const char *str;
48         DotNET version;
49     };
50     static VSVersionMapping mapping[] = {
51         { "7.0", NET2002 },
52         { "7.1", NET2003 },
53         { "8.0", NET2005 },
54         { "9.0", NET2008 },
55         { "10.0", NET2010 },
56         { "11.0", NET2012 },
57         { "12.0", NET2013 },
58         { "14.0", NET2015 },
59         { "15.0", NET2017 },
60         { "16.0", NET2019 }
61     };
62     DotNET result = NETUnknown;
63     for (const auto entry : mapping) {
64         if (strcmp(entry.str, versionString) == 0)
65             return entry.version;
66     }
67     return result;
68 }
69 
vsVersionFromString(const ProString & versionString)70 DotNET vsVersionFromString(const ProString &versionString)
71 {
72     return vsVersionFromString(versionString.toLatin1().constData());
73 }
74 
75 // XML Tags ---------------------------------------------------------
76 const char _Configuration[]                     = "Configuration";
77 const char _Configurations[]                    = "Configurations";
78 const char q_File[]                              = "File";
79 const char _FileConfiguration[]                 = "FileConfiguration";
80 const char q_Files[]                             = "Files";
81 const char _Filter[]                            = "Filter";
82 const char _Globals[]                           = "Globals";
83 const char _Platform[]                          = "Platform";
84 const char _Platforms[]                         = "Platforms";
85 const char _Tool[]                              = "Tool";
86 const char _VisualStudioProject[]               = "VisualStudioProject";
87 
88 // XML Properties ---------------------------------------------------
89 const char _AddModuleNamesToAssembly[]          = "AddModuleNamesToAssembly";
90 const char _AdditionalDependencies[]            = "AdditionalDependencies";
91 const char _AdditionalFiles[]                   = "AdditionalFiles";
92 const char _AdditionalIncludeDirectories[]      = "AdditionalIncludeDirectories";
93 const char _AdditionalLibraryDirectories[]      = "AdditionalLibraryDirectories";
94 const char _AdditionalOptions[]                 = "AdditionalOptions";
95 const char _AdditionalUsingDirectories[]        = "AdditionalUsingDirectories";
96 const char _AssemblerListingLocation[]          = "AssemblerListingLocation";
97 const char _AssemblerOutput[]                   = "AssemblerOutput";
98 const char _ATLMinimizesCRunTimeLibraryUsage[]  = "ATLMinimizesCRunTimeLibraryUsage";
99 const char _BaseAddress[]                       = "BaseAddress";
100 const char _BasicRuntimeChecks[]                = "BasicRuntimeChecks";
101 const char _BrowseInformation[]                 = "BrowseInformation";
102 const char _BrowseInformationFile[]             = "BrowseInformationFile";
103 const char _BufferSecurityCheck[]               = "BufferSecurityCheck";
104 const char _BuildBrowserInformation[]           = "BuildBrowserInformation";
105 const char _CPreprocessOptions[]                = "CPreprocessOptions";
106 const char _CallingConvention[]                 = "CallingConvention";
107 const char _CharacterSet[]                      = "CharacterSet";
108 const char _CommandLine[]                       = "CommandLine";
109 const char _CompileAs[]                         = "CompileAs";
110 const char _CompileAsManaged[]                  = "CompileAsManaged";
111 const char _CompileOnly[]                       = "CompileOnly";
112 const char _ConfigurationType[]                 = "ConfigurationType";
113 const char _Culture[]                           = "Culture";
114 const char _DLLDataFileName[]                   = "DLLDataFileName";
115 const char _DataExecutionPrevention[]           = "DataExecutionPrevention";
116 const char _DebugInformationFormat[]            = "DebugInformationFormat";
117 const char _DefaultCharType[]                   = "DefaultCharType";
118 const char _DelayLoadDLLs[]                     = "DelayLoadDLLs";
119 const char _DeleteExtensionsOnClean[]           = "DeleteExtensionsOnClean";
120 const char _Description[]                       = "Description";
121 const char _Detect64BitPortabilityProblems[]    = "Detect64BitPortabilityProblems";
122 const char _DisableLanguageExtensions[]         = "DisableLanguageExtensions";
123 const char _DisableSpecificWarnings[]           = "DisableSpecificWarnings";
124 const char _EmbedManifest[]                     = "EmbedManifest";
125 const char _EnableCOMDATFolding[]               = "EnableCOMDATFolding";
126 const char _EnableErrorChecks[]                 = "EnableErrorChecks";
127 const char _EnableEnhancedInstructionSet[]      = "EnableEnhancedInstructionSet";
128 const char _EnableFiberSafeOptimizations[]      = "EnableFiberSafeOptimizations";
129 const char _EnableFunctionLevelLinking[]        = "EnableFunctionLevelLinking";
130 const char _EnableIntrinsicFunctions[]          = "EnableIntrinsicFunctions";
131 const char _EntryPointSymbol[]                  = "EntryPointSymbol";
132 const char _ErrorCheckAllocations[]             = "ErrorCheckAllocations";
133 const char _ErrorCheckBounds[]                  = "ErrorCheckBounds";
134 const char _ErrorCheckEnumRange[]               = "ErrorCheckEnumRange";
135 const char _ErrorCheckRefPointers[]             = "ErrorCheckRefPointers";
136 const char _ErrorCheckStubData[]                = "ErrorCheckStubData";
137 const char _ExceptionHandling[]                 = "ExceptionHandling";
138 const char _ExcludedFromBuild[]                 = "ExcludedFromBuild";
139 const char _ExpandAttributedSource[]            = "ExpandAttributedSource";
140 const char _ExportNamedFunctions[]              = "ExportNamedFunctions";
141 const char _FavorSizeOrSpeed[]                  = "FavorSizeOrSpeed";
142 const char _FloatingPointModel[]                = "FloatingPointModel";
143 const char _FloatingPointExceptions[]           = "FloatingPointExceptions";
144 const char _ForceConformanceInForLoopScope[]    = "ForceConformanceInForLoopScope";
145 const char _ForceSymbolReferences[]             = "ForceSymbolReferences";
146 const char _ForcedIncludeFiles[]                = "ForcedIncludeFiles";
147 const char _ForcedUsingFiles[]                  = "ForcedUsingFiles";
148 const char _FullIncludePath[]                   = "FullIncludePath";
149 const char _FunctionOrder[]                     = "FunctionOrder";
150 const char _GenerateDebugInformation[]          = "GenerateDebugInformation";
151 const char _GenerateMapFile[]                   = "GenerateMapFile";
152 const char _GeneratePreprocessedFile[]          = "GeneratePreprocessedFile";
153 const char _GenerateStublessProxies[]           = "GenerateStublessProxies";
154 const char _GenerateTypeLibrary[]               = "GenerateTypeLibrary";
155 const char _GlobalOptimizations[]               = "GlobalOptimizations";
156 const char _HeaderFileName[]                    = "HeaderFileName";
157 const char _HeapCommitSize[]                    = "HeapCommitSize";
158 const char _HeapReserveSize[]                   = "HeapReserveSize";
159 const char _IgnoreAllDefaultLibraries[]         = "IgnoreAllDefaultLibraries";
160 const char _IgnoreDefaultLibraryNames[]         = "IgnoreDefaultLibraryNames";
161 const char _IgnoreEmbeddedIDL[]                 = "IgnoreEmbeddedIDL";
162 const char _IgnoreImportLibrary[]               = "IgnoreImportLibrary";
163 const char _IgnoreStandardIncludePath[]         = "IgnoreStandardIncludePath";
164 const char _ImportLibrary[]                     = "ImportLibrary";
165 const char _ImproveFloatingPointConsistency[]   = "ImproveFloatingPointConsistency";
166 const char _InlineFunctionExpansion[]           = "InlineFunctionExpansion";
167 const char _InterfaceIdentifierFileName[]       = "InterfaceIdentifierFileName";
168 const char _IntermediateDirectory[]             = "IntermediateDirectory";
169 const char _KeepComments[]                      = "KeepComments";
170 const char _LargeAddressAware[]                 = "LargeAddressAware";
171 const char _LinkDLL[]                           = "LinkDLL";
172 const char _LinkIncremental[]                   = "LinkIncremental";
173 const char _LinkTimeCodeGeneration[]            = "LinkTimeCodeGeneration";
174 const char _LinkToManagedResourceFile[]         = "LinkToManagedResourceFile";
175 const char _MapExports[]                        = "MapExports";
176 const char _MapFileName[]                       = "MapFileName";
177 const char _MapLines[]                          = "MapLines ";
178 const char _MergeSections[]                     = "MergeSections";
179 const char _MergedIDLBaseFileName[]             = "MergedIDLBaseFileName";
180 const char _MidlCommandFile[]                   = "MidlCommandFile";
181 const char _MinimalRebuild[]                    = "MinimalRebuild";
182 const char _MkTypLibCompatible[]                = "MkTypLibCompatible";
183 const char _ModuleDefinitionFile[]              = "ModuleDefinitionFile";
184 const char _Name[]                              = "Name";
185 const char _ObjectFile[]                        = "ObjectFile";
186 const char _OmitFramePointers[]                 = "OmitFramePointers";
187 const char _OpenMP[]                            = "OpenMP";
188 const char _Optimization[]                      = "Optimization ";
189 const char _OptimizeForProcessor[]              = "OptimizeForProcessor";
190 const char _OptimizeForWindows98[]              = "OptimizeForWindows98";
191 const char _OptimizeForWindowsApplication[]     = "OptimizeForWindowsApplication";
192 const char _OptimizeReferences[]                = "OptimizeReferences";
193 const char _OutputDirectory[]                   = "OutputDirectory";
194 const char _OutputFile[]                        = "OutputFile";
195 const char _Outputs[]                           = "Outputs";
196 const char _ParseFiles[]                        = "ParseFiles";
197 const char _PrecompiledHeaderFile[]             = "PrecompiledHeaderFile";
198 const char _PrecompiledHeaderThrough[]          = "PrecompiledHeaderThrough";
199 const char _PreprocessorDefinitions[]           = "PreprocessorDefinitions";
200 const char _PrimaryOutput[]                     = "PrimaryOutput";
201 const char _ProjectGUID[]                       = "ProjectGUID";
202 const char _Keyword[]                           = "Keyword";
203 const char _ProjectType[]                       = "ProjectType";
204 const char _ProgramDatabase[]                   = "ProgramDatabase";
205 const char _ProgramDataBaseFileName[]           = "ProgramDataBaseFileName";
206 const char _ProgramDatabaseFile[]               = "ProgramDatabaseFile";
207 const char _ProxyFileName[]                     = "ProxyFileName";
208 const char _RandomizedBaseAddress[]             = "RandomizedBaseAddress";
209 const char _RedirectOutputAndErrors[]           = "RedirectOutputAndErrors";
210 const char _RegisterOutput[]                    = "RegisterOutput";
211 const char _RelativePath[]                      = "RelativePath";
212 const char _RemoteDirectory[]                   = "RemoteDirectory";
213 const char _ResourceOnlyDLL[]                   = "ResourceOnlyDLL";
214 const char _ResourceOutputFileName[]            = "ResourceOutputFileName";
215 const char _RuntimeLibrary[]                    = "RuntimeLibrary";
216 const char _RuntimeTypeInfo[]                   = "RuntimeTypeInfo";
217 const char _SccProjectName[]                    = "SccProjectName";
218 const char _SccLocalPath[]                      = "SccLocalPath";
219 const char _SetChecksum[]                       = "SetChecksum";
220 const char _ShowIncludes[]                      = "ShowIncludes";
221 const char _ShowProgress[]                      = "ShowProgress";
222 const char _SmallerTypeCheck[]                  = "SmallerTypeCheck";
223 const char _StackCommitSize[]                   = "StackCommitSize";
224 const char _StackReserveSize[]                  = "StackReserveSize";
225 const char _StringPooling[]                     = "StringPooling";
226 const char _StripPrivateSymbols[]               = "StripPrivateSymbols";
227 const char _StructMemberAlignment[]             = "StructMemberAlignment";
228 const char _SubSystem[]                         = "SubSystem";
229 const char _SupportUnloadOfDelayLoadedDLL[]     = "SupportUnloadOfDelayLoadedDLL";
230 const char _SuppressStartupBanner[]             = "SuppressStartupBanner";
231 const char _SwapRunFromCD[]                     = "SwapRunFromCD";
232 const char _SwapRunFromNet[]                    = "SwapRunFromNet";
233 const char _TargetEnvironment[]                 = "TargetEnvironment";
234 const char _TargetMachine[]                     = "TargetMachine";
235 const char _TerminalServerAware[]               = "TerminalServerAware";
236 const char _Path[]                              = "Path";
237 const char _TreatWChar_tAsBuiltInType[]         = "TreatWChar_tAsBuiltInType";
238 const char _TurnOffAssemblyGeneration[]         = "TurnOffAssemblyGeneration";
239 const char _TypeLibraryFile[]                   = "TypeLibraryFile";
240 const char _TypeLibraryName[]                   = "TypeLibraryName";
241 const char _TypeLibraryResourceID[]             = "TypeLibraryResourceID";
242 const char _UndefineAllPreprocessorDefinitions[]= "UndefineAllPreprocessorDefinitions";
243 const char _UndefinePreprocessorDefinitions[]   = "UndefinePreprocessorDefinitions";
244 const char _UniqueIdentifier[]                  = "UniqueIdentifier";
245 const char _UseOfATL[]                          = "UseOfATL";
246 const char _UseOfMfc[]                          = "UseOfMfc";
247 const char _UsePrecompiledHeader[]              = "UsePrecompiledHeader";
248 const char _ValidateParameters[]                = "ValidateParameters";
249 const char _VCCLCompilerTool[]                  = "VCCLCompilerTool";
250 const char _VCLibrarianTool[]                   = "VCLibrarianTool";
251 const char _VCLinkerTool[]                      = "VCLinkerTool";
252 const char _VCManifestTool[]                    = "VCManifestTool";
253 const char _VCCustomBuildTool[]                 = "VCCustomBuildTool";
254 const char _VCResourceCompilerTool[]            = "VCResourceCompilerTool";
255 const char _VCMIDLTool[]                        = "VCMIDLTool";
256 const char _Version[]                           = "Version";
257 const char _WarnAsError[]                       = "WarnAsError";
258 const char _WarningLevel[]                      = "WarningLevel";
259 const char _WholeProgramOptimization[]          = "WholeProgramOptimization";
260 const char _CompileForArchitecture[]            = "CompileForArchitecture";
261 const char _InterworkCalls[]                    = "InterworkCalls";
262 const char _GenerateManifest[]                  = "GenerateManifest";
263 
264 // XmlOutput stream functions ------------------------------
attrT(const char * name,const triState v)265 inline XmlOutput::xml_output attrT(const char *name, const triState v)
266 {
267     if(v == unset)
268         return noxml();
269     return attr(name, (v == _True ? "true" : "false"));
270 }
271 
attrE(const char * name,int v)272 inline XmlOutput::xml_output attrE(const char *name, int v)
273 {
274     return attr(name, QString::number(v));
275 }
276 
277 /*ifNot version*/
attrE(const char * name,int v,int ifn)278 inline XmlOutput::xml_output attrE(const char *name, int v, int ifn)
279 {
280     if (v == ifn)
281         return noxml();
282     return attr(name, QString::number(v));
283 }
284 
attrL(const char * name,qint64 v)285 inline XmlOutput::xml_output attrL(const char *name, qint64 v)
286 {
287     return attr(name, QString::number(v));
288 }
289 
290 /*ifNot version*/
attrL(const char * name,qint64 v,qint64 ifn)291 inline XmlOutput::xml_output attrL(const char *name, qint64 v, qint64 ifn)
292 {
293     if (v == ifn)
294         return noxml();
295     return attr(name, QString::number(v));
296 }
297 
attrS(const char * name,const QString & v)298 inline XmlOutput::xml_output attrS(const char *name, const QString &v)
299 {
300     if(v.isEmpty())
301         return noxml();
302     return attr(name, v);
303 }
304 
attrX(const char * name,const QStringList & v,const char * s=",")305 inline XmlOutput::xml_output attrX(const char *name, const QStringList &v, const char *s = ",")
306 {
307     if(v.isEmpty())
308         return noxml();
309     return attr(name, v.join(s));
310 }
311 
operator !(const triState & rhs)312 triState operator!(const triState &rhs)
313 {
314     if (rhs == unset)
315         return rhs;
316     triState lhs = (rhs == _True ? _False : _True);
317     return lhs;
318 }
319 
320 // VCToolBase -------------------------------------------------
fixCommandLine(const QString & input)321 QStringList VCToolBase::fixCommandLine(const QString &input)
322 {
323     // The splitting regexp is a bit bizarre for backwards compat reasons (why else ...).
324     return input.split(QRegExp(QLatin1String("(\n\t|\r\\\\h|\r\n)\\s*")));
325 }
326 
vcCommandSeparator()327 static QString vcCommandSeparator()
328 {
329     // MSVC transforms the build tree into a single batch file, simply pasting the contents
330     // of the custom commands into it, and putting an "if errorlevel goto" statement behind it.
331     // As we want every sub-command to be error-checked (as is done by makefile-based
332     // backends), we insert the checks ourselves, using the undocumented jump target.
333     static QString cmdSep =
334     QLatin1String("&#x000D;&#x000A;if errorlevel 1 goto VCReportError&#x000D;&#x000A;");
335     return cmdSep;
336 }
337 
unknownOptionWarning(const char * tool,const char * option)338 static void unknownOptionWarning(const char *tool, const char *option)
339 {
340     static bool firstCall = true;
341     warn_msg(WarnLogic, "Could not parse %s option '%s'; added to AdditionalOptions.", tool, option);
342     if (firstCall) {
343         firstCall = false;
344         warn_msg(WarnLogic,
345                  "You can suppress these warnings with CONFIG+=suppress_vcproj_warnings.");
346     }
347 }
348 
349 
350 // VCCLCompilerTool -------------------------------------------------
VCCLCompilerTool()351 VCCLCompilerTool::VCCLCompilerTool()
352     :        AssemblerOutput(asmListingNone),
353         BasicRuntimeChecks(runtimeBasicCheckNone),
354         BrowseInformation(brInfoNone),
355         BufferSecurityCheck(unset),
356         CallingConvention(callConventionDefault),
357         CompileAs(compileAsDefault),
358         CompileAsManaged(managedDefault),
359         CompileAsWinRT(unset),
360         CompileOnly(unset),
361         DebugInformationFormat(debugDisabled),
362         Detect64BitPortabilityProblems(unset),
363         DisableLanguageExtensions(unset),
364         EnableEnhancedInstructionSet(archNotSet),
365         EnableFiberSafeOptimizations(unset),
366         EnableFunctionLevelLinking(unset),
367         EnableIntrinsicFunctions(unset),
368         ExceptionHandling(ehDefault),
369         ExpandAttributedSource(unset),
370         FavorSizeOrSpeed(favorNone),
371         FloatingPointModel(floatingPointNotSet),
372         FloatingPointExceptions(unset),
373         ForceConformanceInForLoopScope(unset),
374         GeneratePreprocessedFile(preprocessNo),
375         PreprocessSuppressLineNumbers(unset),
376         GlobalOptimizations(unset),
377         IgnoreStandardIncludePath(unset),
378         ImproveFloatingPointConsistency(unset),
379         InlineFunctionExpansion(expandDefault),
380         KeepComments(unset),
381         MinimalRebuild(unset),
382         OmitDefaultLibName(unset),
383         OmitFramePointers(unset),
384         OpenMP(unset),
385         Optimization(optimizeCustom),
386         OptimizeForProcessor(procOptimizeBlended),
387         OptimizeForWindowsApplication(unset),
388         ProgramDataBaseFileName(""),
389         RuntimeLibrary(rtMultiThreaded),
390         RuntimeTypeInfo(unset),
391         ShowIncludes(unset),
392         SmallerTypeCheck(unset),
393         StringPooling(unset),
394         StructMemberAlignment(alignNotSet),
395         SuppressStartupBanner(unset),
396         TreatWChar_tAsBuiltInType(unset),
397         TurnOffAssemblyGeneration(unset),
398         UndefineAllPreprocessorDefinitions(unset),
399         UsePrecompiledHeader(pchUnset),
400         UseUnicodeForAssemblerListing(unset),
401         WarnAsError(unset),
402         WarningLevel(warningLevel_0),
403         WholeProgramOptimization(unset),
404         CompileForArchitecture(archUnknown),
405         InterworkCalls(unset),
406         EnablePREfast(unset),
407         DisplayFullPaths(unset),
408         MultiProcessorCompilation(unset),
409         GenerateXMLDocumentationFiles(unset),
410         CreateHotpatchableImage(unset)
411 {
412 }
413 
414 /*
415  * Some values for the attribute UsePrecompiledHeader have changed from VS 2003 to VS 2005,
416  * see the following chart, so we need a function that transforms those values if we are
417  * using NET2005:
418  *
419  * Meaning                      2003    2005
420  * -----------------------------------------
421  * Don't use PCH                0       0
422  * Create PCH (/Yc)             1       1
423  * Automatically generate (/YX) 2       (seems that it was removed)
424  * Use specific PCH (/Yu)       3       2
425  *
426  */
xformUsePrecompiledHeaderForNET2005(pchOption whatPch,DotNET compilerVersion)427 inline XmlOutput::xml_output xformUsePrecompiledHeaderForNET2005(pchOption whatPch, DotNET compilerVersion)
428 {
429     if (compilerVersion >= NET2005) {
430         if (whatPch ==  pchGenerateAuto) whatPch = (pchOption)0;
431         if (whatPch ==  pchUseUsingSpecific) whatPch = (pchOption)2;
432     }
433     return attrE(_UsePrecompiledHeader, whatPch, /*ifNot*/ pchUnset);
434 }
435 
xformExceptionHandlingNET2005(exceptionHandling eh,DotNET compilerVersion)436 inline XmlOutput::xml_output xformExceptionHandlingNET2005(exceptionHandling eh, DotNET compilerVersion)
437 {
438     if (eh == ehDefault)
439         return noxml();
440 
441     if (compilerVersion >= NET2005)
442         return attrE(_ExceptionHandling, eh);
443 
444     return attrS(_ExceptionHandling, (eh == ehNoSEH ? "true" : "false"));
445 }
446 
parseOption(const char * option)447 bool VCCLCompilerTool::parseOption(const char* option)
448 {
449     // skip index 0 ('/' or '-')
450     char first  = option[1];
451     char second = option[2];
452     char third  = option[3];
453     char fourth = option[4];
454     bool found = true;
455 
456     switch (first) {
457     case '?':
458     case 'h':
459         if(second == 'o' && third == 't' && fourth == 'p') {
460             CreateHotpatchableImage = _True;
461             break;
462         }
463         qWarning("Generator: Option '/?', '/help': MSVC.NET projects do not support outputting help info");
464         found = false;
465         break;
466     case '@':
467         qWarning("Generator: Option '/@': MSVC.NET projects do not support the use of a response file");
468         found = false;
469         break;
470     case 'l':
471         qWarning("Generator: Option '/link': qmake generator does not support passing link options through the compiler tool");
472         found = false;
473         break;
474     case 'A':
475         if(second != 'I') {
476             found = false; break;
477         }
478         AdditionalUsingDirectories += option+3;
479         break;
480     case 'C':
481         KeepComments = _True;
482         break;
483     case 'D':
484         PreprocessorDefinitions += option+2;
485         break;
486     case 'E':
487         if(second == 'H') {
488             QByteArray opt(option + 2);
489             if (opt.contains('a') && !opt.contains('s') && !opt.contains('c'))
490                 ExceptionHandling = ehSEH;
491             else if (!opt.contains('a') && opt.contains("s-") && opt.contains("c-"))
492                 ExceptionHandling = ehNone;
493             else if (!opt.contains('a') && opt.contains('s') && opt.contains('c'))
494                 ExceptionHandling = ehNoSEH;
495             else {
496                 // ExceptionHandling must be false, or it will override
497                 // with an /EHsc option
498                 ExceptionHandling = ehNone;
499                 AdditionalOptions += option;
500             }
501             if (config->CompilerVersion < NET2005
502                 && ExceptionHandling == ehSEH) {
503                 ExceptionHandling = ehNone;
504                 AdditionalOptions += option;
505             }
506             break;
507         } else if (second == 'P') {
508             PreprocessSuppressLineNumbers = _True;
509         }
510         GeneratePreprocessedFile = preprocessYes;
511         break;
512     case 'F':
513         if(second <= '9' && second >= '0') {
514             AdditionalOptions += option;
515             break;
516         } else {
517             switch (second) {
518             case 'A':
519                 if(third == 'c') {
520                     AssemblerOutput = asmListingAsmMachine;
521                     if(fourth == 's')
522                         AssemblerOutput = asmListingAsmMachineSrc;
523                 } else if(third == 's') {
524                     AssemblerOutput = asmListingAsmSrc;
525                 } else if (third == 'u') {
526                     UseUnicodeForAssemblerListing = _True;
527                 } else {
528                     AssemblerOutput = asmListingAssemblyOnly;
529                 }
530                 break;
531             case 'C':
532                 DisplayFullPaths = _True;
533                 break;
534             case 'a':
535                 AssemblerListingLocation = option+3;
536                 break;
537             case 'I':
538                 ForcedIncludeFiles += option+3;
539                 break;
540             case 'i':
541                 PreprocessOutputPath += option+3;
542                 break;
543             case 'R':
544                 BrowseInformation = brAllInfo;
545                 BrowseInformationFile = option+3;
546                 break;
547             case 'S':
548                 if (config->CompilerVersion < NET2013)
549                     found = false;
550                 // Ignore this flag. Visual Studio 2013 takes care of this setting.
551                 break;
552             case 'r':
553                 BrowseInformation = brNoLocalSymbols;
554                 BrowseInformationFile = option+3;
555                 break;
556             case 'U':
557                 ForcedUsingFiles += option+3;
558                 break;
559             case 'd':
560                 ProgramDataBaseFileName = option+3;
561                 break;
562             case 'e':
563                 OutputFile = option+3;
564                 break;
565             case 'm':
566                 AdditionalOptions += option;
567                 break;
568             case 'o':
569                 ObjectFile = option+3;
570                 break;
571             case 'p':
572                 PrecompiledHeaderFile = option+3;
573                 break;
574             case 'x':
575                 ExpandAttributedSource = _True;
576                 break;
577             default:
578                 found = false; break;
579             }
580         }
581         break;
582     case 'G':
583         switch (second) {
584         case '3':
585         case '4':
586             qWarning("Option '/G3' and '/G4' were phased out in Visual C++ 5.0");
587             found = false; break;
588         case '5':
589             OptimizeForProcessor = procOptimizePentium;
590             break;
591         case '6':
592         case 'B':
593             OptimizeForProcessor = procOptimizePentiumProAndAbove;
594             break;
595         case '7':
596             OptimizeForProcessor = procOptimizePentium4AndAbove;
597             break;
598         case 'A':
599             OptimizeForWindowsApplication = _True;
600             break;
601         case 'F':
602             StringPooling = _True;
603             break;
604         case 'H':
605             AdditionalOptions += option;
606             break;
607         case 'L':
608             WholeProgramOptimization = _True;
609             if(third == '-')
610                 WholeProgramOptimization = _False;
611             break;
612         case 'R':
613             RuntimeTypeInfo = _True;
614             if(third == '-')
615                 RuntimeTypeInfo = _False;
616             break;
617         case 'S':
618             BufferSecurityCheck = _True;
619             if(third == '-')
620                 BufferSecurityCheck = _False;
621             break;
622         case 'T':
623             EnableFiberSafeOptimizations = _True;
624             break;
625         case 'X':
626             // Same as the /EHsc option, which is Exception Handling without SEH
627             ExceptionHandling = ehNoSEH;
628             if (third == '-')
629                 ExceptionHandling = ehNone;
630             break;
631         case 'Z':
632         case 'e':
633         case 'h':
634             AdditionalOptions += option;
635             break;
636         case 'd':
637             CallingConvention = callConventionCDecl;
638             break;
639         case 'f':
640             StringPooling = _True;
641             AdditionalOptions += option;
642             break;
643         case 'm':
644             MinimalRebuild = _True;
645             if(third == '-')
646                 MinimalRebuild = _False;
647             break;
648         case 'r':
649             CallingConvention = callConventionFastCall;
650             break;
651         case 's':
652             AdditionalOptions += option;
653             break;
654         case 'y':
655             EnableFunctionLevelLinking = _True;
656             break;
657         case 'z':
658             CallingConvention = callConventionStdCall;
659             break;
660         default:
661             found = false; break;
662         }
663         break;
664     case 'H':
665         AdditionalOptions += option;
666         break;
667     case 'I':
668         AdditionalIncludeDirectories += option+2;
669         break;
670     case 'J':
671         AdditionalOptions += option;
672         break;
673     case 'L':
674         if(second == 'D') {
675             AdditionalOptions += option;
676             break;
677         }
678         found = false; break;
679     case 'M':
680         if(second == 'D') {
681             RuntimeLibrary = rtMultiThreadedDLL;
682             if(third == 'd')
683                 RuntimeLibrary = rtMultiThreadedDebugDLL;
684             break;
685         } else if(second == 'L') {
686             RuntimeLibrary = rtSingleThreaded;
687             if(third == 'd')
688                 RuntimeLibrary = rtSingleThreadedDebug;
689             break;
690         } else if(second == 'T') {
691             RuntimeLibrary = rtMultiThreaded;
692             if(third == 'd')
693                 RuntimeLibrary = rtMultiThreadedDebug;
694             break;
695         } else if (second == 'P') {
696             if (config->CompilerVersion >= NET2010) {
697                 MultiProcessorCompilation = _True;
698                 MultiProcessorCompilationProcessorCount = option+3;
699             } else if (config->CompilerVersion >= NET2005) {
700                 AdditionalOptions += option;
701             } else {
702                 warn_msg(WarnLogic, "/MP option is not supported in Visual C++ < 2005, ignoring.");
703             }
704             break;
705         }
706         found = false; break;
707     case 'O':
708         switch (second) {
709         case '1':
710             Optimization = optimizeMinSpace;
711             break;
712         case '2':
713             Optimization = optimizeMaxSpeed;
714             break;
715         case 'a':
716             AdditionalOptions += option;
717             break;
718         case 'b':
719             if(third == '0')
720                 InlineFunctionExpansion = expandDisable;
721             else if(third == '1')
722                 InlineFunctionExpansion = expandOnlyInline;
723             else if(third == '2')
724                 InlineFunctionExpansion = expandAnySuitable;
725             else
726                 found = false;
727             break;
728         case 'd':
729             Optimization = optimizeDisabled;
730             break;
731         case 'g':
732             GlobalOptimizations = _True;
733             break;
734         case 'i':
735             EnableIntrinsicFunctions = _True;
736             break;
737         case 'p':
738             ImproveFloatingPointConsistency = _True;
739             if(third == '-')
740                 ImproveFloatingPointConsistency = _False;
741             break;
742         case 's':
743             FavorSizeOrSpeed = favorSize;
744             break;
745         case 't':
746             FavorSizeOrSpeed = favorSpeed;
747             break;
748         case 'w':
749             AdditionalOptions += option;
750             break;
751         case 'x':
752             Optimization = optimizeFull;
753             break;
754         case 'y':
755             OmitFramePointers = _True;
756             if(third == '-')
757                 OmitFramePointers = _False;
758             break;
759         default:
760             found = false; break;
761         }
762         break;
763     case 'P':
764         GeneratePreprocessedFile = preprocessYes;
765         break;
766     case 'Q':
767         if(second == 'I') {
768             AdditionalOptions += option;
769             break;
770         } else if (second == 'R') {
771             QString opt = option + 3;
772             if (opt == "interwork-return") {
773                 InterworkCalls = _True;
774                 break;
775             } else if (opt == "arch4") {
776                 CompileForArchitecture = archArmv4;
777                 break;
778             } else if (opt == "arch5") {
779                 CompileForArchitecture = archArmv5;
780                 break;
781             } else if (opt == "arch4T") {
782                 CompileForArchitecture = archArmv4T;
783                 break;
784             } else if (opt == "arch5T") {
785                 CompileForArchitecture = archArmv5T;
786                 break;
787             }
788         } else if (second == 'M') {
789             QString opt = option + 3;
790             if (opt == "mips1") {
791                 CompileForArchitecture = archMips1;
792                 break;
793             }
794             else if (opt == "mips2") {
795                 CompileForArchitecture = archMips2;
796                 break;
797             }
798             else if (opt == "mips3") {
799                 CompileForArchitecture = archMips3;
800                 break;
801             }
802             else if (opt == "mips4") {
803                 CompileForArchitecture = archMips4;
804                 break;
805             }
806             else if (opt == "mips5") {
807                 CompileForArchitecture = archMips5;
808                 break;
809             }
810             else if (opt == "mips16") {
811                 CompileForArchitecture = archMips16;
812                 break;
813             }
814             else if (opt == "mips32") {
815                 CompileForArchitecture = archMips32;
816                 break;
817             }
818             else if (opt == "mips64") {
819                 CompileForArchitecture = archMips64;
820                 break;
821             }
822         }
823         found = false; break;
824     case 'R':
825         if(second == 'T' && third == 'C') {
826             int rtc = BasicRuntimeChecks;
827             for (size_t i = 4; option[i]; ++i) {
828                 if (!parseRuntimeCheckOption(option[i], &rtc)) {
829                     found = false;
830                     break;
831                 }
832             }
833             BasicRuntimeChecks = static_cast<basicRuntimeCheckOption>(rtc);
834         }
835         break;
836     case 'T':
837         if(second == 'C') {
838             CompileAs = compileAsC;
839         } else if(second == 'P') {
840             CompileAs = compileAsCPlusPlus;
841         } else {
842             qWarning("Generator: Options '/Tp<filename>' and '/Tc<filename>' are not supported by qmake");
843             found = false; break;
844         }
845         break;
846     case 'U':
847         UndefinePreprocessorDefinitions += option+2;
848         break;
849     case 'V':
850         AdditionalOptions += option;
851         break;
852     case 'W':
853         switch (second) {
854         case 'a':
855         case '4':
856             WarningLevel = warningLevel_4;
857             break;
858         case '3':
859             WarningLevel = warningLevel_3;
860             break;
861         case '2':
862             WarningLevel = warningLevel_2;
863             break;
864         case '1':
865             WarningLevel = warningLevel_1;
866             break;
867         case '0':
868             WarningLevel = warningLevel_0;
869             break;
870         case 'L':
871             AdditionalOptions += option;
872             break;
873         case 'X':
874             WarnAsError = _True;
875             break;
876         case 'p':
877             if(third == '6' && fourth == '4') {
878                 if (config->CompilerVersion >= NET2010) {
879                      // Deprecated for VS2010 but can be used under Additional Options.
880                     AdditionalOptions += option;
881                 } else {
882                    Detect64BitPortabilityProblems = _True;
883                 }
884                 break;
885             }
886             // Fallthrough
887         default:
888             found = false; break;
889         }
890         break;
891     case 'X':
892         IgnoreStandardIncludePath = _True;
893         break;
894     case 'Y':
895         switch (second) {
896         case '\0':
897         case '-':
898             AdditionalOptions += option;
899             break;
900         case 'X':
901             UsePrecompiledHeader = pchGenerateAuto;
902             PrecompiledHeaderThrough = option+3;
903             break;
904         case 'c':
905             UsePrecompiledHeader = pchCreateUsingSpecific;
906             PrecompiledHeaderThrough = option+3;
907             break;
908         case 'd':
909         case 'l':
910             AdditionalOptions += option;
911             break;
912         case 'u':
913             UsePrecompiledHeader = pchUseUsingSpecific;
914             PrecompiledHeaderThrough = option+3;
915             break;
916         default:
917             found = false; break;
918         }
919         break;
920     case 'Z':
921         switch (second) {
922         case '7':
923             DebugInformationFormat = debugOldStyleInfo;
924             break;
925         case 'I':
926             DebugInformationFormat = debugEditAndContinue;
927             break;
928         case 'd':
929             DebugInformationFormat = debugLineInfoOnly;
930             break;
931         case 'i':
932             DebugInformationFormat = debugEnabled;
933             break;
934         case 'l':
935             OmitDefaultLibName = _True;
936             break;
937         case 'a':
938             DisableLanguageExtensions = _True;
939             break;
940         case 'e':
941             DisableLanguageExtensions = _False;
942             break;
943         case 'c':
944             if(third == ':') {
945                 const char *c = option + 4;
946                 // Go to the end of the option
947                 while ( *c != '\0' && *c != ' ' && *c != '-')
948                     ++c;
949                 if(fourth == 'f')
950                     ForceConformanceInForLoopScope = ((*c) == '-' ? _False : _True);
951                 else if(fourth == 'w')
952                     TreatWChar_tAsBuiltInType = ((*c) == '-' ? _False : _True);
953                 else
954                     AdditionalOptions += option;
955             } else {
956                 found = false; break;
957             }
958             break;
959         case 'g':
960         case 'm':
961         case 's':
962             AdditionalOptions += option;
963             break;
964         case 'p':
965             switch (third)
966             {
967             case '\0':
968             case '1':
969                 StructMemberAlignment = alignSingleByte;
970                 if(fourth == '6')
971                     StructMemberAlignment = alignSixteenBytes;
972                 break;
973             case '2':
974                 StructMemberAlignment = alignTwoBytes;
975                 break;
976             case '4':
977                 StructMemberAlignment = alignFourBytes;
978                 break;
979             case '8':
980                 StructMemberAlignment = alignEightBytes;
981                 break;
982             default:
983                 found = false; break;
984             }
985             break;
986         case 'W':
987             if (third == '-')
988                 CompileAsWinRT = _False;
989             else
990                 CompileAsWinRT = _True;
991             break;
992         default:
993             found = false; break;
994         }
995         break;
996     case 'a':
997         if (second == 'r' && third == 'c' && fourth == 'h') {
998             if (option[5] == ':') {
999                 const char *o = option;
1000                 if (o[6] == 'S' && o[7] == 'S' && o[8] == 'E') {
1001                     EnableEnhancedInstructionSet = o[9] == '2' ? archSSE2 : archSSE;
1002                     break;
1003                 }
1004             }
1005         } else if (second == 'n' && third == 'a' && fourth == 'l') {
1006             EnablePREfast = _True;
1007             break;
1008         }
1009         found = false;
1010         break;
1011     case 'b':   // see http://msdn2.microsoft.com/en-us/library/ms173499.aspx
1012         if (second == 'i' && third == 'g' && fourth == 'o') {
1013             const char *o = option;
1014             if (o[5] == 'b' && o[6] == 'j') {
1015                 AdditionalOptions += option;
1016                 break;
1017             }
1018         }
1019         found = false;
1020         break;
1021     case 'c':
1022         if(second == '\0') {
1023             CompileOnly = _True;
1024         } else if(second == 'l') {
1025             if (config->CompilerVersion < NET2005) {
1026                 if(*(option+5) == 'n') {
1027                     CompileAsManaged = managedAssemblyPure;
1028                     TurnOffAssemblyGeneration = _True;
1029                 } else if(*(option+5) == 'p') {
1030                     CompileAsManaged = managedAssemblyPure;
1031                     warn_msg(WarnLogic, "/clr:pure option only for .NET >= 2005, using /clr");
1032                 } else if(*(option+5) == 's') {
1033                     CompileAsManaged = managedAssemblyPure;
1034                     warn_msg(WarnLogic, "/clr:safe option only for .NET >= 2005, using /clr");
1035                 } else if(*(option+5) == 'o') {
1036                     CompileAsManaged = managedAssemblyPure;
1037                     warn_msg(WarnLogic, "/clr:oldSyntax option only for .NET >= 2005, using /clr");
1038                 } else if(*(option+5) == 'i') {
1039                     CompileAsManaged = managedAssemblyPure;
1040                     warn_msg(WarnLogic, "initialAppDomain enum value unknown, using /crl");
1041                 } else {
1042                     CompileAsManaged = managedAssemblyPure;
1043                 }
1044             } else {
1045                 if(*(option+5) == 'n') {
1046                     CompileAsManaged = managedAssembly;
1047                     TurnOffAssemblyGeneration = _True;
1048                 } else if(*(option+5) == 'p') {
1049                     CompileAsManaged = managedAssemblyPure;
1050                 } else if(*(option+5) == 's') {
1051                     CompileAsManaged = managedAssemblySafe;
1052                 } else if(*(option+5) == 'o') {
1053                     CompileAsManaged = managedAssemblyOldSyntax;
1054                 } else if(*(option+5) == 'i') {
1055                     CompileAsManaged = managedAssembly;
1056                     warn_msg(WarnLogic, "initialAppDomain enum value unknown, using /crl default");
1057                 } else {
1058                     CompileAsManaged = managedAssembly;
1059                 }
1060             }
1061         } else {
1062             found = false; break;
1063         }
1064         break;
1065     case 'd':
1066         if (second == 'r') {
1067             CompileAsManaged = managedAssembly;
1068             break;
1069         } else if (second != 'o' && third == 'c') {
1070             GenerateXMLDocumentationFiles = _True;
1071             XMLDocumentationFileName += option+4;
1072             break;
1073         }
1074         found = false;
1075         break;
1076     case 'e':
1077         if (second == 'r' && third == 'r' && fourth == 'o') {
1078             if (option[12] == ':') {
1079                 if ( option[13] == 'n') {
1080                     ErrorReporting = "None";
1081                 } else if (option[13] == 'p') {
1082                     ErrorReporting = "Prompt";
1083                 } else if (option[13] == 'q') {
1084                     ErrorReporting = "Queue";
1085                 } else if (option[13] == 's') {
1086                     ErrorReporting = "Send";
1087                 } else {
1088                     found = false;
1089                 }
1090                 break;
1091             }
1092         }
1093         found = false;
1094         break;
1095     case 'f':
1096         if(second == 'p' && third == ':') {
1097             // Go to the end of the option
1098             const char *c = option + 4;
1099             while (*c != '\0' && *c != ' ' && *c != '-')
1100                 ++c;
1101             switch (fourth) {
1102             case 'e':
1103                 FloatingPointExceptions = ((*c) == '-' ? _False : _True);
1104                 break;
1105             case 'f':
1106                 FloatingPointModel = floatingPointFast;
1107                 break;
1108             case 'p':
1109                 FloatingPointModel = floatingPointPrecise;
1110                 break;
1111             case 's':
1112                 FloatingPointModel = floatingPointStrict;
1113                 break;
1114             default:
1115                 found = false;
1116                 break;
1117             }
1118         }
1119         break;
1120     case 'n':
1121         if(second == 'o' && third == 'B' && fourth == 'o') {
1122             AdditionalOptions += "/noBool";
1123             break;
1124         }
1125         if(second == 'o' && third == 'l' && fourth == 'o') {
1126             SuppressStartupBanner = _True;
1127             break;
1128         }
1129         found = false; break;
1130     case 'o':
1131     {
1132         const char *str = option + 2;
1133         const size_t len = strlen(str);
1134         if (len >= 5 && len <= 6 && strncmp(str, "penmp", 5) == 0) {
1135             if (len == 5) {
1136                 OpenMP = _True;
1137                 break;
1138             } else if (str[5] == '-') {
1139                 OpenMP = _False;
1140                 break;
1141             }
1142         }
1143         found = false; break;
1144     }
1145     case 's':
1146         if(second == 'h' && third == 'o' && fourth == 'w') {
1147             ShowIncludes = _True;
1148             break;
1149         }
1150         if (strlen(option) > 8 && second == 't' && third == 'd') {
1151             const QString version = option + 8;
1152             static const QStringList knownVersions = { "14", "17", "latest" };
1153             if (knownVersions.contains(version)) {
1154                 LanguageStandard = "stdcpp" + version;
1155                 break;
1156             }
1157         }
1158         found = false; break;
1159     case 'u':
1160         if (!second)
1161             UndefineAllPreprocessorDefinitions = _True;
1162         else if (strcmp(option + 2, "tf-8") == 0)
1163             AdditionalOptions += option;
1164         else
1165             found = false;
1166         break;
1167     case 'v':
1168         if(second == 'd' || second == 'm') {
1169             AdditionalOptions += option;
1170             break;
1171         }
1172         found = false; break;
1173     case 'w':
1174         switch (second) {
1175         case '\0':
1176             WarningLevel = warningLevel_0;
1177             break;
1178         case 'd':
1179             DisableSpecificWarnings += option+3;
1180             break;
1181         case 'e':
1182             if (config->CompilerVersion <= NET2008)
1183                 AdditionalOptions += option;
1184             else
1185                 TreatSpecificWarningsAsErrors += option + 3;
1186             break;
1187         default:
1188             AdditionalOptions += option;
1189         }
1190         break;
1191     default:
1192         AdditionalOptions += option;
1193         break;
1194     }
1195     if(!found) {
1196         if (!config->suppressUnknownOptionWarnings)
1197             unknownOptionWarning("Compiler", option);
1198         AdditionalOptions += option;
1199     }
1200     return true;
1201 }
1202 
parseRuntimeCheckOption(char c,int * rtc)1203 bool VCCLCompilerTool::parseRuntimeCheckOption(char c, int *rtc)
1204 {
1205     if (c == '1')
1206         *rtc = runtimeBasicCheckAll;
1207     else if (c == 'c')
1208         SmallerTypeCheck = _True;
1209     else if (c == 's')
1210         *rtc |= runtimeCheckStackFrame;
1211     else if (c == 'u')
1212         *rtc |= runtimeCheckUninitVariables;
1213     else
1214         return false;
1215     return true;
1216 }
1217 
1218 // VCLinkerTool -----------------------------------------------------
VCLinkerTool()1219 VCLinkerTool::VCLinkerTool()
1220     :   DataExecutionPrevention(unset),
1221         EnableCOMDATFolding(optFoldingDefault),
1222         GenerateDebugInformation(unset),
1223         DebugInfoOption(linkerDebugOptionNone),
1224         GenerateMapFile(unset),
1225         HeapCommitSize(-1),
1226         HeapReserveSize(-1),
1227         IgnoreAllDefaultLibraries(unset),
1228         IgnoreEmbeddedIDL(unset),
1229         IgnoreImportLibrary(_True),
1230         ImageHasSafeExceptionHandlers(unset),
1231         LargeAddressAware(addrAwareDefault),
1232         LinkDLL(unset),
1233         LinkIncremental(linkIncrementalDefault),
1234         LinkTimeCodeGeneration(optLTCGDefault),
1235         MapExports(unset),
1236         MapLines(unset),
1237         OptimizeForWindows98(optWin98Default),
1238         OptimizeReferences(optReferencesDefault),
1239         RandomizedBaseAddress(unset),
1240         RegisterOutput(unset),
1241         ResourceOnlyDLL(unset),
1242         SetChecksum(unset),
1243         ShowProgress(linkProgressNotSet),
1244         StackCommitSize(-1),
1245         StackReserveSize(-1),
1246         SubSystem(subSystemNotSet),
1247         SupportUnloadOfDelayLoadedDLL(unset),
1248         SuppressStartupBanner(unset),
1249         SwapRunFromCD(unset),
1250         SwapRunFromNet(unset),
1251         TargetMachine(machineNotSet),
1252         TerminalServerAware(termSvrAwareDefault),
1253         TreatWarningsAsErrors(unset),
1254         TurnOffAssemblyGeneration(unset),
1255         TypeLibraryResourceID(0),
1256         GenerateManifest(unset),
1257         EnableUAC(unset),
1258         UACUIAccess(unset),
1259         SectionAlignment(-1),
1260         PreventDllBinding(unset),
1261         AllowIsolation(unset),
1262         AssemblyDebug(unset),
1263         CLRUnmanagedCodeCheck(unset),
1264         DelaySign(unset),
1265         GenerateWindowsMetadata(unset)
1266 {
1267 }
1268 
1269 // Hashing routine to do fast option lookups ----
1270 // Slightly rewritten to stop on ':' ',' and '\0'
1271 // Original routine in qtranslator.cpp ----------
elfHash(const char * name)1272 static uint elfHash(const char* name)
1273 {
1274     const uchar *k;
1275     uint h = 0;
1276     uint g;
1277 
1278     if(name) {
1279         k = (const uchar *) name;
1280         while((*k) &&
1281                 (*k)!= ':' &&
1282                 (*k)!=',' &&
1283                 (*k)!=' ') {
1284             h = (h << 4) + *k++;
1285             if((g = (h & 0xf0000000)) != 0)
1286                 h ^= g >> 24;
1287             h &= ~g;
1288         }
1289     }
1290     if(!h)
1291         h = 1;
1292     return h;
1293 }
1294 
1295 //#define USE_DISPLAY_HASH
1296 #ifdef USE_DISPLAY_HASH
displayHash(const char * str)1297 static void displayHash(const char* str)
1298 {
1299     printf("case 0x%07x: // %s\n    break;\n", elfHash(str), str);
1300 }
1301 #endif
1302 
parseOption(const char * option)1303 bool VCLinkerTool::parseOption(const char* option)
1304 {
1305 #ifdef USE_DISPLAY_HASH
1306     // Main options
1307     displayHash("/ALIGN"); displayHash("/ALLOWBIND"); displayHash("/ASSEMBLYMODULE");
1308     displayHash("/ASSEMBLYRESOURCE"); displayHash("/BASE"); displayHash("/DEBUG");
1309     displayHash("/DEF"); displayHash("/DEFAULTLIB"); displayHash("/DELAY");
1310     displayHash("/DELAYLOAD"); displayHash("/DLL"); displayHash("/DRIVER");
1311     displayHash("/ENTRY"); displayHash("/EXETYPE"); displayHash("/EXPORT");
1312     displayHash("/FIXED"); displayHash("/FORCE"); displayHash("/HEAP");
1313     displayHash("/IDLOUT"); displayHash("/IGNORE"); displayHash("/IGNOREIDL"); displayHash("/IMPLIB");
1314     displayHash("/INCLUDE"); displayHash("/INCREMENTAL"); displayHash("/LARGEADDRESSAWARE");
1315     displayHash("/LIBPATH"); displayHash("/LTCG"); displayHash("/MACHINE");
1316     displayHash("/MAP"); displayHash("/MAPINFO"); displayHash("/MERGE");
1317     displayHash("/MIDL"); displayHash("/NOASSEMBLY"); displayHash("/NODEFAULTLIB");
1318     displayHash("/NOENTRY"); displayHash("/NOLOGO"); displayHash("/OPT");
1319     displayHash("/ORDER"); displayHash("/OUT"); displayHash("/PDB");
1320     displayHash("/PDBSTRIPPED"); displayHash("/RELEASE"); displayHash("/SECTION");
1321     displayHash("/STACK"); displayHash("/STUB"); displayHash("/SUBSYSTEM");
1322     displayHash("/SWAPRUN"); displayHash("/TLBID"); displayHash("/TLBOUT");
1323     displayHash("/TSAWARE"); displayHash("/VERBOSE"); displayHash("/VERSION");
1324     displayHash("/VXD"); displayHash("/WS "); displayHash("/libpath");
1325     displayHash("/WINMD"); displayHash("/WINMDFILE:");
1326 
1327 #endif
1328 #ifdef USE_DISPLAY_HASH
1329     // Sub options
1330     displayHash("UNLOAD"); displayHash("NOBIND"); displayHash("no"); displayHash("NOSTATUS"); displayHash("STATUS");
1331     displayHash("AM33"); displayHash("ARM"); displayHash("CEE"); displayHash("EBC"); displayHash("IA64"); displayHash("X86"); displayHash("X64"); displayHash("M32R");
1332     displayHash("MIPS"); displayHash("MIPS16"); displayHash("MIPSFPU"); displayHash("MIPSFPU16"); displayHash("MIPSR41XX"); displayHash("PPC");
1333     displayHash("SH3"); displayHash("SH3DSP"); displayHash("SH4"); displayHash("SH5"); displayHash("THUMB"); displayHash("TRICORE"); displayHash("EXPORTS");
1334     displayHash("LINES"); displayHash("REF"); displayHash("NOREF"); displayHash("ICF"); displayHash("WIN98"); displayHash("NOWIN98");
1335     displayHash("CONSOLE"); displayHash("EFI_APPLICATION"); displayHash("EFI_BOOT_SERVICE_DRIVER"); displayHash("EFI_ROM"); displayHash("EFI_RUNTIME_DRIVER"); displayHash("NATIVE");
1336     displayHash("POSIX"); displayHash("WINDOWS"); displayHash("WINDOWSCE"); displayHash("NET"); displayHash("CD"); displayHash("NO");
1337 #endif
1338     bool found = true;
1339     const uint optionHash = elfHash(option);
1340     if (config->CompilerVersion < NET2010) {
1341         switch (optionHash) {
1342         case 0x3360dbe: // /ALIGN[:number]
1343         case 0x1485c34: // /ALLOWBIND[:NO]
1344         case 0x33aec94: // /FIXED[:NO]
1345         case 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#]
1346         case 0x0348992: // /STUB:filename
1347             AdditionalOptions += option;
1348             return true;
1349         }
1350     }
1351 
1352     switch (optionHash) {
1353     case 0x6b21972: // /DEFAULTLIB:library
1354     case 0x396ea92: // /DRIVER[:UPONLY | :WDM]
1355     case 0xaca9d75: // /EXETYPE[:DYNAMIC | :DEV386]
1356     case 0x3ad5444: // /EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
1357     case 0x33b4675: // /FORCE:[MULTIPLE|UNRESOLVED]
1358     case 0x3dc3455: // /IGNORE:number,number,number,number  ### NOTE: This one is undocumented, but it is even used by Microsoft.
1359                     //                                      In recent versions of the Microsoft linker they have disabled this undocumented feature.
1360     case 0x0034bc4: // /VXD
1361         AdditionalOptions += option;
1362         break;
1363     case 0x3360dbe: // /ALIGN[:number]
1364         SectionAlignment = QString(option+7).toLongLong();
1365         break;
1366     case 0x1485c34: // /ALLOWBIND[:NO]
1367         if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N'))
1368             PreventDllBinding = _False;
1369         else
1370             PreventDllBinding = _True;
1371         break;
1372     case 0x312011e: // /ALLOWISOLATION[:NO]
1373         if(*(option+15) == ':' && (*(option+16) == 'n' || *(option+16) == 'N'))
1374             AllowIsolation = _False;
1375         else
1376             AllowIsolation = _True;
1377         break;
1378     case 0x679c075: // /ASSEMBLYMODULE:filename
1379         AddModuleNamesToAssembly += option+15;
1380         break;
1381     case 0x75f35f7: // /ASSEMBLYDEBUG[:DISABLE]
1382         if(*(option+14) == ':' && (*(option+15) == 'D'))
1383             AssemblyDebug = _False;
1384         else
1385             AssemblyDebug = _True;
1386         break;
1387     case 0x43294a5: // /ASSEMBLYLINKRESOURCE:filename
1388             AssemblyLinkResource += option+22;
1389         break;
1390     case 0x062d065: // /ASSEMBLYRESOURCE:filename
1391         LinkToManagedResourceFile = option+18;
1392         break;
1393     case 0x0336675: // /BASE:{address | @filename,key}
1394         // Do we need to do a manual lookup when '@filename,key'?
1395         // Seems BaseAddress only can contain the location...
1396         // We don't use it in Qt, so keep it simple for now
1397         BaseAddress = option+6;
1398         break;
1399     case 0x63bf065: // /CLRIMAGETYPE:{IJW|PURE|SAFE}
1400         if(*(option+14) == 'I')
1401             CLRImageType = "ForceIJWImage";
1402         else if(*(option+14) == 'P')
1403             CLRImageType = "ForcePureILImage";
1404         else if(*(option+14) == 'S')
1405             CLRImageType = "ForceSafeILImage";
1406         break;
1407     case 0x5f2a6a2: // /CLRSUPPORTLASTERROR{:NO | SYSTEMDLL}
1408         if(*(option+20) == ':') {
1409             if(*(option+21) == 'N') {
1410                 CLRSupportLastError = "Disabled";
1411             } else if(*(option+21) == 'S') {
1412                 CLRSupportLastError = "SystemDlls";
1413             }
1414         } else {
1415             CLRSupportLastError = "Enabled";
1416         }
1417         break;
1418     case 0xc7984f5: // /CLRTHREADATTRIBUTE:{STA|MTA|NONE}
1419         if(*(option+20) == 'N')
1420             CLRThreadAttribute = "DefaultThreadingAttribute";
1421         else if(*(option+20) == 'M')
1422             CLRThreadAttribute = "MTAThreadingAttribute";
1423         else if(*(option+20) == 'S')
1424             CLRThreadAttribute = "STAThreadingAttribute";
1425         break;
1426     case 0xa8c637b: // /CLRUNMANAGEDCODECHECK[:NO]
1427         if(*(option+23) == 'N')
1428             CLRUnmanagedCodeCheck = _False;
1429         else
1430             CLRUnmanagedCodeCheck = _True;
1431         break;
1432     case 0x62d9e94: // /MANIFEST[:NO]
1433         if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n')))
1434             GenerateManifest = _False;
1435         else
1436             GenerateManifest = _True;
1437         break;
1438     case 0x34be314: // /WINMD[:NO]
1439         if ((*(option+6) == ':' && (*(option+7) == 'N' || *(option+7) == 'n')))
1440             GenerateWindowsMetadata = _False;
1441         else
1442             GenerateWindowsMetadata = _True;
1443         break;
1444     case 0x31be7e5: // /WINMDFILE:filename
1445         WindowsMetadataFile = option+11;
1446         break;
1447     case 0x8b64559: // /MANIFESTDEPENDENCY:manifest_dependency
1448         AdditionalManifestDependencies += option+20;
1449         break;
1450     case 0xe9e8195: // /MANIFESTFILE:filename
1451         ManifestFile = option+14;
1452         break;
1453     case 0x9e9fb83: // /MANIFESTUAC http://msdn.microsoft.com/en-us/library/bb384691%28VS.100%29.aspx
1454         if ((*(option+12) == ':' && (*(option+13) == 'N' || *(option+13) == 'n')))
1455             EnableUAC = _False;
1456         else if((*(option+12) == ':' && (*(option+13) == 'l' || *(option+14) == 'e'))) { // level
1457             if(*(option+20) == 'a')
1458                 UACExecutionLevel = "AsInvoker";
1459             else if(*(option+20) == 'h')
1460                 UACExecutionLevel = "HighestAvailable";
1461             else if(*(option+20) == 'r')
1462                 UACExecutionLevel = "RequireAdministrator";
1463         } else if((*(option+12) == ':' && (*(option+13) == 'u' || *(option+14) == 'i'))) { // uiAccess
1464             if(*(option+22) == 't')
1465                 UACUIAccess = _True;
1466             else
1467                 UACUIAccess = _False;
1468         } else if((*(option+12) == ':' && (*(option+13) == 'f' || *(option+14) == 'r'))) { // fragment
1469             AdditionalOptions += option;
1470         }else
1471             EnableUAC = _True;
1472         break;
1473     case 0x3389797: // /DEBUG[:FASTLINK]
1474         GenerateDebugInformation = _True;
1475         if (config->CompilerVersion >= NET2015 && strcmp(option + 7, "FASTLINK") == 0)
1476             DebugInfoOption = linkerDebugOptionFastLink;
1477         break;
1478     case 0x0033896: // /DEF:filename
1479         ModuleDefinitionFile = option+5;
1480         break;
1481     case 0x338a069: // /DELAY:{UNLOAD | NOBIND}
1482         // MS documentation does not specify what to do with
1483         // this option, so we'll put it in AdditionalOptions
1484         AdditionalOptions += option;
1485         break;
1486     case 0x06f4bf4: // /DELAYLOAD:dllname
1487         DelayLoadDLLs += option+11;
1488         break;
1489     case 0x06d451e: // /DELAYSIGN[:NO]
1490         if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N'))
1491             DelaySign = _False;
1492         else
1493             DelaySign = _True;
1494         break;
1495     case 0x003390c: // /DLL
1496         // This option is not used for vcproj files
1497         break;
1498     case 0x2ee8415: // /DYNAMICBASE[:NO]
1499         if(*(option+12) == ':' && (*(option+13) == 'n' || *(option+13) == 'N'))
1500             RandomizedBaseAddress = _False;
1501         else
1502             RandomizedBaseAddress = _True;
1503         break;
1504     case 0x33a3979: // /ENTRY:function
1505         EntryPointSymbol = option+7;
1506         break;
1507     case 0x4504334: // /ERRORREPORT:[ NONE | PROMPT | QUEUE | SEND ]
1508         if(*(option+12) == ':' ) {
1509             if(*(option+13) == 'N')
1510                 LinkErrorReporting = "NoErrorReport";
1511             else if(*(option+13) == 'P')
1512                 LinkErrorReporting = "PromptImmediately";
1513             else if(*(option+13) == 'Q')
1514                 LinkErrorReporting = "QueueForNextLogin";
1515             else if(*(option+13) == 'S')
1516                 LinkErrorReporting = "SendErrorReport";
1517         }
1518         break;
1519     case 0x033c960: // /HEAP:reserve[,commit]
1520         {
1521             QStringList both = QString(option+6).split(",");
1522             HeapReserveSize = both[0].toLongLong();
1523             if(both.count() == 2)
1524                 HeapCommitSize = both[1].toLongLong();
1525         }
1526         break;
1527     case 0x3d91494: // /IDLOUT:[path\]filename
1528         MergedIDLBaseFileName = option+8;
1529         break;
1530     case 0x345a04c: // /IGNOREIDL
1531         IgnoreEmbeddedIDL = _True;
1532         break;
1533     case 0x3e250e2: // /IMPLIB:filename
1534         ImportLibrary = option+8;
1535         break;
1536     case 0xe281ab5: // /INCLUDE:symbol
1537         ForceSymbolReferences += option+9;
1538         break;
1539     case 0xb28103c: // /INCREMENTAL[:no]
1540         if(*(option+12) == ':' &&
1541              (*(option+13) == 'n' || *(option+13) == 'N'))
1542             LinkIncremental = linkIncrementalNo;
1543         else
1544             LinkIncremental = linkIncrementalYes;
1545         break;
1546     case 0x07f1ab2: // /KEYCONTAINER:name
1547         KeyContainer = option+14;
1548         break;
1549     case 0xfadaf35: // /KEYFILE:filename
1550         KeyFile = option+9;
1551         break;
1552     case 0x26e4675: // /LARGEADDRESSAWARE[:no]
1553         if(*(option+18) == ':' &&
1554              *(option+19) == 'n')
1555             LargeAddressAware = addrAwareNoLarge;
1556         else
1557             LargeAddressAware = addrAwareLarge;
1558         break;
1559     case 0x2f96bc8: // /libpath:dir
1560     case 0x0d745c8: // /LIBPATH:dir
1561         AdditionalLibraryDirectories += option+9;
1562         break;
1563     case 0x0341877: // /LTCG[:NOSTATUS|:STATUS]
1564         config->WholeProgramOptimization = _True;
1565         if (config->CompilerVersion >= NET2005) {
1566             LinkTimeCodeGeneration = optLTCGEnabled;
1567             if(*(option+5) == ':') {
1568                 const char* str = option+6;
1569                 if (*str == 'S')
1570                     ShowProgress = linkProgressAll;
1571                 else if (qstricmp(str, "pginstrument") == 0)
1572                     LinkTimeCodeGeneration = optLTCGInstrument;
1573                 else if (qstricmp(str, "pgoptimize") == 0)
1574                     LinkTimeCodeGeneration = optLTCGOptimize;
1575                 else if (qstricmp(str, "pgupdate") == 0)
1576                     LinkTimeCodeGeneration = optLTCGUpdate;
1577             }
1578         } else {
1579             AdditionalOptions.append(option);
1580         }
1581         break;
1582     case 0x379ED25:
1583     case 0x157cf65: // /MACHINE:{AM33|ARM|CEE|IA64|X86|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|PPC|SH3|SH4|SH5|THUMB|TRICORE}
1584         switch (elfHash(option+9)) {
1585         // Very limited documentation on all options but X86,
1586         case 0x0005bb6: // X86
1587             TargetMachine = machineX86;
1588             break;
1589         case 0x0005b94: // X64
1590             TargetMachine = machineX64;
1591             break;
1592         // so we put the others in AdditionalOptions...
1593         case 0x0046063: // AM33
1594         case 0x000466d: // ARM
1595         case 0x0004795: // CEE
1596         case 0x0004963: // EBC
1597         case 0x004d494: // IA64
1598         case 0x0050672: // M32R
1599         case 0x0051e53: // MIPS
1600         case 0x51e5646: // MIPS16
1601         case 0x1e57b05: // MIPSFPU
1602         case 0x57b09a6: // MIPSFPU16
1603         case 0x5852738: // MIPSR41XX
1604         case 0x0005543: // PPC
1605         case 0x00057b3: // SH3
1606         case 0x57b7980: // SH3DSP
1607         case 0x00057b4: // SH4
1608         case 0x00057b5: // SH5
1609         case 0x058da12: // THUMB
1610         case 0x96d8435: // TRICORE
1611         default:
1612             AdditionalOptions += option;
1613             break;
1614         }
1615         break;
1616     case 0x0034160: // /MAP[:filename]
1617         GenerateMapFile = _True;
1618         if (option[4] == ':')
1619             MapFileName = option+5;
1620         break;
1621     case 0x164e1ef: // /MAPINFO:{EXPORTS|LINES}
1622         if(*(option+9) == 'E')
1623             MapExports = _True;
1624         else if(*(option+9) == 'L')
1625             MapLines = _True;
1626         break;
1627     case 0x341a6b5: // /MERGE:from=to
1628         if (MergeSections.isEmpty()) {
1629             MergeSections = option+7;
1630         } else {
1631             // vcxproj files / the VS property editor do not support multiple MergeSections entries.
1632             // Add them as additional options.
1633             AdditionalOptions += option;
1634         }
1635         break;
1636     case 0x0341d8c: // /MIDL:@file
1637         MidlCommandFile = option+7;
1638         break;
1639     case 0x84e2679: // /NOASSEMBLY
1640         TurnOffAssemblyGeneration = _True;
1641         break;
1642     case 0x2b21942: // /NODEFAULTLIB[:library]
1643         if(*(option+13) == '\0')
1644             IgnoreAllDefaultLibraries = _True;
1645         else
1646             IgnoreDefaultLibraryNames += option+14;
1647         break;
1648     case 0x33a3a39: // /NOENTRY
1649         ResourceOnlyDLL = _True;
1650         break;
1651     case 0x434138f: // /NOLOGO
1652         SuppressStartupBanner = _True;
1653         break;
1654     case 0xc841054: // /NXCOMPAT[:NO]
1655         if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n')))
1656             DataExecutionPrevention = _False;
1657         else
1658             DataExecutionPrevention = _True;
1659         break;
1660     case 0x0034454: // /OPT:{REF | NOREF | ICF[=iterations] | NOICF | WIN98 | NOWIN98}
1661         {
1662             char third = *(option+7);
1663             switch (third) {
1664             case 'F': // REF
1665                 if(*(option+5) == 'R') {
1666                     OptimizeReferences = optReferences;
1667                 } else { // ICF[=iterations]
1668                     EnableCOMDATFolding = optFolding;
1669                     // [=iterations] case is not documented
1670                 }
1671                 break;
1672             case 'R': // NOREF
1673                 OptimizeReferences = optNoReferences;
1674                 break;
1675             case 'I': // NOICF
1676                 EnableCOMDATFolding = optNoFolding;
1677                 break;
1678             case 'N': // WIN98
1679                 OptimizeForWindows98 = optWin98Yes;
1680                 break;
1681             case 'W': // NOWIN98
1682                 OptimizeForWindows98 = optWin98No;
1683                 break;
1684             default:
1685                 found = false;
1686             }
1687         }
1688         break;
1689     case 0x34468a2: // /ORDER:@filename
1690         FunctionOrder = option+8;
1691         break;
1692     case 0x00344a4: // /OUT:filename
1693         OutputFile = option+5;
1694         break;
1695     case 0x0034482: // /PDB:filename
1696         ProgramDatabaseFile = option+5;
1697         break;
1698     case 0xa2ad314: // /PDBSTRIPPED:pdb_file_name
1699         StripPrivateSymbols = option+13;
1700         break;
1701     case 0x6a09535: // /RELEASE
1702         SetChecksum = _True;
1703         break;
1704     case 0x348857b: // /STACK:reserve[,commit]
1705         {
1706             QStringList both = QString(option+7).split(",");
1707             StackReserveSize = both[0].toLongLong();
1708             if(both.count() == 2)
1709                 StackCommitSize = both[1].toLongLong();
1710         }
1711         break;
1712     case 0x75AA4D8: // /SAFESEH:{NO}
1713         if (config->CompilerVersion >= NET2010)
1714             ImageHasSafeExceptionHandlers = (option[8] == ':') ? _False : _True;
1715         else
1716             AdditionalOptions += option;
1717         break;
1718     case 0x9B3C00D:
1719     case 0x78dc00d: // /SUBSYSTEM:{CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|WINDOWSCE}[,major[.minor]]
1720         {
1721             // Split up in subsystem, and version number
1722             QStringList both = QString(option+11).split(",");
1723             switch (elfHash(both[0].toLatin1().constData())) {
1724             case 0x8438445: // CONSOLE
1725                 SubSystem = subSystemConsole;
1726                 break;
1727             case 0xbe29493: // WINDOWS
1728                 SubSystem = subSystemWindows;
1729                 break;
1730             // The following are undocumented, so add them to AdditionalOptions
1731             case 0x240949e: // EFI_APPLICATION
1732             case 0xe617652: // EFI_BOOT_SERVICE_DRIVER
1733             case 0x9af477d: // EFI_ROM
1734             case 0xd34df42: // EFI_RUNTIME_DRIVER
1735             case 0x5268ea5: // NATIVE
1736             case 0x05547e8: // POSIX
1737             case 0x2949c95: // WINDOWSCE
1738             case 0x4B69795: // windowsce
1739                 AdditionalOptions += option;
1740                 break;
1741             default:
1742                 found = false;
1743             }
1744         }
1745         break;
1746     case 0x8b654de: // /SWAPRUN:{NET | CD}
1747         if(*(option+9) == 'N')
1748             SwapRunFromNet = _True;
1749         else if(*(option+9) == 'C')
1750             SwapRunFromCD = _True;
1751         else
1752             found = false;
1753         break;
1754     case 0x34906d4: // /TLBID:id
1755         TypeLibraryResourceID = QString(option+7).toLongLong();
1756         break;
1757     case 0x4907494: // /TLBOUT:[path\]filename
1758         TypeLibraryFile = option+8;
1759         break;
1760     case 0x976b525: // /TSAWARE[:NO]
1761         if(*(option+8) == ':')
1762             TerminalServerAware = termSvrAwareNo;
1763         else
1764             TerminalServerAware = termSvrAwareYes;
1765         break;
1766     case 0xaa67735: // /VERBOSE[:lib]
1767         if(*(option+9) == ':') {
1768             ShowProgress = linkProgressLibs;
1769             AdditionalOptions += option;
1770         } else {
1771             ShowProgress = linkProgressAll;
1772         }
1773         break;
1774     case 0xaa77f7e: // /VERSION:major[.minor]
1775         Version = option+9;
1776         break;
1777     case 0x0034c50: // /WS[:NO]
1778         if (config->CompilerVersion >= NET2010) {
1779             if(*(option+3) == ':')
1780                 TreatWarningsAsErrors = _False;
1781             else
1782                 TreatWarningsAsErrors = _True;
1783         } else {
1784             AdditionalOptions += option;
1785         }
1786         break;
1787     default:
1788         AdditionalOptions += option;
1789         break;
1790     }
1791     if(!found) {
1792         if (!config->suppressUnknownOptionWarnings)
1793             unknownOptionWarning("Linker", option);
1794         AdditionalOptions += option;
1795     }
1796     return found;
1797 }
1798 
1799 // VCManifestTool ---------------------------------------------------
VCManifestTool()1800 VCManifestTool::VCManifestTool()
1801     : EmbedManifest(unset)
1802 {
1803 }
1804 
parseOption(const char * option)1805 bool VCManifestTool::parseOption(const char *option)
1806 {
1807     Q_UNUSED(option);
1808     // ### implement if we introduce QMAKE_MT_FLAGS
1809     return false;
1810 }
1811 
1812 // VCMIDLTool -------------------------------------------------------
VCMIDLTool()1813 VCMIDLTool::VCMIDLTool()
1814     :        DefaultCharType(midlCharUnsigned),
1815         EnableErrorChecks(midlDisableAll),
1816         ErrorCheckAllocations(unset),
1817         ErrorCheckBounds(unset),
1818         ErrorCheckEnumRange(unset),
1819         ErrorCheckRefPointers(unset),
1820         ErrorCheckStubData(unset),
1821         GenerateStublessProxies(unset),
1822         GenerateTypeLibrary(unset),
1823         IgnoreStandardIncludePath(unset),
1824         MkTypLibCompatible(unset),
1825         StructMemberAlignment(midlAlignNotSet),
1826         SuppressStartupBanner(unset),
1827         TargetEnvironment(midlTargetNotSet),
1828         ValidateParameters(unset),
1829         WarnAsError(unset),
1830         WarningLevel(midlWarningLevel_0),
1831         ApplicationConfigurationMode(unset),
1832         ValidateAllParameters(unset),
1833         SuppressCompilerWarnings(unset),
1834         LocaleID(-1)
1835 {
1836 }
1837 
parseOption(const char * option)1838 bool VCMIDLTool::parseOption(const char* option)
1839 {
1840 #ifdef USE_DISPLAY_HASH
1841     displayHash("/D name[=def]"); displayHash("/I directory-list"); displayHash("/Oi");
1842     displayHash("/Oic"); displayHash("/Oicf"); displayHash("/Oif"); displayHash("/Os");
1843     displayHash("/U name"); displayHash("/WX"); displayHash("/W{0|1|2|3|4}");
1844     displayHash("/Zp {N}"); displayHash("/Zs"); displayHash("/acf filename");
1845     displayHash("/align {N}"); displayHash("/app_config"); displayHash("/c_ext");
1846     displayHash("/char ascii7"); displayHash("/char signed"); displayHash("/char unsigned");
1847     displayHash("/client none"); displayHash("/client stub"); displayHash("/confirm");
1848     displayHash("/cpp_cmd cmd_line"); displayHash("/cpp_opt options");
1849     displayHash("/cstub filename"); displayHash("/dlldata filename"); displayHash("/env win32");
1850     displayHash("/env win64"); displayHash("/error all"); displayHash("/error allocation");
1851     displayHash("/error bounds_check"); displayHash("/error enum"); displayHash("/error none");
1852     displayHash("/error ref"); displayHash("/error stub_data"); displayHash("/h filename");
1853     displayHash("/header filename"); displayHash("/iid filename"); displayHash("/lcid");
1854     displayHash("/mktyplib203"); displayHash("/ms_ext"); displayHash("/ms_union");
1855     displayHash("/msc_ver <nnnn>"); displayHash("/newtlb"); displayHash("/no_cpp");
1856     displayHash("/no_def_idir"); displayHash("/no_default_epv"); displayHash("/no_format_opt");
1857     displayHash("/no_warn"); displayHash("/nocpp"); displayHash("/nologo"); displayHash("/notlb");
1858     displayHash("/o filename"); displayHash("/oldnames"); displayHash("/oldtlb");
1859     displayHash("/osf"); displayHash("/out directory"); displayHash("/pack {N}");
1860     displayHash("/prefix all"); displayHash("/prefix client"); displayHash("/prefix server");
1861     displayHash("/prefix switch"); displayHash("/protocol all"); displayHash("/protocol dce");
1862     displayHash("/protocol ndr64"); displayHash("/proxy filename"); displayHash("/robust");
1863     displayHash("/rpcss"); displayHash("/savePP"); displayHash("/server none");
1864     displayHash("/server stub"); displayHash("/sstub filename"); displayHash("/syntax_check");
1865     displayHash("/target {system}"); displayHash("/tlb filename"); displayHash("/use_epv");
1866     displayHash("/win32"); displayHash("/win64");
1867 #endif
1868     bool found = true;
1869     int offset = 0;
1870 
1871     const uint optionHash = elfHash(option);
1872 
1873     if (config->CompilerVersion < NET2010) {
1874         switch (optionHash) {
1875         case 0x5b1cb97: // /app_config
1876         case 0x5a2fc64: // /client {none|stub}
1877         case 0x35aabb2: // /cstub filename
1878         case 0x64ceb12: // /newtlb
1879         case 0x556dbee: // /no_warn
1880         case 0x662bb12: // /oldtlb
1881         case 0x69c9cf2: // /server {none|stub}
1882         case 0x36aabb2: // /sstub filename
1883             AdditionalOptions += option;
1884             return true;
1885         }
1886     }
1887 
1888     switch(optionHash) {
1889     case 0x0000334: // /D name[=def]
1890         PreprocessorDefinitions += option+3;
1891         break;
1892     case 0x0000339: // /I directory-list
1893         AdditionalIncludeDirectories += option+3;
1894         break;
1895     case 0x0345f96: // /Oicf
1896     case 0x00345f6: // /Oif
1897         GenerateStublessProxies = _True;
1898         break;
1899     case 0x0000345: // /U name
1900         UndefinePreprocessorDefinitions += option+3;
1901         break;
1902     case 0x00034c8: // /WX
1903         WarnAsError = _True;
1904         break;
1905     case 0x3582fde: // /align {N}
1906         offset = 3;  // Fallthrough
1907     case 0x0003510: // /Zp {N}
1908         switch (*(option+offset+4)) {
1909         case '1':
1910             StructMemberAlignment = (*(option+offset+5) == '\0') ? midlAlignSingleByte : midlAlignSixteenBytes;
1911             break;
1912         case '2':
1913             StructMemberAlignment = midlAlignTwoBytes;
1914             break;
1915         case '4':
1916             StructMemberAlignment = midlAlignFourBytes;
1917             break;
1918         case '8':
1919             StructMemberAlignment = midlAlignEightBytes;
1920             break;
1921         default:
1922             found = false;
1923         }
1924         break;
1925     case 0x5b1cb97: // /app_config
1926         ApplicationConfigurationMode = _True;
1927         break;
1928     case 0x0359e82: // /char {ascii7|signed|unsigned}
1929         switch(*(option+6)) {
1930         case 'a':
1931             DefaultCharType = midlCharAscii7;
1932             break;
1933         case 's':
1934             DefaultCharType = midlCharSigned;
1935             break;
1936         case 'u':
1937             DefaultCharType = midlCharUnsigned;
1938             break;
1939         default:
1940             found = false;
1941         }
1942         break;
1943     case 0x5a2fc64: // /client {none|stub}
1944         if(*(option+8) == 's')
1945             GenerateClientFiles = "Stub";
1946         else
1947             GenerateClientFiles = "None";
1948         break;
1949     case 0xa766524: // /cpp_opt options
1950         CPreprocessOptions += option+9;
1951         break;
1952     case 0x35aabb2: // /cstub filename
1953         ClientStubFile = option+7;
1954         break;
1955     case 0xb32abf1: // /dlldata filename
1956         DLLDataFileName = option + 9;
1957         break;
1958     case 0x0035c56: // /env {win32|win64}
1959         TargetEnvironment = (*(option+8) == '6') ? midlTargetWin64 : midlTargetWin32;
1960         break;
1961     case 0x35c9962: // /error {all|allocation|bounds_check|enum|none|ref|stub_data}
1962         EnableErrorChecks = midlEnableCustom;
1963         switch (*(option+7)) {
1964         case 'a':
1965             if(*(option+10) == '\0')
1966                 EnableErrorChecks = midlEnableAll;
1967             else
1968                 ErrorCheckAllocations = _True;
1969             break;
1970         case 'b':
1971             ErrorCheckBounds = _True;
1972             break;
1973         case 'e':
1974             ErrorCheckEnumRange = _True;
1975             break;
1976         case 'n':
1977             EnableErrorChecks = midlDisableAll;
1978             break;
1979         case 'r':
1980             ErrorCheckRefPointers = _True;
1981             break;
1982         case 's':
1983             ErrorCheckStubData = _True;
1984             break;
1985         default:
1986             found = false;
1987         }
1988         break;
1989     case 0x5eb7af2: // /header filename
1990         offset = 5;
1991         Q_FALLTHROUGH();
1992     case 0x0000358: // /h filename
1993         HeaderFileName = option + offset + 3;
1994         break;
1995     case 0x0035ff4: // /iid filename
1996         InterfaceIdentifierFileName = option+5;
1997         break;
1998     case 0x64b7933: // /mktyplib203
1999         MkTypLibCompatible = _True;
2000         break;
2001     case 0x64ceb12: // /newtlb
2002         TypeLibFormat = "NewFormat";
2003         break;
2004     case 0x8e0b0a2: // /no_def_idir
2005         IgnoreStandardIncludePath = _True;
2006         break;
2007     case 0x65635ef: // /nologo
2008         SuppressStartupBanner = _True;
2009         break;
2010     case 0x695e9f4: // /no_robust
2011         ValidateAllParameters = _False;
2012         break;
2013     case 0x3656b22: // /notlb
2014         GenerateTypeLibrary = _True;
2015         break;
2016     case 0x556dbee: // /no_warn
2017         SuppressCompilerWarnings = _True;
2018         break;
2019     case 0x000035f: // /o filename
2020         RedirectOutputAndErrors = option+3;
2021         break;
2022     case 0x662bb12: // /oldtlb
2023         TypeLibFormat = "OldFormat";
2024         break;
2025     case 0x00366c4: // /out directory
2026         OutputDirectory = option+5;
2027         break;
2028     case 0x36796f9: // /proxy filename
2029         ProxyFileName = option+7;
2030         break;
2031     case 0x6959c94: // /robust
2032         ValidateParameters = _True;
2033         break;
2034     case 0x6a88df4: // /target {system}
2035         if(*(option+11) == '6')
2036             TargetEnvironment = midlTargetWin64;
2037         else
2038             TargetEnvironment = midlTargetWin32;
2039         break;
2040     case 0x69c9cf2: // /server {none|stub}
2041         if(*(option+8) == 's')
2042             GenerateServerFiles = "Stub";
2043         else
2044             GenerateServerFiles = "None";
2045         break;
2046     case 0x36aabb2: // /sstub filename
2047         ServerStubFile = option+7;
2048         break;
2049     case 0x0036b22: // /tlb filename
2050         TypeLibraryName = option+5;
2051         break;
2052     case 0x36e0162: // /win32
2053         TargetEnvironment = midlTargetWin32;
2054         break;
2055     case 0x36e0194: // /win64
2056         TargetEnvironment = midlTargetWin64;
2057         break;
2058     case 0x0003459: // /Oi
2059     case 0x00345f3: // /Oic
2060     case 0x0003463: // /Os
2061     case 0x0003513: // /Zs
2062     case 0x0035796: // /acf filename
2063     case 0x3595cf4: // /c_ext
2064     case 0xa64d3dd: // /confirm
2065     case 0xa765b64: // /cpp_cmd cmd_line
2066     case 0x03629f4: // /lcid
2067     case 0x6495cc4: // /ms_ext
2068     case 0x96c7a1e: // /ms_union
2069     case 0x4996fa2: // /msc_ver <nnnn>
2070     case 0x6555a40: // /no_cpp
2071     case 0xf64d6a6: // /no_default_epv
2072     case 0x6dd9384: // /no_format_opt
2073     case 0x3655a70: // /nocpp
2074     case 0x2b455a3: // /oldnames
2075     case 0x0036696: // /osf
2076     case 0x036679b: // /pack {N}
2077     case 0x678bd38: // /prefix {all|client|server|switch}
2078     case 0x96b702c: // /protocol {all|dce|ndr64}
2079     case 0x3696aa3: // /rpcss
2080     case 0x698ca60: // /savePP
2081     case 0xce9b12b: // /syntax_check
2082     case 0xc9b5f16: // /use_epv
2083         AdditionalOptions += option;
2084         break;
2085     default:
2086         // /W{0|1|2|3|4} case
2087         if(*(option+1) == 'W') {
2088             switch (*(option+2)) {
2089             case '0':
2090                 WarningLevel = midlWarningLevel_0;
2091                 break;
2092             case '1':
2093                 WarningLevel = midlWarningLevel_1;
2094                 break;
2095             case '2':
2096                 WarningLevel = midlWarningLevel_2;
2097                 break;
2098             case '3':
2099                 WarningLevel = midlWarningLevel_3;
2100                 break;
2101             case '4':
2102                 WarningLevel = midlWarningLevel_4;
2103                 break;
2104             default:
2105                 found = false;
2106             }
2107         }
2108         break;
2109     }
2110     if(!found)
2111         warn_msg(WarnLogic, "Could not parse MIDL option: %s", option);
2112     return true;
2113 }
2114 
2115 // VCLibrarianTool --------------------------------------------------
VCLibrarianTool()2116 VCLibrarianTool::VCLibrarianTool()
2117     :        IgnoreAllDefaultLibraries(unset),
2118         SuppressStartupBanner(_True)
2119 {
2120 }
2121 
2122 // VCCustomBuildTool ------------------------------------------------
VCCustomBuildTool()2123 VCCustomBuildTool::VCCustomBuildTool()
2124 {
2125     ToolName = "VCCustomBuildTool";
2126 }
2127 
2128 // VCResourceCompilerTool -------------------------------------------
VCResourceCompilerTool()2129 VCResourceCompilerTool::VCResourceCompilerTool()
2130     :   Culture(rcUseDefault),
2131         IgnoreStandardIncludePath(unset),
2132         ShowProgress(linkProgressNotSet),
2133         SuppressStartupBanner(unset)
2134 {
2135 }
2136 
2137 // VCDeploymentTool --------------------------------------------
VCDeploymentTool()2138 VCDeploymentTool::VCDeploymentTool()
2139     :   RegisterOutput(registerNo)
2140 {
2141     DeploymentTag = "DeploymentTool";
2142     RemoteDirectory = "";
2143 }
2144 
VCEventTool(const QString & eventName)2145 VCEventTool::VCEventTool(const QString &eventName)
2146     : ExcludedFromBuild(unset)
2147 {
2148     EventName = eventName;
2149     ToolName = "VC";
2150     ToolName += eventName;
2151     ToolName += "Tool";
2152 }
2153 
2154 // VCPostBuildEventTool ---------------------------------------------
VCPostBuildEventTool()2155 VCPostBuildEventTool::VCPostBuildEventTool()
2156     : VCEventTool("PostBuildEvent")
2157 {
2158 }
2159 
2160 // VCPreBuildEventTool ----------------------------------------------
VCPreBuildEventTool()2161 VCPreBuildEventTool::VCPreBuildEventTool()
2162     : VCEventTool("PreBuildEvent")
2163 {
2164 }
2165 
2166 // VCPreLinkEventTool -----------------------------------------------
VCPreLinkEventTool()2167 VCPreLinkEventTool::VCPreLinkEventTool()
2168     : VCEventTool("PreLinkEvent")
2169 {
2170 }
2171 
2172 // VCConfiguration --------------------------------------------------
2173 
VCConfiguration()2174 VCConfiguration::VCConfiguration()
2175     :   WinRT(false),
2176         ATLMinimizesCRunTimeLibraryUsage(unset),
2177         BuildBrowserInformation(unset),
2178         CharacterSet(charSetNotSet),
2179         ConfigurationType(typeApplication),
2180         RegisterOutput(unset),
2181         UseOfATL(useATLNotSet),
2182         UseOfMfc(useMfcStdWin),
2183         WholeProgramOptimization(unset)
2184 {
2185     compiler.config = this;
2186     linker.config = this;
2187     idl.config = this;
2188 }
2189 
2190 // VCFilter ---------------------------------------------------------
VCFilter()2191 VCFilter::VCFilter()
2192     :   ParseFiles(unset),
2193         Config(nullptr)
2194 {
2195     useCustomBuildTool = false;
2196     useCompilerTool = false;
2197 }
2198 
addFile(const QString & filename)2199 void VCFilter::addFile(const QString& filename)
2200 {
2201     Files += VCFilterFile(filename);
2202 }
2203 
addFile(const VCFilterFile & fileInfo)2204 void VCFilter::addFile(const VCFilterFile& fileInfo)
2205 {
2206     Files += VCFilterFile(fileInfo);
2207 }
2208 
addFiles(const QStringList & fileList)2209 void VCFilter::addFiles(const QStringList& fileList)
2210 {
2211     for (int i = 0; i < fileList.count(); ++i)
2212         addFile(fileList.at(i));
2213 }
2214 
addFiles(const ProStringList & fileList)2215 void VCFilter::addFiles(const ProStringList& fileList)
2216 {
2217     for (int i = 0; i < fileList.count(); ++i)
2218         addFile(fileList.at(i).toQString());
2219 }
2220 
modifyPCHstage(QString str)2221 void VCFilter::modifyPCHstage(QString str)
2222 {
2223     const bool isHFile = (str == Project->precompH);
2224     const bool pchThroughSourceFile = !Project->precompSource.isEmpty();
2225     if (isHFile && pchThroughSourceFile && Project->autogenPrecompSource) {
2226         useCustomBuildTool = true;
2227         QString toFile(Project->precompSource);
2228         CustomBuildTool.Description = "Generating precompiled header source file '" + toFile + "' ...";
2229         CustomBuildTool.Outputs += toFile;
2230 
2231         QStringList lines;
2232         CustomBuildTool.CommandLine +=
2233                 "echo /*-------------------------------------------------------------------- >" + toFile;
2234         lines << "* Precompiled header source file used by Visual Studio.NET to generate";
2235         lines << "* the .pch file.";
2236         lines << "*";
2237         lines << "* Due to issues with the dependencies checker within the IDE, it";
2238         lines << "* sometimes fails to recompile the PCH file, if we force the IDE to";
2239         lines << "* create the PCH file directly from the header file.";
2240         lines << "*";
2241         lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was";
2242         lines << "* specified, and is used as the common stdafx.cpp. The file is only";
2243         lines << QLatin1String("* generated when creating ")
2244                 + (Config->CompilerVersion < NET2010 ? ".vcproj" : ".vcxproj")
2245                 + " project files, and is not used for";
2246         lines << "* command line compilations by nmake.";
2247         lines << "*";
2248         lines << "* WARNING: All changes made in this file will be lost.";
2249         lines << "--------------------------------------------------------------------*/";
2250         lines << "#include \"" + Project->precompHFilename + "\"";
2251         for (const QString &line : qAsConst(lines))
2252             CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile;
2253         return;
2254     }
2255 
2256     useCompilerTool = true;
2257     const bool isPrecompSource = pchThroughSourceFile && (str == Project->precompSource);
2258     if (isPrecompSource) {
2259         CompilerTool.UsePrecompiledHeader = pchCreateUsingSpecific;
2260         if (Project->autogenPrecompSource)
2261             CompilerTool.PrecompiledHeaderThrough = Project->precompHFilename;
2262         CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)");
2263         return;
2264     }
2265 
2266     bool isCFile = false;
2267     for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) {
2268         if (str.endsWith(*it)) {
2269             isCFile = true;
2270             break;
2271         }
2272     }
2273 
2274     bool pchCompatible = (isCFile == Project->pchIsCFile);
2275     if (!pchCompatible) {
2276         CompilerTool.UsePrecompiledHeader = pchNone;
2277         CompilerTool.PrecompiledHeaderThrough = QLatin1String("$(NOINHERIT)");
2278         CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)");
2279     }
2280 }
2281 
findFile(const QString & filePath,bool * found) const2282 VCFilterFile VCFilter::findFile(const QString &filePath, bool *found) const
2283 {
2284     for (int i = 0; i < Files.count(); ++i) {
2285         const VCFilterFile &f = Files.at(i);
2286         if (f.file == filePath) {
2287             *found = true;
2288             return f;
2289         }
2290     }
2291     *found = false;
2292     return VCFilterFile();
2293 }
2294 
addExtraCompiler(const VCFilterFile & info)2295 bool VCFilter::addExtraCompiler(const VCFilterFile &info)
2296 {
2297     const QStringList &extraCompilers = Project->extraCompilerSources.value(info.file);
2298     if (extraCompilers.isEmpty())
2299         return false;
2300 
2301     QString inFile = info.file;
2302 
2303     // is the extracompiler rule on a file with a built in compiler?
2304     const QString objectMappedFile = Project->extraCompilerOutputs.value(inFile);
2305     bool hasBuiltIn = false;
2306     if (!objectMappedFile.isEmpty()) {
2307         hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile);
2308 
2309         // Remove the fake file suffix we've added initially to generate correct command lines.
2310         inFile.chop(Project->customBuildToolFilterFileSuffix.length());
2311 
2312 //        qDebug("*** Extra compiler file has object mapped file '%s' => '%s'", qPrintable(inFile), qPrintable(objectMappedFile.join(' ')));
2313     }
2314 
2315     CustomBuildTool.AdditionalDependencies.clear();
2316     CustomBuildTool.CommandLine.clear();
2317     CustomBuildTool.Description.clear();
2318     CustomBuildTool.Outputs.clear();
2319     CustomBuildTool.ToolPath.clear();
2320     CustomBuildTool.ToolName = QLatin1String(_VCCustomBuildTool);
2321 
2322     for (int x = 0; x < extraCompilers.count(); ++x) {
2323         const QString &extraCompilerName = extraCompilers.at(x);
2324 
2325         if (!Project->verifyExtraCompiler(extraCompilerName, inFile) && !hasBuiltIn)
2326             continue;
2327 
2328         // All information about the extra compiler
2329         QString tmp_out = Project->project->first(ProKey(extraCompilerName + ".output")).toQString();
2330         QString tmp_cmd = Project->project->values(ProKey(extraCompilerName + ".commands")).join(' ');
2331         QString tmp_cmd_name = Project->project->values(ProKey(extraCompilerName + ".name")).join(' ');
2332         QStringList tmp_dep = Project->project->values(ProKey(extraCompilerName + ".depends")).toQStringList();
2333         QString tmp_dep_cmd = Project->project->values(ProKey(extraCompilerName + ".depend_command")).join(' ');
2334         const ProStringList &configs = Project->project->values(ProKey(extraCompilerName + ".CONFIG"));
2335         bool combined = configs.indexOf("combine") != -1;
2336 
2337         QString cmd, cmd_name, out;
2338         QStringList deps, inputs;
2339         // Variabel replacement of output name
2340         out = Option::fixPathToTargetOS(Project->replaceExtraCompilerVariables(
2341                 tmp_out, inFile, QString(), MakefileGenerator::NoShell), false);
2342 
2343         // If file has built-in compiler, we've swapped the input and output of
2344         // the command, as we in Visual Studio cannot have a Custom Buildstep on
2345         // a file which uses a built-in compiler. We would in this case only get
2346         // the result from the extra compiler. If 'hasBuiltIn' is true, we know
2347         // that we're actually on the _output_file_ of the result, and we
2348         // therefore swap inFile and out below, since the extra-compiler still
2349         // must see it as the original way. If the result also has a built-in
2350         // compiler, too bad..
2351         if (hasBuiltIn) {
2352             out = inFile;
2353             inFile = objectMappedFile;
2354         }
2355 
2356         // Dependency for the output
2357         if (!tmp_dep.isEmpty())
2358             deps = tmp_dep;
2359         if (!tmp_dep_cmd.isEmpty()) {
2360             Project->callExtraCompilerDependCommand(extraCompilerName, tmp_dep_cmd,
2361                                                     inFile, out,
2362                                                     true, // dep_lines
2363                                                     &deps,
2364                                                     configs.contains("dep_existing_only"),
2365                                                     true  /* checkCommandAvailability */);
2366         }
2367         for (int i = 0; i < deps.count(); ++i)
2368             deps[i] = Option::fixPathToTargetOS(
2369                         Project->replaceExtraCompilerVariables(
2370                                 deps.at(i), inFile, out, MakefileGenerator::NoShell),
2371                         false);
2372         // Command for file
2373         if (combined) {
2374             // Add dependencies for each file
2375             const ProStringList &tmp_in = Project->project->values(ProKey(extraCompilerName + ".input"));
2376             for (int a = 0; a < tmp_in.count(); ++a) {
2377                 const ProStringList &files = Project->project->values(tmp_in.at(a).toKey());
2378                 for (int b = 0; b < files.count(); ++b) {
2379                     QString file = files.at(b).toQString();
2380                     deps += Project->findDependencies(file);
2381                     inputs += Option::fixPathToTargetOS(file, false);
2382                 }
2383             }
2384             deps = inputs + deps; // input files themselves too..
2385 
2386             // Replace variables for command w/all input files
2387             cmd = Project->replaceExtraCompilerVariables(tmp_cmd,
2388                                                          inputs,
2389                                                          QStringList(out),
2390                                                          MakefileGenerator::TargetShell);
2391         } else {
2392             deps.prepend(inFile); // input file itself too..
2393             cmd = Project->replaceExtraCompilerVariables(tmp_cmd,
2394                                                          inFile,
2395                                                          out,
2396                                                          MakefileGenerator::TargetShell);
2397         }
2398         // Name for command
2399         if (!tmp_cmd_name.isEmpty()) {
2400             cmd_name = Project->replaceExtraCompilerVariables(
2401                     tmp_cmd_name, inFile, out, MakefileGenerator::NoShell);
2402         } else {
2403             int space = cmd.indexOf(' ');
2404             if (space != -1)
2405                 cmd_name = cmd.left(space);
2406             else
2407                 cmd_name = cmd;
2408         }
2409 
2410         // Fixify paths
2411         for (int i = 0; i < deps.count(); ++i)
2412             deps[i] = Option::fixPathToTargetOS(deps[i], false);
2413 
2414 
2415         // Output in info.additionalFile -----------
2416         if (!CustomBuildTool.Description.isEmpty())
2417             CustomBuildTool.Description += ", ";
2418         CustomBuildTool.Description += cmd_name;
2419         CustomBuildTool.CommandLine += VCToolBase::fixCommandLine(cmd.trimmed());
2420         int space = cmd.indexOf(' ');
2421         QFileInfo finf(cmd.left(space));
2422         if (CustomBuildTool.ToolPath.isEmpty())
2423             CustomBuildTool.ToolPath += Option::fixPathToTargetOS(finf.path());
2424         CustomBuildTool.Outputs += out;
2425 
2426         deps += CustomBuildTool.AdditionalDependencies;
2427         // Make sure that all deps are only once
2428         QStringList uniqDeps;
2429         for (int c = 0; c < deps.count(); ++c) {
2430             QString aDep = deps.at(c);
2431             if (!aDep.isEmpty())
2432                 uniqDeps << aDep;
2433         }
2434         uniqDeps.removeDuplicates();
2435         CustomBuildTool.AdditionalDependencies = uniqDeps;
2436     }
2437 
2438     // Ensure that none of the output files are also dependencies. Or else, the custom buildstep
2439     // will be rebuild every time, even if nothing has changed.
2440     for (const QString &output : qAsConst(CustomBuildTool.Outputs))
2441         CustomBuildTool.AdditionalDependencies.removeAll(output);
2442 
2443     useCustomBuildTool = !CustomBuildTool.CommandLine.isEmpty();
2444     return useCustomBuildTool;
2445 }
2446 
2447 // VCProjectSingleConfig --------------------------------------------
filterByName(const QString & name) const2448 const VCFilter &VCProjectSingleConfig::filterByName(const QString &name) const
2449 {
2450     if (name == "Root Files")
2451         return RootFiles;
2452     if (name == "Source Files")
2453         return SourceFiles;
2454     if (name == "Header Files")
2455         return HeaderFiles;
2456     if (name == "Generated Files")
2457         return GeneratedFiles;
2458     if (name == "LexYacc Files")
2459         return LexYaccFiles;
2460     if (name == "Translation Files")
2461         return TranslationFiles;
2462     if (name == "Form Files")
2463         return FormFiles;
2464     if (name == "Resource Files")
2465         return ResourceFiles;
2466     if (name == "Deployment Files")
2467         return DeploymentFiles;
2468     if (name == "Distribution Files")
2469         return DistributionFiles;
2470     return filterForExtraCompiler(name);
2471 }
2472 
filterForExtraCompiler(const QString & compilerName) const2473 const VCFilter &VCProjectSingleConfig::filterForExtraCompiler(const QString &compilerName) const
2474 {
2475     for (int i = 0; i < ExtraCompilersFiles.count(); ++i)
2476         if (ExtraCompilersFiles.at(i).Name == compilerName)
2477             return ExtraCompilersFiles.at(i);
2478 
2479     static VCFilter nullFilter;
2480     return nullFilter;
2481 }
2482 
2483 // Tree file generation ---------------------------------------------
generateXML(XmlOutput & xml,const QString & tagName,VCProject & tool,const QString & filter)2484 void TreeNode::generateXML(XmlOutput &xml, const QString &tagName, VCProject &tool, const QString &filter) {
2485     if (children.size()) {
2486         // Filter
2487         ChildrenMap::ConstIterator it, end = children.constEnd();
2488         if (!tagName.isEmpty()) {
2489             xml << tag("Filter")
2490                 << attr("Name", tagName)
2491                 << attr("Filter", "");
2492         }
2493         // First round, do nested filters
2494         for (it = children.constBegin(); it != end; ++it)
2495             if ((*it)->children.size())
2496                 (*it)->generateXML(xml, it.key(), tool, filter);
2497         // Second round, do leafs
2498         for (it = children.constBegin(); it != end; ++it)
2499             if (!(*it)->children.size())
2500                 (*it)->generateXML(xml, it.key(), tool, filter);
2501 
2502         if (!tagName.isEmpty())
2503             xml << closetag("Filter");
2504     } else {
2505         // Leaf
2506         VCProjectWriter::outputFileConfigs(tool, xml, info, filter);
2507     }
2508 }
2509 
2510 // Flat file generation ---------------------------------------------
generateXML(XmlOutput & xml,const QString &,VCProject & tool,const QString & filter)2511 void FlatNode::generateXML(XmlOutput &xml, const QString &/*tagName*/, VCProject &tool, const QString &filter) {
2512     if (children.size()) {
2513         ChildrenMapFlat::ConstIterator it = children.constBegin();
2514         ChildrenMapFlat::ConstIterator end = children.constEnd();
2515         for (; it != end; ++it) {
2516             VCProjectWriter::outputFileConfigs(tool, xml, (*it), filter);
2517         }
2518     }
2519 }
2520 
write(XmlOutput & xml,VCProjectSingleConfig & tool)2521 void VCProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool)
2522 {
2523     xml << decl("1.0", "Windows-1252")
2524         << tag(_VisualStudioProject)
2525         << attrS(_ProjectType, "Visual C++")
2526         << attrS(_Version, tool.Version)
2527         << attrS(_Name, tool.Name)
2528         << attrS(_ProjectGUID, tool.ProjectGUID)
2529         << attrS(_Keyword, tool.Keyword)
2530         << attrS(_SccProjectName, tool.SccProjectName)
2531         << attrS(_SccLocalPath, tool.SccLocalPath)
2532         << tag(_Platforms)
2533         << tag(_Platform)
2534         << attrS(_Name, tool.PlatformName)
2535         << closetag(_Platforms)
2536         << tag(_Configurations);
2537     write(xml, tool.Configuration);
2538     xml << closetag(_Configurations)
2539         << tag(q_Files);
2540     // Add this configuration into a multi-config project, since that's where we have the flat/tree
2541     // XML output functionality
2542     VCProject tempProj;
2543     tempProj.SingleProjects += tool;
2544     outputFilter(tempProj, xml, "Source Files");
2545     outputFilter(tempProj, xml, "Header Files");
2546     outputFilter(tempProj, xml, "Generated Files");
2547     outputFilter(tempProj, xml, "LexYacc Files");
2548     outputFilter(tempProj, xml, "Translation Files");
2549     outputFilter(tempProj, xml, "Form Files");
2550     outputFilter(tempProj, xml, "Resource Files");
2551     outputFilter(tempProj, xml, "Deployment Files");
2552     outputFilter(tempProj, xml, "Distribution Files");
2553 
2554     QSet<QString> extraCompilersInProject;
2555     for (int i = 0; i < tool.ExtraCompilersFiles.count(); ++i) {
2556         const QString &compilerName = tool.ExtraCompilersFiles.at(i).Name;
2557         if (!extraCompilersInProject.contains(compilerName)) {
2558             extraCompilersInProject += compilerName;
2559             tempProj.ExtraCompilers += compilerName;
2560         }
2561     }
2562 
2563     for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) {
2564         outputFilter(tempProj, xml, tempProj.ExtraCompilers.at(x));
2565     }
2566     outputFilter(tempProj, xml, "Root Files");
2567     xml     << closetag(q_Files)
2568             << tag(_Globals)
2569                 << data(); // No "/>" end tag
2570 }
2571 
write(XmlOutput & xml,VCProject & tool)2572 void VCProjectWriter::write(XmlOutput &xml, VCProject &tool)
2573 {
2574     if (tool.SingleProjects.count() == 0) {
2575         warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output");
2576         return;
2577     }
2578 
2579     xml << decl("1.0", "Windows-1252")
2580         << tag(_VisualStudioProject)
2581             << attrS(_ProjectType, "Visual C++")
2582             << attrS(_Version, tool.Version)
2583             << attrS(_Name, tool.Name)
2584             << attrS(_ProjectGUID, tool.ProjectGUID)
2585             << attrS(_Keyword, tool.Keyword)
2586             << attrS(_SccProjectName, tool.SccProjectName)
2587             << attrS(_SccLocalPath, tool.SccLocalPath)
2588             << tag(_Platforms)
2589                 << tag(_Platform)
2590                     << attrS(_Name, tool.PlatformName)
2591             << closetag(_Platforms)
2592             << tag(_Configurations);
2593     // Output each configuration
2594     for (int i = 0; i < tool.SingleProjects.count(); ++i)
2595         write(xml, tool.SingleProjects.at(i).Configuration);
2596     xml     << closetag(_Configurations)
2597             << tag(q_Files);
2598     outputFilter(tool, xml, "Source Files");
2599     outputFilter(tool, xml, "Header Files");
2600     outputFilter(tool, xml, "Generated Files");
2601     outputFilter(tool, xml, "LexYacc Files");
2602     outputFilter(tool, xml, "Translation Files");
2603     outputFilter(tool, xml, "Form Files");
2604     outputFilter(tool, xml, "Resource Files");
2605     outputFilter(tool, xml, "Deployment Files");
2606     outputFilter(tool, xml, "Distribution Files");
2607     for (int x = 0; x < tool.ExtraCompilers.count(); ++x) {
2608         outputFilter(tool, xml, tool.ExtraCompilers.at(x));
2609     }
2610     outputFilter(tool, xml, "Root Files");
2611     xml     << closetag(q_Files)
2612             << tag(_Globals)
2613             << data(); // No "/>" end tag
2614 }
2615 
write(XmlOutput & xml,const VCCLCompilerTool & tool)2616 void VCProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool)
2617 {
2618     xml << tag(_Tool)
2619         << attrS(_Name, _VCCLCompilerTool)
2620         << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories)
2621         << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
2622         << attrX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories)
2623         << attrS(_AssemblerListingLocation, tool.AssemblerListingLocation)
2624         << attrE(_AssemblerOutput, tool.AssemblerOutput, /*ifNot*/ asmListingNone)
2625         << attrE(_BasicRuntimeChecks, tool.BasicRuntimeChecks, /*ifNot*/ runtimeBasicCheckNone)
2626         << attrE(_BrowseInformation, tool.BrowseInformation, /*ifNot*/ brInfoNone)
2627         << attrS(_BrowseInformationFile, tool.BrowseInformationFile)
2628         << attrT(_BufferSecurityCheck, tool.BufferSecurityCheck)
2629         << attrE(_CallingConvention, tool.CallingConvention, /*ifNot*/ callConventionDefault)
2630         << attrE(_CompileAs, tool.CompileAs, compileAsDefault)
2631         << attrE(_CompileAsManaged, tool.CompileAsManaged, /*ifNot*/ managedDefault)
2632         << attrT(_CompileOnly, tool.CompileOnly)
2633         << attrE(_DebugInformationFormat, tool.DebugInformationFormat, /*ifNot*/ debugUnknown)
2634         << attrT(_Detect64BitPortabilityProblems, tool.Detect64BitPortabilityProblems)
2635         << attrT(_DisableLanguageExtensions, tool.DisableLanguageExtensions)
2636         << attrX(_DisableSpecificWarnings, tool.DisableSpecificWarnings)
2637         << attrE(_EnableEnhancedInstructionSet, tool.EnableEnhancedInstructionSet, /*ifnot*/ archNotSet)
2638         << attrT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations)
2639         << attrT(_EnableFunctionLevelLinking, tool.EnableFunctionLevelLinking)
2640         << attrT(_EnableIntrinsicFunctions, tool.EnableIntrinsicFunctions)
2641         << xformExceptionHandlingNET2005(tool.ExceptionHandling, tool.config->CompilerVersion)
2642         << attrT(_ExpandAttributedSource, tool.ExpandAttributedSource)
2643         << attrE(_FavorSizeOrSpeed, tool.FavorSizeOrSpeed, /*ifNot*/ favorNone)
2644 
2645         << attrE(_FloatingPointModel, tool.FloatingPointModel, /*ifNot*/ floatingPointNotSet)
2646         << attrT(_FloatingPointExceptions, tool.FloatingPointExceptions)
2647 
2648         << attrT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope)
2649         << attrX(_ForcedIncludeFiles, tool.ForcedIncludeFiles)
2650         << attrX(_ForcedUsingFiles, tool.ForcedUsingFiles)
2651         << attrE(_GeneratePreprocessedFile, tool.GeneratePreprocessedFile, /*ifNot*/ preprocessUnknown)
2652         << attrT(_GlobalOptimizations, tool.GlobalOptimizations)
2653         << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
2654         << attrT(_ImproveFloatingPointConsistency, tool.ImproveFloatingPointConsistency)
2655         << attrE(_InlineFunctionExpansion, tool.InlineFunctionExpansion, /*ifNot*/ expandDefault)
2656         << attrT(_KeepComments, tool.KeepComments)
2657         << attrT(_MinimalRebuild, tool.MinimalRebuild)
2658         << attrS(_ObjectFile, tool.ObjectFile)
2659         << attrT(_OmitFramePointers, tool.OmitFramePointers)
2660         << attrT(_OpenMP, tool.OpenMP)
2661         << attrE(_Optimization, tool.Optimization, /*ifNot*/ optimizeDefault)
2662         << attrE(_OptimizeForProcessor, tool.OptimizeForProcessor, /*ifNot*/ procOptimizeBlended)
2663         << attrT(_OptimizeForWindowsApplication, tool.OptimizeForWindowsApplication)
2664         << attrS(_OutputFile, tool.OutputFile)
2665         << attrS(_PrecompiledHeaderFile, tool.PrecompiledHeaderFile)
2666         << attrS(_PrecompiledHeaderThrough, tool.PrecompiledHeaderThrough)
2667         << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions)
2668         << (tool.ProgramDataBaseFileName.isNull() ? noxml() : attr(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName))
2669         << attrE(_RuntimeLibrary, tool.RuntimeLibrary, /*ifNot*/ rtUnknown)
2670         << attrT(_RuntimeTypeInfo, tool.RuntimeTypeInfo)
2671         << attrT(_ShowIncludes, tool.ShowIncludes)
2672         << attrT(_SmallerTypeCheck, tool.SmallerTypeCheck)
2673         << attrT(_StringPooling, tool.StringPooling)
2674         << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ alignNotSet)
2675         << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner)
2676         << attrT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType)
2677         << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration)
2678         << attrT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions)
2679         << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions)
2680         << xformUsePrecompiledHeaderForNET2005(tool.UsePrecompiledHeader, tool.config->CompilerVersion)
2681         << attrT(_WarnAsError, tool.WarnAsError)
2682         << attrE(_WarningLevel, tool.WarningLevel, /*ifNot*/ warningLevelUnknown)
2683         << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization)
2684         << attrE(_CompileForArchitecture, tool.CompileForArchitecture, /*ifNot*/ archUnknown)
2685         << attrT(_InterworkCalls, tool.InterworkCalls)
2686 
2687         << closetag(_Tool);
2688 }
2689 
write(XmlOutput & xml,const VCLinkerTool & tool)2690 void VCProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool)
2691 {
2692     xml << tag(_Tool)
2693         << attrS(_Name, _VCLinkerTool)
2694         << attrX(_AdditionalDependencies, tool.AdditionalDependencies, " ")
2695         << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories)
2696         << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
2697         << attrX(_AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly)
2698         << attrS(_BaseAddress, tool.BaseAddress)
2699         << attrT(_DataExecutionPrevention, tool.DataExecutionPrevention)
2700         << attrX(_DelayLoadDLLs, tool.DelayLoadDLLs)
2701         << attrE(_EnableCOMDATFolding, tool.EnableCOMDATFolding, /*ifNot*/ optFoldingDefault)
2702         << attrS(_EntryPointSymbol, tool.EntryPointSymbol)
2703         << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences)
2704         << attrS(_FunctionOrder, tool.FunctionOrder)
2705         << attrT(_GenerateDebugInformation, tool.GenerateDebugInformation)
2706         << attrT(_GenerateMapFile, tool.GenerateMapFile)
2707         << attrL(_HeapCommitSize, tool.HeapCommitSize, /*ifNot*/ -1)
2708         << attrL(_HeapReserveSize, tool.HeapReserveSize, /*ifNot*/ -1)
2709         << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries)
2710         << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames)
2711         << attrT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL)
2712         << attrT(_IgnoreImportLibrary, tool.IgnoreImportLibrary)
2713         << attrS(_ImportLibrary, tool.ImportLibrary)
2714         << attrE(_LargeAddressAware, tool.LargeAddressAware, /*ifNot*/ addrAwareDefault)
2715         << attrT(_LinkDLL, tool.LinkDLL)
2716         << attrE(_LinkIncremental, tool.LinkIncremental, /*ifNot*/ linkIncrementalDefault)
2717         << attrE(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration)
2718         << attrS(_LinkToManagedResourceFile, tool.LinkToManagedResourceFile)
2719         << attrT(_MapExports, tool.MapExports)
2720         << attrS(_MapFileName, tool.MapFileName)
2721         << attrT(_MapLines, tool.MapLines)
2722         << attrS(_MergedIDLBaseFileName, tool.MergedIDLBaseFileName)
2723         << attrS(_MergeSections, tool.MergeSections)
2724         << attrS(_MidlCommandFile, tool.MidlCommandFile)
2725         << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile)
2726         << attrE(_OptimizeForWindows98, tool.OptimizeForWindows98, /*ifNot*/ optWin98Default)
2727         << attrE(_OptimizeReferences, tool.OptimizeReferences, /*ifNot*/ optReferencesDefault)
2728         << attrS(_OutputFile, tool.OutputFile)
2729         << attr(_ProgramDatabaseFile, tool.ProgramDatabaseFile)
2730         << attrT(_RandomizedBaseAddress, tool.RandomizedBaseAddress)
2731         << attrT(_RegisterOutput, tool.RegisterOutput)
2732         << attrT(_ResourceOnlyDLL, tool.ResourceOnlyDLL)
2733         << attrT(_SetChecksum, tool.SetChecksum)
2734         << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet)
2735         << attrL(_StackCommitSize, tool.StackCommitSize, /*ifNot*/ -1)
2736         << attrL(_StackReserveSize, tool.StackReserveSize, /*ifNot*/ -1)
2737         << attrS(_StripPrivateSymbols, tool.StripPrivateSymbols)
2738         << attrE(_SubSystem, tool.SubSystem)
2739         << attrT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL)
2740         << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner)
2741         << attrT(_SwapRunFromCD, tool.SwapRunFromCD)
2742         << attrT(_SwapRunFromNet, tool.SwapRunFromNet)
2743         << attrE(_TargetMachine, tool.TargetMachine, /*ifNot*/ machineNotSet)
2744         << attrE(_TerminalServerAware, tool.TerminalServerAware, /*ifNot*/ termSvrAwareDefault)
2745         << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration)
2746         << attrS(_TypeLibraryFile, tool.TypeLibraryFile)
2747         << attrL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ rcUseDefault)
2748         << attrS(_Version, tool.Version)
2749         << attrT(_GenerateManifest, tool.GenerateManifest)
2750         << closetag(_Tool);
2751 }
2752 
write(XmlOutput & xml,const VCManifestTool & tool)2753 void VCProjectWriter::write(XmlOutput &xml, const VCManifestTool &tool)
2754 {
2755     xml << tag(_Tool)
2756         << attrS(_Name, _VCManifestTool)
2757         << attrT(_EmbedManifest, tool.EmbedManifest)
2758         << closetag(_Tool);
2759 }
2760 
write(XmlOutput & xml,const VCMIDLTool & tool)2761 void VCProjectWriter::write(XmlOutput &xml, const VCMIDLTool &tool)
2762 {
2763     xml << tag(_Tool)
2764         << attrS(_Name, _VCMIDLTool)
2765         << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories)
2766         << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
2767         << attrX(_CPreprocessOptions, tool.CPreprocessOptions)
2768         << attrE(_DefaultCharType, tool.DefaultCharType)
2769         << attrS(_DLLDataFileName, tool.DLLDataFileName)
2770         << attrE(_EnableErrorChecks, tool.EnableErrorChecks)
2771         << attrT(_ErrorCheckAllocations, tool.ErrorCheckAllocations)
2772         << attrT(_ErrorCheckBounds, tool.ErrorCheckBounds)
2773         << attrT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange)
2774         << attrT(_ErrorCheckRefPointers, tool.ErrorCheckRefPointers)
2775         << attrT(_ErrorCheckStubData, tool.ErrorCheckStubData)
2776         << attrX(_FullIncludePath, tool.FullIncludePath)
2777         << attrT(_GenerateStublessProxies, tool.GenerateStublessProxies)
2778         << attrT(_GenerateTypeLibrary, tool.GenerateTypeLibrary)
2779         << attrS(_HeaderFileName, tool.HeaderFileName)
2780         << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
2781         << attrS(_InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName)
2782         << attrT(_MkTypLibCompatible, tool.MkTypLibCompatible)
2783         << attrS(_OutputDirectory, tool.OutputDirectory)
2784         << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions)
2785         << attrS(_ProxyFileName, tool.ProxyFileName)
2786         << attrS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors)
2787         << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ midlAlignNotSet)
2788         << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner)
2789         << attrE(_TargetEnvironment, tool.TargetEnvironment, /*ifNot*/ midlTargetNotSet)
2790         << attrS(_TypeLibraryName, tool.TypeLibraryName)
2791         << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions)
2792         << attrT(_ValidateParameters, tool.ValidateParameters)
2793         << attrT(_WarnAsError, tool.WarnAsError)
2794         << attrE(_WarningLevel, tool.WarningLevel)
2795         << closetag(_Tool);
2796 }
2797 
write(XmlOutput & xml,const VCCustomBuildTool & tool)2798 void VCProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool)
2799 {
2800     xml << tag(_Tool)
2801             << attrS(_Name, tool.ToolName)
2802             << attrX(_AdditionalDependencies, tool.AdditionalDependencies, ";")
2803             << attrS(_CommandLine, tool.CommandLine.join(vcCommandSeparator()))
2804             << attrS(_Description, tool.Description)
2805             << attrX(_Outputs, tool.Outputs, ";")
2806             << attrS(_Path, tool.ToolPath)
2807         << closetag(_Tool);
2808 }
2809 
write(XmlOutput & xml,const VCLibrarianTool & tool)2810 void VCProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool)
2811 {
2812     xml
2813         << tag(_Tool)
2814             << attrS(_Name, _VCLibrarianTool)
2815             << attrX(_AdditionalDependencies, tool.AdditionalDependencies)
2816             << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories)
2817             << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
2818             << attrX(_ExportNamedFunctions, tool.ExportNamedFunctions)
2819             << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences)
2820             << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries)
2821             << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames)
2822             << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile)
2823             << attrS(_OutputFile, tool.OutputFile)
2824             << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner)
2825         << closetag(_Tool);
2826 }
2827 
write(XmlOutput & xml,const VCResourceCompilerTool & tool)2828 void VCProjectWriter::write(XmlOutput &xml, const VCResourceCompilerTool &tool)
2829 {
2830     xml
2831         << tag(_Tool)
2832             << attrS(_Name, _VCResourceCompilerTool)
2833             << attrS(_Path, tool.ToolPath)
2834             << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories)
2835             << attrX(_AdditionalOptions, tool.AdditionalOptions, " ")
2836             << attrE(_Culture, tool.Culture, /*ifNot*/ rcUseDefault)
2837             << attrX(_FullIncludePath, tool.FullIncludePath)
2838             << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath)
2839             << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions)
2840             << attrS(_ResourceOutputFileName, tool.ResourceOutputFileName)
2841             << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet)
2842         << closetag(_Tool);
2843 }
2844 
write(XmlOutput & xml,const VCEventTool & tool)2845 void VCProjectWriter::write(XmlOutput &xml, const VCEventTool &tool)
2846 {
2847     xml
2848         << tag(_Tool)
2849             << attrS(_Name, tool.ToolName)
2850             << attrS(_Path, tool.ToolPath)
2851             << attrS(_CommandLine, tool.CommandLine.join(vcCommandSeparator()))
2852             << attrS(_Description, tool.Description)
2853             << attrT(_ExcludedFromBuild, tool.ExcludedFromBuild)
2854         << closetag(_Tool);
2855 }
2856 
write(XmlOutput & xml,const VCDeploymentTool & tool)2857 void VCProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool)
2858 {
2859     if (tool.AdditionalFiles.isEmpty())
2860         return;
2861     xml << tag(tool.DeploymentTag)
2862         << attrS(_RemoteDirectory, tool.RemoteDirectory)
2863         << attrE(_RegisterOutput, tool.RegisterOutput)
2864         << attrS(_AdditionalFiles, tool.AdditionalFiles)
2865         << closetag(tool.DeploymentTag);
2866 }
2867 
write(XmlOutput & xml,const VCWinDeployQtTool & tool)2868 void VCProjectWriter::write(XmlOutput &xml, const VCWinDeployQtTool &tool)
2869 {
2870     Q_UNUSED(xml);
2871     Q_UNUSED(tool);
2872 }
2873 
write(XmlOutput & xml,const VCConfiguration & tool)2874 void VCProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool)
2875 {
2876     xml << tag(_Configuration)
2877             << attrS(_Name, tool.Name)
2878             << attrS(_OutputDirectory, tool.OutputDirectory)
2879             << attrT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage)
2880             << attrT(_BuildBrowserInformation, tool.BuildBrowserInformation)
2881             << attrE(_CharacterSet, tool.CharacterSet, /*ifNot*/ charSetNotSet)
2882             << attrE(_ConfigurationType, tool.ConfigurationType)
2883             << attrS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean)
2884             << attrS(_ImportLibrary, tool.ImportLibrary)
2885             << attrS(_IntermediateDirectory, tool.IntermediateDirectory)
2886             << attrS(_PrimaryOutput, tool.PrimaryOutput)
2887             << attrS(_ProgramDatabase, tool.ProgramDatabase)
2888             << attrT(_RegisterOutput, tool.RegisterOutput)
2889             << attrE(_UseOfATL, tool.UseOfATL, /*ifNot*/ useATLNotSet)
2890             << attrE(_UseOfMfc, tool.UseOfMfc)
2891             << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization);
2892     write(xml, tool.compiler);
2893     if (tool.ConfigurationType == typeStaticLibrary)
2894         write(xml, tool.librarian);
2895     else
2896         write(xml, tool.linker);
2897     write(xml, tool.manifestTool);
2898     write(xml, tool.idl);
2899     write(xml, tool.postBuild);
2900     write(xml, tool.preBuild);
2901     write(xml, tool.preLink);
2902     write(xml, tool.resource);
2903     write(xml, tool.deployment);
2904     xml << closetag(_Configuration);
2905 }
2906 
write(XmlOutput & xml,VCFilter & tool)2907 void VCProjectWriter::write(XmlOutput &xml, VCFilter &tool)
2908 {
2909     if(!tool.Files.count())
2910         return;
2911 
2912     if (!tool.Name.isEmpty()) {
2913         xml << tag(_Filter)
2914                 << attrS(_Name, tool.Name)
2915                 << attrS(_Filter, tool.Filter)
2916                 << attrS(_UniqueIdentifier, tool.Guid)
2917                 << attrT(_ParseFiles, tool.ParseFiles);
2918     }
2919     for (int i = 0; i < tool.Files.count(); ++i) {
2920         const VCFilterFile &info = tool.Files.at(i);
2921         xml << tag(q_File)
2922                 << attrS(_RelativePath, Option::fixPathToTargetOS(info.file))
2923             << data(); // In case no custom builds, to avoid "/>" endings
2924         outputFileConfig(tool, xml, tool.Files.at(i).file);
2925         xml << closetag(q_File);
2926     }
2927     if (!tool.Name.isEmpty())
2928         xml << closetag(_Filter);
2929 }
2930 
2931 // outputs a given filter for all existing configurations of a project
outputFilter(VCProject & project,XmlOutput & xml,const QString & filtername)2932 void VCProjectWriter::outputFilter(VCProject &project, XmlOutput &xml, const QString &filtername)
2933 {
2934     QScopedPointer<Node> root;
2935     if (project.SingleProjects.at(0).flat_files)
2936         root.reset(new FlatNode);
2937     else
2938         root.reset(new TreeNode);
2939 
2940     QString name, extfilter, guid;
2941     triState parse = unset;
2942 
2943     for (int i = 0; i < project.SingleProjects.count(); ++i) {
2944         const VCFilter filter = project.SingleProjects.at(i).filterByName(filtername);
2945 
2946         // Merge all files in this filter to root tree
2947         for (int x = 0; x < filter.Files.count(); ++x)
2948             root->addElement(filter.Files.at(x));
2949 
2950         // Save filter setting from first filter. Next filters
2951         // may differ but we cannot handle that. (ex. extfilter)
2952         if (name.isEmpty()) {
2953             name = filter.Name;
2954             extfilter = filter.Filter;
2955             parse = filter.ParseFiles;
2956             guid = filter.Guid;
2957         }
2958     }
2959 
2960     if (!root->hasElements())
2961         return;
2962 
2963     // Actual XML output ----------------------------------
2964     if (!name.isEmpty()) {
2965         xml << tag(_Filter)
2966                 << attrS(_Name, name)
2967                 << attrS(_Filter, extfilter)
2968                 << attrS(_UniqueIdentifier, guid)
2969                 << attrT(_ParseFiles, parse);
2970     }
2971     root->generateXML(xml, "", project, filtername); // output root tree
2972     if (!name.isEmpty())
2973         xml << closetag(_Filter);
2974 }
2975 
2976 // Output all configurations (by filtername) for a file (by info)
2977 // A filters config output is in VCFilter.outputFileConfig()
outputFileConfigs(VCProject & project,XmlOutput & xml,const VCFilterFile & info,const QString & filtername)2978 void VCProjectWriter::outputFileConfigs(VCProject &project, XmlOutput &xml, const VCFilterFile &info, const QString &filtername)
2979 {
2980     xml << tag(q_File)
2981             << attrS(_RelativePath, Option::fixPathToTargetOS(info.file));
2982     for (int i = 0; i < project.SingleProjects.count(); ++i) {
2983         VCFilter filter = project.SingleProjects.at(i).filterByName(filtername);
2984         if (filter.Config) // only if the filter is not empty
2985             outputFileConfig(filter, xml, info.file);
2986     }
2987     xml << closetag(q_File);
2988 }
2989 
outputFileConfig(VCFilter & filter,XmlOutput & xml,const QString & filename)2990 void VCProjectWriter::outputFileConfig(VCFilter &filter, XmlOutput &xml, const QString &filename)
2991 {
2992     // Clearing each filter tool
2993     filter.useCustomBuildTool = false;
2994     filter.useCompilerTool = false;
2995     filter.CustomBuildTool = VCCustomBuildTool();
2996     filter.CompilerTool = VCCLCompilerTool();
2997 
2998     // Unset some default options
2999     filter.CustomBuildTool.config = filter.Config;
3000     filter.CompilerTool.BufferSecurityCheck = unset;
3001     filter.CompilerTool.DebugInformationFormat = debugUnknown;
3002     filter.CompilerTool.ExceptionHandling = ehDefault;
3003     filter.CompilerTool.GeneratePreprocessedFile = preprocessUnknown;
3004     filter.CompilerTool.Optimization = optimizeDefault;
3005     filter.CompilerTool.ProgramDataBaseFileName.clear();
3006     filter.CompilerTool.RuntimeLibrary = rtUnknown;
3007     filter.CompilerTool.WarningLevel = warningLevelUnknown;
3008     filter.CompilerTool.config = filter.Config;
3009 
3010     bool inBuild;
3011     VCFilterFile info = filter.findFile(filename, &inBuild);
3012     inBuild &= !info.excludeFromBuild;
3013 
3014     if (inBuild) {
3015         filter.addExtraCompiler(info);
3016         if(filter.Project->usePCH)
3017             filter.modifyPCHstage(info.file);
3018     } else {
3019         // Excluded files uses an empty compiler stage
3020         if(info.excludeFromBuild)
3021             filter.useCompilerTool = true;
3022     }
3023 
3024     // Actual XML output ----------------------------------
3025     if (filter.useCustomBuildTool || filter.useCompilerTool || !inBuild) {
3026         xml << tag(_FileConfiguration)
3027                 << attr(_Name, filter.Config->Name)
3028                 << (!inBuild ? attrS(_ExcludedFromBuild, "true") : noxml());
3029         if (filter.useCustomBuildTool)
3030             filter.Project->projectWriter->write(xml, filter.CustomBuildTool);
3031         if (filter.useCompilerTool)
3032             filter.Project->projectWriter->write(xml, filter.CompilerTool);
3033         xml << closetag(_FileConfiguration);
3034     }
3035 }
3036 
3037 QT_END_NAMESPACE
3038