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

source code of qtbase/qmake/generators/win32/msvc_objectmodel.cpp