// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "msvc_objectmodel.h" #include "msvc_vcproj.h" #include "msvc_vcxproj.h" #include #include #include #include using namespace QMakeInternal; QT_BEGIN_NAMESPACE DotNET vsVersionFromString(const ProString &versionString) { int idx = versionString.indexOf(QLatin1Char('.')); if (idx == -1) return NETUnknown; QStringView versionView = versionString.toQStringView(); int versionMajor = versionView.left(idx).toInt(); int versionMinor = versionView.mid(idx + 1).toInt(); if (versionMajor == 17) return NET2022; if (versionMajor == 16) return NET2019; if (versionMajor == 15) return NET2017; if (versionMajor == 14) return NET2015; if (versionMajor == 12) return NET2013; if (versionMajor == 11) return NET2012; if (versionMajor == 10) return NET2010; if (versionMajor == 9) return NET2008; if (versionMajor == 8) return NET2005; if (versionMajor == 7) { if (versionMinor == 0) return NET2002; if (versionMinor == 1) return NET2003; } return NETUnknown; } // XML Tags --------------------------------------------------------- const char _Configuration[] = "Configuration"; const char _Configurations[] = "Configurations"; const char q_File[] = "File"; const char _FileConfiguration[] = "FileConfiguration"; const char q_Files[] = "Files"; const char _Filter[] = "Filter"; const char _Globals[] = "Globals"; const char _Platform[] = "Platform"; const char _Platforms[] = "Platforms"; const char _Tool[] = "Tool"; const char _VisualStudioProject[] = "VisualStudioProject"; // XML Properties --------------------------------------------------- const char _AddModuleNamesToAssembly[] = "AddModuleNamesToAssembly"; const char _AdditionalDependencies[] = "AdditionalDependencies"; const char _AdditionalFiles[] = "AdditionalFiles"; const char _AdditionalIncludeDirectories[] = "AdditionalIncludeDirectories"; const char _AdditionalLibraryDirectories[] = "AdditionalLibraryDirectories"; const char _AdditionalOptions[] = "AdditionalOptions"; const char _AdditionalUsingDirectories[] = "AdditionalUsingDirectories"; const char _AssemblerListingLocation[] = "AssemblerListingLocation"; const char _AssemblerOutput[] = "AssemblerOutput"; const char _ATLMinimizesCRunTimeLibraryUsage[] = "ATLMinimizesCRunTimeLibraryUsage"; const char _BaseAddress[] = "BaseAddress"; const char _BasicRuntimeChecks[] = "BasicRuntimeChecks"; const char _BrowseInformation[] = "BrowseInformation"; const char _BrowseInformationFile[] = "BrowseInformationFile"; const char _BufferSecurityCheck[] = "BufferSecurityCheck"; const char _BuildBrowserInformation[] = "BuildBrowserInformation"; const char _CPreprocessOptions[] = "CPreprocessOptions"; const char _CallingConvention[] = "CallingConvention"; const char _CharacterSet[] = "CharacterSet"; const char _CommandLine[] = "CommandLine"; const char _CompileAs[] = "CompileAs"; const char _CompileAsManaged[] = "CompileAsManaged"; const char _CompileOnly[] = "CompileOnly"; const char _ConfigurationType[] = "ConfigurationType"; const char _Culture[] = "Culture"; const char _DLLDataFileName[] = "DLLDataFileName"; const char _DataExecutionPrevention[] = "DataExecutionPrevention"; const char _DebugInformationFormat[] = "DebugInformationFormat"; const char _DefaultCharType[] = "DefaultCharType"; const char _DelayLoadDLLs[] = "DelayLoadDLLs"; const char _DeleteExtensionsOnClean[] = "DeleteExtensionsOnClean"; const char _Description[] = "Description"; const char _Detect64BitPortabilityProblems[] = "Detect64BitPortabilityProblems"; const char _DisableLanguageExtensions[] = "DisableLanguageExtensions"; const char _DisableSpecificWarnings[] = "DisableSpecificWarnings"; const char _EmbedManifest[] = "EmbedManifest"; const char _EnableCOMDATFolding[] = "EnableCOMDATFolding"; const char _EnableErrorChecks[] = "EnableErrorChecks"; const char _EnableEnhancedInstructionSet[] = "EnableEnhancedInstructionSet"; const char _EnableFiberSafeOptimizations[] = "EnableFiberSafeOptimizations"; const char _EnableFunctionLevelLinking[] = "EnableFunctionLevelLinking"; const char _EnableIntrinsicFunctions[] = "EnableIntrinsicFunctions"; const char _EntryPointSymbol[] = "EntryPointSymbol"; const char _ErrorCheckAllocations[] = "ErrorCheckAllocations"; const char _ErrorCheckBounds[] = "ErrorCheckBounds"; const char _ErrorCheckEnumRange[] = "ErrorCheckEnumRange"; const char _ErrorCheckRefPointers[] = "ErrorCheckRefPointers"; const char _ErrorCheckStubData[] = "ErrorCheckStubData"; const char _ExceptionHandling[] = "ExceptionHandling"; const char _ExcludedFromBuild[] = "ExcludedFromBuild"; const char _ExpandAttributedSource[] = "ExpandAttributedSource"; const char _ExportNamedFunctions[] = "ExportNamedFunctions"; const char _FavorSizeOrSpeed[] = "FavorSizeOrSpeed"; const char _FloatingPointModel[] = "FloatingPointModel"; const char _FloatingPointExceptions[] = "FloatingPointExceptions"; const char _ForceConformanceInForLoopScope[] = "ForceConformanceInForLoopScope"; const char _ForceSymbolReferences[] = "ForceSymbolReferences"; const char _ForcedIncludeFiles[] = "ForcedIncludeFiles"; const char _ForcedUsingFiles[] = "ForcedUsingFiles"; const char _FullIncludePath[] = "FullIncludePath"; const char _FunctionOrder[] = "FunctionOrder"; const char _GenerateDebugInformation[] = "GenerateDebugInformation"; const char _GenerateMapFile[] = "GenerateMapFile"; const char _GeneratePreprocessedFile[] = "GeneratePreprocessedFile"; const char _GenerateStublessProxies[] = "GenerateStublessProxies"; const char _GenerateTypeLibrary[] = "GenerateTypeLibrary"; const char _GlobalOptimizations[] = "GlobalOptimizations"; const char _HeaderFileName[] = "HeaderFileName"; const char _HeapCommitSize[] = "HeapCommitSize"; const char _HeapReserveSize[] = "HeapReserveSize"; const char _IgnoreAllDefaultLibraries[] = "IgnoreAllDefaultLibraries"; const char _IgnoreDefaultLibraryNames[] = "IgnoreDefaultLibraryNames"; const char _IgnoreEmbeddedIDL[] = "IgnoreEmbeddedIDL"; const char _IgnoreImportLibrary[] = "IgnoreImportLibrary"; const char _IgnoreStandardIncludePath[] = "IgnoreStandardIncludePath"; const char _ImportLibrary[] = "ImportLibrary"; const char _ImproveFloatingPointConsistency[] = "ImproveFloatingPointConsistency"; const char _InlineFunctionExpansion[] = "InlineFunctionExpansion"; const char _InterfaceIdentifierFileName[] = "InterfaceIdentifierFileName"; const char _IntermediateDirectory[] = "IntermediateDirectory"; const char _KeepComments[] = "KeepComments"; const char _LargeAddressAware[] = "LargeAddressAware"; const char _LinkDLL[] = "LinkDLL"; const char _LinkIncremental[] = "LinkIncremental"; const char _LinkTimeCodeGeneration[] = "LinkTimeCodeGeneration"; const char _LinkToManagedResourceFile[] = "LinkToManagedResourceFile"; const char _MapExports[] = "MapExports"; const char _MapFileName[] = "MapFileName"; const char _MapLines[] = "MapLines "; const char _MergeSections[] = "MergeSections"; const char _MergedIDLBaseFileName[] = "MergedIDLBaseFileName"; const char _MidlCommandFile[] = "MidlCommandFile"; const char _MinimalRebuild[] = "MinimalRebuild"; const char _MkTypLibCompatible[] = "MkTypLibCompatible"; const char _ModuleDefinitionFile[] = "ModuleDefinitionFile"; const char _Name[] = "Name"; const char _ObjectFile[] = "ObjectFile"; const char _OmitFramePointers[] = "OmitFramePointers"; const char _OpenMP[] = "OpenMP"; const char _Optimization[] = "Optimization "; const char _OptimizeForProcessor[] = "OptimizeForProcessor"; const char _OptimizeForWindows98[] = "OptimizeForWindows98"; const char _OptimizeForWindowsApplication[] = "OptimizeForWindowsApplication"; const char _OptimizeReferences[] = "OptimizeReferences"; const char _OutputDirectory[] = "OutputDirectory"; const char _OutputFile[] = "OutputFile"; const char _Outputs[] = "Outputs"; const char _ParseFiles[] = "ParseFiles"; const char _PrecompiledHeaderFile[] = "PrecompiledHeaderFile"; const char _PrecompiledHeaderThrough[] = "PrecompiledHeaderThrough"; const char _PreprocessorDefinitions[] = "PreprocessorDefinitions"; const char _PrimaryOutput[] = "PrimaryOutput"; const char _ProjectGUID[] = "ProjectGUID"; const char _Keyword[] = "Keyword"; const char _ProjectType[] = "ProjectType"; const char _ProgramDatabase[] = "ProgramDatabase"; const char _ProgramDataBaseFileName[] = "ProgramDataBaseFileName"; const char _ProgramDatabaseFile[] = "ProgramDatabaseFile"; const char _ProxyFileName[] = "ProxyFileName"; const char _RandomizedBaseAddress[] = "RandomizedBaseAddress"; const char _RedirectOutputAndErrors[] = "RedirectOutputAndErrors"; const char _RegisterOutput[] = "RegisterOutput"; const char _RelativePath[] = "RelativePath"; const char _RemoteDirectory[] = "RemoteDirectory"; const char _ResourceOnlyDLL[] = "ResourceOnlyDLL"; const char _ResourceOutputFileName[] = "ResourceOutputFileName"; const char _RuntimeLibrary[] = "RuntimeLibrary"; const char _RuntimeTypeInfo[] = "RuntimeTypeInfo"; const char _SccProjectName[] = "SccProjectName"; const char _SccLocalPath[] = "SccLocalPath"; const char _SetChecksum[] = "SetChecksum"; const char _ShowIncludes[] = "ShowIncludes"; const char _ShowProgress[] = "ShowProgress"; const char _SmallerTypeCheck[] = "SmallerTypeCheck"; const char _StackCommitSize[] = "StackCommitSize"; const char _StackReserveSize[] = "StackReserveSize"; const char _StringPooling[] = "StringPooling"; const char _StripPrivateSymbols[] = "StripPrivateSymbols"; const char _StructMemberAlignment[] = "StructMemberAlignment"; const char _SubSystem[] = "SubSystem"; const char _SupportUnloadOfDelayLoadedDLL[] = "SupportUnloadOfDelayLoadedDLL"; const char _SuppressStartupBanner[] = "SuppressStartupBanner"; const char _SwapRunFromCD[] = "SwapRunFromCD"; const char _SwapRunFromNet[] = "SwapRunFromNet"; const char _TargetEnvironment[] = "TargetEnvironment"; const char _TargetMachine[] = "TargetMachine"; const char _TerminalServerAware[] = "TerminalServerAware"; const char _Path[] = "Path"; const char _TreatWChar_tAsBuiltInType[] = "TreatWChar_tAsBuiltInType"; const char _TurnOffAssemblyGeneration[] = "TurnOffAssemblyGeneration"; const char _TypeLibraryFile[] = "TypeLibraryFile"; const char _TypeLibraryName[] = "TypeLibraryName"; const char _TypeLibraryResourceID[] = "TypeLibraryResourceID"; const char _UndefineAllPreprocessorDefinitions[]= "UndefineAllPreprocessorDefinitions"; const char _UndefinePreprocessorDefinitions[] = "UndefinePreprocessorDefinitions"; const char _UniqueIdentifier[] = "UniqueIdentifier"; const char _UseOfATL[] = "UseOfATL"; const char _UseOfMfc[] = "UseOfMfc"; const char _UsePrecompiledHeader[] = "UsePrecompiledHeader"; const char _ValidateParameters[] = "ValidateParameters"; const char _VCCLCompilerTool[] = "VCCLCompilerTool"; const char _VCLibrarianTool[] = "VCLibrarianTool"; const char _VCLinkerTool[] = "VCLinkerTool"; const char _VCManifestTool[] = "VCManifestTool"; const char _VCCustomBuildTool[] = "VCCustomBuildTool"; const char _VCResourceCompilerTool[] = "VCResourceCompilerTool"; const char _VCMIDLTool[] = "VCMIDLTool"; const char _Version[] = "Version"; const char _WarnAsError[] = "WarnAsError"; const char _WarningLevel[] = "WarningLevel"; const char _WholeProgramOptimization[] = "WholeProgramOptimization"; const char _CompileForArchitecture[] = "CompileForArchitecture"; const char _InterworkCalls[] = "InterworkCalls"; const char _GenerateManifest[] = "GenerateManifest"; // XmlOutput stream functions ------------------------------ inline XmlOutput::xml_output attrT(const char *name, const triState v) { if(v == unset) return noxml(); return attr(name, (v == _True ? "true" : "false")); } inline XmlOutput::xml_output attrE(const char *name, int v) { return attr(name, QString::number(v)); } /*ifNot version*/ inline XmlOutput::xml_output attrE(const char *name, int v, int ifn) { if (v == ifn) return noxml(); return attr(name, QString::number(v)); } inline XmlOutput::xml_output attrL(const char *name, qint64 v) { return attr(name, QString::number(v)); } /*ifNot version*/ inline XmlOutput::xml_output attrL(const char *name, qint64 v, qint64 ifn) { if (v == ifn) return noxml(); return attr(name, QString::number(v)); } inline XmlOutput::xml_output attrS(const char *name, const QString &v) { if(v.isEmpty()) return noxml(); return attr(name, v); } inline XmlOutput::xml_output attrX(const char *name, const QStringList &v, const char *s = ",") { if(v.isEmpty()) return noxml(); return attr(name, v.join(s)); } triState operator!(const triState &rhs) { if (rhs == unset) return rhs; triState lhs = (rhs == _True ? _False : _True); return lhs; } // VCToolBase ------------------------------------------------- QStringList VCToolBase::fixCommandLine(const QString &input) { // The splitting regexp is a bit bizarre for backwards compat reasons (why else ...). return input.split(QRegularExpression(QLatin1String("(\n\t|\r\\\\h|\r\n)\\s*"))); } static QString vcCommandSeparator() { // MSVC transforms the build tree into a single batch file, simply pasting the contents // of the custom commands into it, and putting an "if errorlevel goto" statement behind it. // As we want every sub-command to be error-checked (as is done by makefile-based // backends), we insert the checks ourselves, using the undocumented jump target. return QStringLiteral(" if errorlevel 1 goto VCReportError "); } static void unknownOptionWarning(const char *tool, const char *option) { Q_CONSTINIT static bool firstCall = true; warn_msg(WarnLogic, "Could not parse %s option '%s'; added to AdditionalOptions.", tool, option); if (firstCall) { firstCall = false; warn_msg(WarnLogic, "You can suppress these warnings with CONFIG+=suppress_vcproj_warnings."); } } // VCCLCompilerTool ------------------------------------------------- VCCLCompilerTool::VCCLCompilerTool() : AssemblerOutput(asmListingNone), BasicRuntimeChecks(runtimeBasicCheckNone), BrowseInformation(brInfoNone), BufferSecurityCheck(unset), CallingConvention(callConventionDefault), CompileAs(compileAsDefault), CompileAsManaged(managedDefault), CompileAsWinRT(unset), CompileOnly(unset), DebugInformationFormat(debugDisabled), Detect64BitPortabilityProblems(unset), DisableLanguageExtensions(unset), EnableEnhancedInstructionSet(archNotSet), EnableFiberSafeOptimizations(unset), EnableFunctionLevelLinking(unset), EnableIntrinsicFunctions(unset), ExceptionHandling(ehDefault), ExpandAttributedSource(unset), FavorSizeOrSpeed(favorNone), FloatingPointModel(floatingPointNotSet), FloatingPointExceptions(unset), ForceConformanceInForLoopScope(unset), GeneratePreprocessedFile(preprocessNo), PreprocessSuppressLineNumbers(unset), GlobalOptimizations(unset), IgnoreStandardIncludePath(unset), ImproveFloatingPointConsistency(unset), InlineFunctionExpansion(expandDefault), KeepComments(unset), MinimalRebuild(unset), OmitDefaultLibName(unset), OmitFramePointers(unset), OpenMP(unset), Optimization(optimizeCustom), OptimizeForProcessor(procOptimizeBlended), OptimizeForWindowsApplication(unset), ProgramDataBaseFileName(""), RuntimeLibrary(rtMultiThreaded), RuntimeTypeInfo(unset), ShowIncludes(unset), SmallerTypeCheck(unset), StringPooling(unset), StructMemberAlignment(alignNotSet), SuppressStartupBanner(unset), TreatWChar_tAsBuiltInType(unset), TurnOffAssemblyGeneration(unset), UndefineAllPreprocessorDefinitions(unset), UsePrecompiledHeader(pchUnset), UseUnicodeForAssemblerListing(unset), WarnAsError(unset), WarningLevel(warningLevel_0), WholeProgramOptimization(unset), CompileForArchitecture(archUnknown), InterworkCalls(unset), EnablePREfast(unset), DisplayFullPaths(_False), MultiProcessorCompilation(unset), GenerateXMLDocumentationFiles(unset), CreateHotpatchableImage(unset) { } /* * Some values for the attribute UsePrecompiledHeader have changed from VS 2003 to VS 2005, * see the following chart, so we need a function that transforms those values if we are * using NET2005: * * Meaning 2003 2005 * ----------------------------------------- * Don't use PCH 0 0 * Create PCH (/Yc) 1 1 * Automatically generate (/YX) 2 (seems that it was removed) * Use specific PCH (/Yu) 3 2 * */ inline XmlOutput::xml_output xformUsePrecompiledHeaderForNET2005(pchOption whatPch, DotNET compilerVersion) { if (compilerVersion >= NET2005) { if (whatPch == pchGenerateAuto) whatPch = (pchOption)0; if (whatPch == pchUseUsingSpecific) whatPch = (pchOption)2; } return attrE(_UsePrecompiledHeader, whatPch, /*ifNot*/ pchUnset); } inline XmlOutput::xml_output xformExceptionHandlingNET2005(exceptionHandling eh, DotNET compilerVersion) { if (eh == ehDefault) return noxml(); if (compilerVersion >= NET2005) return attrE(_ExceptionHandling, eh); return attrS(_ExceptionHandling, (eh == ehNoSEH ? "true" : "false")); } bool VCCLCompilerTool::parseOption(const char* option) { // skip index 0 ('/' or '-') char first = option[1]; char second = option[2]; char third = option[3]; char fourth = option[4]; bool found = true; switch (first) { case '?': case 'h': if(second == 'o' && third == 't' && fourth == 'p') { CreateHotpatchableImage = _True; break; } qWarning("Generator: Option '/?', '/help': MSVC.NET projects do not support outputting help info"); found = false; break; case '@': qWarning("Generator: Option '/@': MSVC.NET projects do not support the use of a response file"); found = false; break; case 'l': qWarning("Generator: Option '/link': qmake generator does not support passing link options through the compiler tool"); found = false; break; case 'A': if(second != 'I') { found = false; break; } AdditionalUsingDirectories += option+3; break; case 'C': KeepComments = _True; break; case 'D': PreprocessorDefinitions += option+2; break; case 'E': if(second == 'H') { QByteArray opt(option + 2); if (opt.contains('a') && !opt.contains('s') && !opt.contains('c')) ExceptionHandling = ehSEH; else if (!opt.contains('a') && opt.contains("s-") && opt.contains("c-")) ExceptionHandling = ehNone; else if (!opt.contains('a') && opt.contains('s') && opt.contains('c')) ExceptionHandling = ehNoSEH; else { // ExceptionHandling must be false, or it will override // with an /EHsc option ExceptionHandling = ehNone; AdditionalOptions += option; } if (config->CompilerVersion < NET2005 && ExceptionHandling == ehSEH) { ExceptionHandling = ehNone; AdditionalOptions += option; } break; } else if (second == 'P') { PreprocessSuppressLineNumbers = _True; } GeneratePreprocessedFile = preprocessYes; break; case 'F': if(second <= '9' && second >= '0') { AdditionalOptions += option; break; } else { switch (second) { case 'A': if(third == 'c') { AssemblerOutput = asmListingAsmMachine; if(fourth == 's') AssemblerOutput = asmListingAsmMachineSrc; } else if(third == 's') { AssemblerOutput = asmListingAsmSrc; } else if (third == 'u') { UseUnicodeForAssemblerListing = _True; } else { AssemblerOutput = asmListingAssemblyOnly; } break; case 'C': DisplayFullPaths = _True; break; case 'a': AssemblerListingLocation = option+3; break; case 'I': ForcedIncludeFiles += option+3; break; case 'i': PreprocessOutputPath += option+3; break; case 'R': BrowseInformation = brAllInfo; BrowseInformationFile = option+3; break; case 'S': if (config->CompilerVersion < NET2013) found = false; // Ignore this flag. Visual Studio 2013 takes care of this setting. break; case 'r': BrowseInformation = brNoLocalSymbols; BrowseInformationFile = option+3; break; case 'U': ForcedUsingFiles += option+3; break; case 'd': ProgramDataBaseFileName = option+3; break; case 'e': OutputFile = option+3; break; case 'm': AdditionalOptions += option; break; case 'o': ObjectFile = option+3; break; case 'p': PrecompiledHeaderFile = option+3; break; case 'x': ExpandAttributedSource = _True; break; default: found = false; break; } } break; case 'G': switch (second) { case '3': case '4': qWarning("Option '/G3' and '/G4' were phased out in Visual C++ 5.0"); found = false; break; case '5': OptimizeForProcessor = procOptimizePentium; break; case '6': case 'B': OptimizeForProcessor = procOptimizePentiumProAndAbove; break; case '7': OptimizeForProcessor = procOptimizePentium4AndAbove; break; case 'A': OptimizeForWindowsApplication = _True; break; case 'F': StringPooling = _True; break; case 'H': AdditionalOptions += option; break; case 'L': WholeProgramOptimization = _True; if(third == '-') WholeProgramOptimization = _False; break; case 'R': RuntimeTypeInfo = _True; if(third == '-') RuntimeTypeInfo = _False; break; case 'S': BufferSecurityCheck = _True; if(third == '-') BufferSecurityCheck = _False; break; case 'T': EnableFiberSafeOptimizations = _True; break; case 'X': // Same as the /EHsc option, which is Exception Handling without SEH ExceptionHandling = ehNoSEH; if (third == '-') ExceptionHandling = ehNone; break; case 'Z': case 'e': case 'h': AdditionalOptions += option; break; case 'd': CallingConvention = callConventionCDecl; break; case 'f': StringPooling = _True; AdditionalOptions += option; break; case 'm': MinimalRebuild = _True; if(third == '-') MinimalRebuild = _False; break; case 'r': CallingConvention = callConventionFastCall; break; case 's': AdditionalOptions += option; break; case 'y': EnableFunctionLevelLinking = _True; break; case 'z': CallingConvention = callConventionStdCall; break; default: found = false; break; } break; case 'H': AdditionalOptions += option; break; case 'I': AdditionalIncludeDirectories += option+2; break; case 'J': AdditionalOptions += option; break; case 'L': if(second == 'D') { AdditionalOptions += option; break; } found = false; break; case 'M': if(second == 'D') { RuntimeLibrary = rtMultiThreadedDLL; if(third == 'd') RuntimeLibrary = rtMultiThreadedDebugDLL; break; } else if(second == 'L') { RuntimeLibrary = rtSingleThreaded; if(third == 'd') RuntimeLibrary = rtSingleThreadedDebug; break; } else if(second == 'T') { RuntimeLibrary = rtMultiThreaded; if(third == 'd') RuntimeLibrary = rtMultiThreadedDebug; break; } else if (second == 'P') { if (config->CompilerVersion >= NET2010) { MultiProcessorCompilation = _True; MultiProcessorCompilationProcessorCount = option+3; } else if (config->CompilerVersion >= NET2005) { AdditionalOptions += option; } else { warn_msg(WarnLogic, "/MP option is not supported in Visual C++ < 2005, ignoring."); } break; } found = false; break; case 'O': switch (second) { case '1': Optimization = optimizeMinSpace; break; case '2': Optimization = optimizeMaxSpeed; break; case 'a': AdditionalOptions += option; break; case 'b': if(third == '0') InlineFunctionExpansion = expandDisable; else if(third == '1') InlineFunctionExpansion = expandOnlyInline; else if(third == '2') InlineFunctionExpansion = expandAnySuitable; else found = false; break; case 'd': Optimization = optimizeDisabled; break; case 'g': GlobalOptimizations = _True; break; case 'i': EnableIntrinsicFunctions = _True; break; case 'p': ImproveFloatingPointConsistency = _True; if(third == '-') ImproveFloatingPointConsistency = _False; break; case 's': FavorSizeOrSpeed = favorSize; break; case 't': FavorSizeOrSpeed = favorSpeed; break; case 'w': AdditionalOptions += option; break; case 'x': Optimization = optimizeFull; break; case 'y': OmitFramePointers = _True; if(third == '-') OmitFramePointers = _False; break; default: found = false; break; } break; case 'P': GeneratePreprocessedFile = preprocessYes; break; case 'Q': if(second == 'I') { AdditionalOptions += option; break; } else if (second == 'R') { QString opt = option + 3; if (opt == "interwork-return") { InterworkCalls = _True; break; } else if (opt == "arch4") { CompileForArchitecture = archArmv4; break; } else if (opt == "arch5") { CompileForArchitecture = archArmv5; break; } else if (opt == "arch4T") { CompileForArchitecture = archArmv4T; break; } else if (opt == "arch5T") { CompileForArchitecture = archArmv5T; break; } } else if (second == 'M') { QString opt = option + 3; if (opt == "mips1") { CompileForArchitecture = archMips1; break; } else if (opt == "mips2") { CompileForArchitecture = archMips2; break; } else if (opt == "mips3") { CompileForArchitecture = archMips3; break; } else if (opt == "mips4") { CompileForArchitecture = archMips4; break; } else if (opt == "mips5") { CompileForArchitecture = archMips5; break; } else if (opt == "mips16") { CompileForArchitecture = archMips16; break; } else if (opt == "mips32") { CompileForArchitecture = archMips32; break; } else if (opt == "mips64") { CompileForArchitecture = archMips64; break; } } found = false; break; case 'R': if(second == 'T' && third == 'C') { int rtc = BasicRuntimeChecks; for (size_t i = 4; option[i]; ++i) { if (!parseRuntimeCheckOption(option[i], &rtc)) { found = false; break; } } BasicRuntimeChecks = static_cast(rtc); } break; case 'T': if(second == 'C') { CompileAs = compileAsC; } else if(second == 'P') { CompileAs = compileAsCPlusPlus; } else { qWarning("Generator: Options '/Tp' and '/Tc' are not supported by qmake"); found = false; break; } break; case 'U': UndefinePreprocessorDefinitions += option+2; break; case 'V': AdditionalOptions += option; break; case 'W': switch (second) { case 'a': case '4': WarningLevel = warningLevel_4; break; case '3': WarningLevel = warningLevel_3; break; case '2': WarningLevel = warningLevel_2; break; case '1': WarningLevel = warningLevel_1; break; case '0': WarningLevel = warningLevel_0; break; case 'L': AdditionalOptions += option; break; case 'X': WarnAsError = _True; break; case 'p': if(third == '6' && fourth == '4') { if (config->CompilerVersion >= NET2010) { // Deprecated for VS2010 but can be used under Additional Options. AdditionalOptions += option; } else { Detect64BitPortabilityProblems = _True; } break; } // Fallthrough default: found = false; break; } break; case 'X': IgnoreStandardIncludePath = _True; break; case 'Y': switch (second) { case '\0': case '-': AdditionalOptions += option; break; case 'X': UsePrecompiledHeader = pchGenerateAuto; PrecompiledHeaderThrough = option+3; break; case 'c': UsePrecompiledHeader = pchCreateUsingSpecific; PrecompiledHeaderThrough = option+3; break; case 'd': case 'l': AdditionalOptions += option; break; case 'u': UsePrecompiledHeader = pchUseUsingSpecific; PrecompiledHeaderThrough = option+3; break; default: found = false; break; } break; case 'Z': switch (second) { case '7': DebugInformationFormat = debugOldStyleInfo; break; case 'I': DebugInformationFormat = debugEditAndContinue; break; case 'd': DebugInformationFormat = debugLineInfoOnly; break; case 'i': DebugInformationFormat = debugEnabled; break; case 'l': OmitDefaultLibName = _True; break; case 'a': DisableLanguageExtensions = _True; break; case 'e': DisableLanguageExtensions = _False; break; case 'c': if(third == ':') { const char *c = option + 4; // Go to the end of the option while ( *c != '\0' && *c != ' ' && *c != '-') ++c; if(fourth == 'f') ForceConformanceInForLoopScope = ((*c) == '-' ? _False : _True); else if(fourth == 'w') TreatWChar_tAsBuiltInType = ((*c) == '-' ? _False : _True); else AdditionalOptions += option; } else { found = false; break; } break; case 'g': case 'm': case 's': AdditionalOptions += option; break; case 'p': switch (third) { case '\0': case '1': StructMemberAlignment = alignSingleByte; if(fourth == '6') StructMemberAlignment = alignSixteenBytes; break; case '2': StructMemberAlignment = alignTwoBytes; break; case '4': StructMemberAlignment = alignFourBytes; break; case '8': StructMemberAlignment = alignEightBytes; break; default: found = false; break; } break; case 'W': if (third == '-') CompileAsWinRT = _False; else CompileAsWinRT = _True; break; default: found = false; break; } break; case 'a': if (second == 'r' && third == 'c' && fourth == 'h') { if (option[5] == ':') { const char *o = option; if (o[6] == 'S' && o[7] == 'S' && o[8] == 'E') { EnableEnhancedInstructionSet = o[9] == '2' ? archSSE2 : archSSE; break; } } } else if (second == 'n' && third == 'a' && fourth == 'l') { EnablePREfast = _True; break; } found = false; break; case 'b': // see http://msdn2.microsoft.com/en-us/library/ms173499.aspx if (second == 'i' && third == 'g' && fourth == 'o') { const char *o = option; if (o[5] == 'b' && o[6] == 'j') { AdditionalOptions += option; break; } } found = false; break; case 'c': if(second == '\0') { CompileOnly = _True; } else if(second == 'l') { if (config->CompilerVersion < NET2005) { if(*(option+5) == 'n') { CompileAsManaged = managedAssemblyPure; TurnOffAssemblyGeneration = _True; } else if(*(option+5) == 'p') { CompileAsManaged = managedAssemblyPure; warn_msg(WarnLogic, "/clr:pure option only for .NET >= 2005, using /clr"); } else if(*(option+5) == 's') { CompileAsManaged = managedAssemblyPure; warn_msg(WarnLogic, "/clr:safe option only for .NET >= 2005, using /clr"); } else if(*(option+5) == 'o') { CompileAsManaged = managedAssemblyPure; warn_msg(WarnLogic, "/clr:oldSyntax option only for .NET >= 2005, using /clr"); } else if(*(option+5) == 'i') { CompileAsManaged = managedAssemblyPure; warn_msg(WarnLogic, "initialAppDomain enum value unknown, using /crl"); } else { CompileAsManaged = managedAssemblyPure; } } else { if(*(option+5) == 'n') { CompileAsManaged = managedAssembly; TurnOffAssemblyGeneration = _True; } else if(*(option+5) == 'p') { CompileAsManaged = managedAssemblyPure; } else if(*(option+5) == 's') { CompileAsManaged = managedAssemblySafe; } else if(*(option+5) == 'o') { CompileAsManaged = managedAssemblyOldSyntax; } else if(*(option+5) == 'i') { CompileAsManaged = managedAssembly; warn_msg(WarnLogic, "initialAppDomain enum value unknown, using /crl default"); } else { CompileAsManaged = managedAssembly; } } } else { found = false; break; } break; case 'd': if (second == 'r') { CompileAsManaged = managedAssembly; break; } else if (second != 'o' && third == 'c') { GenerateXMLDocumentationFiles = _True; XMLDocumentationFileName += option+4; break; } found = false; break; case 'e': if (second == 'r' && third == 'r' && fourth == 'o') { if (option[12] == ':') { if ( option[13] == 'n') { ErrorReporting = "None"; } else if (option[13] == 'p') { ErrorReporting = "Prompt"; } else if (option[13] == 'q') { ErrorReporting = "Queue"; } else if (option[13] == 's') { ErrorReporting = "Send"; } else { found = false; } break; } } found = false; break; case 'f': if(second == 'p' && third == ':') { // Go to the end of the option const char *c = option + 4; while (*c != '\0' && *c != ' ' && *c != '-') ++c; switch (fourth) { case 'e': FloatingPointExceptions = ((*c) == '-' ? _False : _True); break; case 'f': FloatingPointModel = floatingPointFast; break; case 'p': FloatingPointModel = floatingPointPrecise; break; case 's': FloatingPointModel = floatingPointStrict; break; default: found = false; break; } } break; case 'n': if(second == 'o' && third == 'B' && fourth == 'o') { AdditionalOptions += "/noBool"; break; } if(second == 'o' && third == 'l' && fourth == 'o') { SuppressStartupBanner = _True; break; } found = false; break; case 'o': { const char *str = option + 2; const size_t len = strlen(str); if (len >= 5 && len <= 6 && strncmp(str, "penmp", 5) == 0) { if (len == 5) { OpenMP = _True; break; } else if (str[5] == '-') { OpenMP = _False; break; } } found = false; break; } case 's': if(second == 'h' && third == 'o' && fourth == 'w') { ShowIncludes = _True; break; } if (strlen(option) > 7 && second == 't' && third == 'd' && fourth == ':') { static const QRegularExpression rex("(c(?:\\+\\+)?)(.+)"); auto m = rex.match(option + 5); if (m.hasMatch()) { QString *var = nullptr; const QStringList *knownVersions = nullptr; QString valuePrefix; auto lang = m.capturedView(1); auto version = m.capturedView(2); if (lang == QStringLiteral("c++")) { // Turn /std:c++17 into stdcpp17 static const QStringList knownCxxVersions = { "14", "17", "20", "latest" }; var = &LanguageStandard; knownVersions = &knownCxxVersions; valuePrefix = "stdcpp"; } else if (lang == QStringLiteral("c")) { // Turn /std:c17 into stdc17 static const QStringList knownCVersions = { "11", "17" }; var = &LanguageStandard_C; knownVersions = &knownCVersions; valuePrefix = "stdc"; } if (var && knownVersions->contains(version)) { *var = valuePrefix + version; break; } } } found = false; break; case 'u': if (!second) UndefineAllPreprocessorDefinitions = _True; else if (strcmp(option + 2, "tf-8") == 0) AdditionalOptions += option; else found = false; break; case 'v': if(second == 'd' || second == 'm') { AdditionalOptions += option; break; } found = false; break; case 'w': switch (second) { case '\0': WarningLevel = warningLevel_0; break; case 'd': DisableSpecificWarnings += option+3; break; case 'e': if (config->CompilerVersion <= NET2008) AdditionalOptions += option; else TreatSpecificWarningsAsErrors += option + 3; break; default: AdditionalOptions += option; } break; default: AdditionalOptions += option; break; } if(!found) { if (!config->suppressUnknownOptionWarnings) unknownOptionWarning("Compiler", option); AdditionalOptions += option; } return true; } bool VCCLCompilerTool::parseRuntimeCheckOption(char c, int *rtc) { if (c == '1') *rtc = runtimeBasicCheckAll; else if (c == 'c') SmallerTypeCheck = _True; else if (c == 's') *rtc |= runtimeCheckStackFrame; else if (c == 'u') *rtc |= runtimeCheckUninitVariables; else return false; return true; } // VCLinkerTool ----------------------------------------------------- VCLinkerTool::VCLinkerTool() : DataExecutionPrevention(unset), EnableCOMDATFolding(optFoldingDefault), GenerateDebugInformation(unset), DebugInfoOption(linkerDebugOptionNone), GenerateMapFile(unset), HeapCommitSize(-1), HeapReserveSize(-1), IgnoreAllDefaultLibraries(unset), IgnoreEmbeddedIDL(unset), IgnoreImportLibrary(_True), ImageHasSafeExceptionHandlers(unset), LargeAddressAware(addrAwareDefault), LinkDLL(unset), LinkIncremental(linkIncrementalDefault), LinkTimeCodeGeneration(optLTCGDefault), MapExports(unset), MapLines(unset), OptimizeForWindows98(optWin98Default), OptimizeReferences(optReferencesDefault), RandomizedBaseAddress(unset), RegisterOutput(unset), ResourceOnlyDLL(unset), SetChecksum(unset), ShowProgress(linkProgressNotSet), StackCommitSize(-1), StackReserveSize(-1), SubSystem(subSystemNotSet), SupportUnloadOfDelayLoadedDLL(unset), SuppressStartupBanner(unset), SwapRunFromCD(unset), SwapRunFromNet(unset), TargetMachine(machineNotSet), TerminalServerAware(termSvrAwareDefault), TreatWarningsAsErrors(unset), TurnOffAssemblyGeneration(unset), TypeLibraryResourceID(0), GenerateManifest(unset), EnableUAC(unset), UACUIAccess(unset), SectionAlignment(-1), PreventDllBinding(unset), AllowIsolation(unset), AssemblyDebug(unset), CLRUnmanagedCodeCheck(unset), DelaySign(unset), GenerateWindowsMetadata(unset) { } // Hashing routine to do fast option lookups ---- // Slightly rewritten to stop on ':' ',' and '\0' // Original routine in qtranslator.cpp ---------- static uint elfHash(const char* name) { const uchar *k; uint h = 0; uint g; if(name) { k = (const uchar *) name; while((*k) && (*k)!= ':' && (*k)!=',' && (*k)!=' ') { h = (h << 4) + *k++; if((g = (h & 0xf0000000)) != 0) h ^= g >> 24; h &= ~g; } } if(!h) h = 1; return h; } //#define USE_DISPLAY_HASH #ifdef USE_DISPLAY_HASH static void displayHash(const char* str) { printf("case 0x%07x: // %s\n break;\n", elfHash(str), str); } #endif bool VCLinkerTool::parseOption(const char* option) { #ifdef USE_DISPLAY_HASH // Main options displayHash("/ALIGN"); displayHash("/ALLOWBIND"); displayHash("/ASSEMBLYMODULE"); displayHash("/ASSEMBLYRESOURCE"); displayHash("/BASE"); displayHash("/DEBUG"); displayHash("/DEF"); displayHash("/DEFAULTLIB"); displayHash("/DELAY"); displayHash("/DELAYLOAD"); displayHash("/DLL"); displayHash("/DRIVER"); displayHash("/ENTRY"); displayHash("/EXETYPE"); displayHash("/EXPORT"); displayHash("/FIXED"); displayHash("/FORCE"); displayHash("/HEAP"); displayHash("/IDLOUT"); displayHash("/IGNORE"); displayHash("/IGNOREIDL"); displayHash("/IMPLIB"); displayHash("/INCLUDE"); displayHash("/INCREMENTAL"); displayHash("/LARGEADDRESSAWARE"); displayHash("/LIBPATH"); displayHash("/LTCG"); displayHash("/MACHINE"); displayHash("/MAP"); displayHash("/MAPINFO"); displayHash("/MERGE"); displayHash("/MIDL"); displayHash("/NOASSEMBLY"); displayHash("/NODEFAULTLIB"); displayHash("/NOENTRY"); displayHash("/NOLOGO"); displayHash("/OPT"); displayHash("/ORDER"); displayHash("/OUT"); displayHash("/PDB"); displayHash("/PDBSTRIPPED"); displayHash("/RELEASE"); displayHash("/SECTION"); displayHash("/STACK"); displayHash("/STUB"); displayHash("/SUBSYSTEM"); displayHash("/SWAPRUN"); displayHash("/TLBID"); displayHash("/TLBOUT"); displayHash("/TSAWARE"); displayHash("/VERBOSE"); displayHash("/VERSION"); displayHash("/VXD"); displayHash("/WS "); displayHash("/libpath"); displayHash("/WINMD"); displayHash("/WINMDFILE:"); #endif #ifdef USE_DISPLAY_HASH // Sub options displayHash("UNLOAD"); displayHash("NOBIND"); displayHash("no"); displayHash("NOSTATUS"); displayHash("STATUS"); displayHash("AM33"); displayHash("ARM"); displayHash("CEE"); displayHash("EBC"); displayHash("IA64"); displayHash("X86"); displayHash("X64"); displayHash("M32R"); displayHash("MIPS"); displayHash("MIPS16"); displayHash("MIPSFPU"); displayHash("MIPSFPU16"); displayHash("MIPSR41XX"); displayHash("PPC"); displayHash("SH3"); displayHash("SH3DSP"); displayHash("SH4"); displayHash("SH5"); displayHash("THUMB"); displayHash("TRICORE"); displayHash("EXPORTS"); displayHash("LINES"); displayHash("REF"); displayHash("NOREF"); displayHash("ICF"); displayHash("WIN98"); displayHash("NOWIN98"); displayHash("CONSOLE"); displayHash("EFI_APPLICATION"); displayHash("EFI_BOOT_SERVICE_DRIVER"); displayHash("EFI_ROM"); displayHash("EFI_RUNTIME_DRIVER"); displayHash("NATIVE"); displayHash("POSIX"); displayHash("WINDOWS"); displayHash("WINDOWSCE"); displayHash("NET"); displayHash("CD"); displayHash("NO"); #endif bool found = true; const uint optionHash = elfHash(option); if (config->CompilerVersion < NET2010) { switch (optionHash) { case 0x3360dbe: // /ALIGN[:number] case 0x1485c34: // /ALLOWBIND[:NO] case 0x33aec94: // /FIXED[:NO] case 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#] case 0x0348992: // /STUB:filename AdditionalOptions += option; return true; } } switch (optionHash) { case 0x6b21972: // /DEFAULTLIB:library case 0x396ea92: // /DRIVER[:UPONLY | :WDM] case 0xaca9d75: // /EXETYPE[:DYNAMIC | :DEV386] case 0x3ad5444: // /EXPORT:entryname[,@ordinal[,NONAME]][,DATA] case 0x33b4675: // /FORCE:[MULTIPLE|UNRESOLVED] case 0x3dc3455: // /IGNORE:number,number,number,number ### NOTE: This one is undocumented, but it is even used by Microsoft. // In recent versions of the Microsoft linker they have disabled this undocumented feature. case 0x0034bc4: // /VXD AdditionalOptions += option; break; case 0x3360dbe: // /ALIGN[:number] SectionAlignment = QString(option+7).toLongLong(); break; case 0x1485c34: // /ALLOWBIND[:NO] if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N')) PreventDllBinding = _False; else PreventDllBinding = _True; break; case 0x312011e: // /ALLOWISOLATION[:NO] if(*(option+15) == ':' && (*(option+16) == 'n' || *(option+16) == 'N')) AllowIsolation = _False; else AllowIsolation = _True; break; case 0x679c075: // /ASSEMBLYMODULE:filename AddModuleNamesToAssembly += option+15; break; case 0x75f35f7: // /ASSEMBLYDEBUG[:DISABLE] if(*(option+14) == ':' && (*(option+15) == 'D')) AssemblyDebug = _False; else AssemblyDebug = _True; break; case 0x43294a5: // /ASSEMBLYLINKRESOURCE:filename AssemblyLinkResource += option+22; break; case 0x062d065: // /ASSEMBLYRESOURCE:filename LinkToManagedResourceFile = option+18; break; case 0x0336675: // /BASE:{address | @filename,key} // Do we need to do a manual lookup when '@filename,key'? // Seems BaseAddress only can contain the location... // We don't use it in Qt, so keep it simple for now BaseAddress = option+6; break; case 0x63bf065: // /CLRIMAGETYPE:{IJW|PURE|SAFE} if(*(option+14) == 'I') CLRImageType = "ForceIJWImage"; else if(*(option+14) == 'P') CLRImageType = "ForcePureILImage"; else if(*(option+14) == 'S') CLRImageType = "ForceSafeILImage"; break; case 0x5f2a6a2: // /CLRSUPPORTLASTERROR{:NO | SYSTEMDLL} if(*(option+20) == ':') { if(*(option+21) == 'N') { CLRSupportLastError = "Disabled"; } else if(*(option+21) == 'S') { CLRSupportLastError = "SystemDlls"; } } else { CLRSupportLastError = "Enabled"; } break; case 0xc7984f5: // /CLRTHREADATTRIBUTE:{STA|MTA|NONE} if(*(option+20) == 'N') CLRThreadAttribute = "DefaultThreadingAttribute"; else if(*(option+20) == 'M') CLRThreadAttribute = "MTAThreadingAttribute"; else if(*(option+20) == 'S') CLRThreadAttribute = "STAThreadingAttribute"; break; case 0xa8c637b: // /CLRUNMANAGEDCODECHECK[:NO] if(*(option+23) == 'N') CLRUnmanagedCodeCheck = _False; else CLRUnmanagedCodeCheck = _True; break; case 0x62d9e94: // /MANIFEST[:NO] if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n'))) GenerateManifest = _False; else GenerateManifest = _True; break; case 0x34be314: // /WINMD[:NO] if ((*(option+6) == ':' && (*(option+7) == 'N' || *(option+7) == 'n'))) GenerateWindowsMetadata = _False; else GenerateWindowsMetadata = _True; break; case 0x31be7e5: // /WINMDFILE:filename WindowsMetadataFile = option+11; break; case 0x8b64559: // /MANIFESTDEPENDENCY:manifest_dependency AdditionalManifestDependencies += option+20; break; case 0xe9e8195: // /MANIFESTFILE:filename ManifestFile = option+14; break; case 0x9e9fb83: // /MANIFESTUAC http://msdn.microsoft.com/en-us/library/bb384691%28VS.100%29.aspx if ((*(option+12) == ':' && (*(option+13) == 'N' || *(option+13) == 'n'))) EnableUAC = _False; else if((*(option+12) == ':' && (*(option+13) == 'l' || *(option+14) == 'e'))) { // level if(*(option+20) == 'a') UACExecutionLevel = "AsInvoker"; else if(*(option+20) == 'h') UACExecutionLevel = "HighestAvailable"; else if(*(option+20) == 'r') UACExecutionLevel = "RequireAdministrator"; } else if((*(option+12) == ':' && (*(option+13) == 'u' || *(option+14) == 'i'))) { // uiAccess if(*(option+22) == 't') UACUIAccess = _True; else UACUIAccess = _False; } else if((*(option+12) == ':' && (*(option+13) == 'f' || *(option+14) == 'r'))) { // fragment AdditionalOptions += option; }else EnableUAC = _True; break; case 0x3389797: // /DEBUG[:{FASTLINK|FULL|NONE}] DebugInfoOption = linkerDebugOptionEnabled; if (config->CompilerVersion >= NET2015 && *(option + 6) == ':') { const char *str = option + 7; if (qstricmp(str, "fastlink") == 0) DebugInfoOption = linkerDebugOptionFastLink; else if (qstricmp(str, "full") == 0) DebugInfoOption = linkerDebugOptionFull; else if (qstricmp(str, "none") == 0) DebugInfoOption = linkerDebugOptionNone; else AdditionalOptions += option; } if (DebugInfoOption == linkerDebugOptionNone) GenerateDebugInformation = _False; else GenerateDebugInformation = _True; break; case 0x0033896: // /DEF:filename ModuleDefinitionFile = option+5; break; case 0x338a069: // /DELAY:{UNLOAD | NOBIND} // MS documentation does not specify what to do with // this option, so we'll put it in AdditionalOptions AdditionalOptions += option; break; case 0x06f4bf4: // /DELAYLOAD:dllname DelayLoadDLLs += option+11; break; case 0x06d451e: // /DELAYSIGN[:NO] if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N')) DelaySign = _False; else DelaySign = _True; break; case 0x003390c: // /DLL // This option is not used for vcproj files break; case 0x2ee8415: // /DYNAMICBASE[:NO] if(*(option+12) == ':' && (*(option+13) == 'n' || *(option+13) == 'N')) RandomizedBaseAddress = _False; else RandomizedBaseAddress = _True; break; case 0x33a3979: // /ENTRY:function EntryPointSymbol = option+7; break; case 0x4504334: // /ERRORREPORT:[ NONE | PROMPT | QUEUE | SEND ] if(*(option+12) == ':' ) { if(*(option+13) == 'N') LinkErrorReporting = "NoErrorReport"; else if(*(option+13) == 'P') LinkErrorReporting = "PromptImmediately"; else if(*(option+13) == 'Q') LinkErrorReporting = "QueueForNextLogin"; else if(*(option+13) == 'S') LinkErrorReporting = "SendErrorReport"; } break; case 0x033c960: // /HEAP:reserve[,commit] { QStringList both = QString(option+6).split(","); HeapReserveSize = both[0].toLongLong(); if(both.size() == 2) HeapCommitSize = both[1].toLongLong(); } break; case 0x3d91494: // /IDLOUT:[path\]filename MergedIDLBaseFileName = option+8; break; case 0x345a04c: // /IGNOREIDL IgnoreEmbeddedIDL = _True; break; case 0x3e250e2: // /IMPLIB:filename ImportLibrary = option+8; break; case 0xe281ab5: // /INCLUDE:symbol ForceSymbolReferences += option+9; break; case 0xb28103c: // /INCREMENTAL[:no] if(*(option+12) == ':' && (*(option+13) == 'n' || *(option+13) == 'N')) LinkIncremental = linkIncrementalNo; else LinkIncremental = linkIncrementalYes; break; case 0x07f1ab2: // /KEYCONTAINER:name KeyContainer = option+14; break; case 0xfadaf35: // /KEYFILE:filename KeyFile = option+9; break; case 0x26e4675: // /LARGEADDRESSAWARE[:no] if(*(option+18) == ':' && *(option+19) == 'n') LargeAddressAware = addrAwareNoLarge; else LargeAddressAware = addrAwareLarge; break; case 0x2f96bc8: // /libpath:dir case 0x0d745c8: // /LIBPATH:dir AdditionalLibraryDirectories += option+9; break; case 0x0341877: // /LTCG[:{INCREMENTAL|NOSTATUS|STATUS|OFF}] // /LTCG:{PGINSTRUMENT|PGOPTIMIZE|PGUPDATE} LinkTimeCodeGeneration = optLTCGEnabled; if (*(option + 5) == ':') { const char* str = option + 6; if (qstricmp(str, "status") == 0) ShowProgress = linkProgressAll; else if (qstricmp(str, "off") == 0) LinkTimeCodeGeneration = optLTCGDefault; else if (qstricmp(str, "incremental") == 0) LinkTimeCodeGeneration = optLTCGIncremental; else if (qstricmp(str, "pginstrument") == 0) LinkTimeCodeGeneration = optLTCGInstrument; else if (qstricmp(str, "pgoptimize") == 0) LinkTimeCodeGeneration = optLTCGOptimize; else if (qstricmp(str, "pgupdate") == 0) LinkTimeCodeGeneration = optLTCGUpdate; else AdditionalOptions.append(option); } if (LinkTimeCodeGeneration != optLTCGDefault) config->WholeProgramOptimization = _True; break; case 0x379ED25: case 0x157cf65: // /MACHINE:{AM33|ARM|CEE|IA64|X86|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|PPC|SH3|SH4|SH5|THUMB|TRICORE} switch (elfHash(option+9)) { // Very limited documentation on all options but X86, case 0x0005bb6: // X86 TargetMachine = machineX86; break; case 0x0005b94: // X64 TargetMachine = machineX64; break; // so we put the others in AdditionalOptions... case 0x0046063: // AM33 case 0x000466d: // ARM case 0x0004795: // CEE case 0x0004963: // EBC case 0x004d494: // IA64 case 0x0050672: // M32R case 0x0051e53: // MIPS case 0x51e5646: // MIPS16 case 0x1e57b05: // MIPSFPU case 0x57b09a6: // MIPSFPU16 case 0x5852738: // MIPSR41XX case 0x0005543: // PPC case 0x00057b3: // SH3 case 0x57b7980: // SH3DSP case 0x00057b4: // SH4 case 0x00057b5: // SH5 case 0x058da12: // THUMB case 0x96d8435: // TRICORE default: AdditionalOptions += option; break; } break; case 0x0034160: // /MAP[:filename] GenerateMapFile = _True; if (option[4] == ':') MapFileName = option+5; break; case 0x164e1ef: // /MAPINFO:{EXPORTS|LINES} if(*(option+9) == 'E') MapExports = _True; else if(*(option+9) == 'L') MapLines = _True; break; case 0x341a6b5: // /MERGE:from=to if (MergeSections.isEmpty()) { MergeSections = option+7; } else { // vcxproj files / the VS property editor do not support multiple MergeSections entries. // Add them as additional options. AdditionalOptions += option; } break; case 0x0341d8c: // /MIDL:@file MidlCommandFile = option+7; break; case 0x84e2679: // /NOASSEMBLY TurnOffAssemblyGeneration = _True; break; case 0x2b21942: // /NODEFAULTLIB[:library] if(*(option+13) == '\0') IgnoreAllDefaultLibraries = _True; else IgnoreDefaultLibraryNames += option+14; break; case 0x33a3a39: // /NOENTRY ResourceOnlyDLL = _True; break; case 0x434138f: // /NOLOGO SuppressStartupBanner = _True; break; case 0xc841054: // /NXCOMPAT[:NO] if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n'))) DataExecutionPrevention = _False; else DataExecutionPrevention = _True; break; case 0x0034454: // /OPT:{REF | NOREF | ICF[=iterations] | NOICF | WIN98 | NOWIN98} { char third = *(option+7); switch (third) { case 'F': // REF if(*(option+5) == 'R') { OptimizeReferences = optReferences; } else { // ICF[=iterations] EnableCOMDATFolding = optFolding; // [=iterations] case is not documented } break; case 'R': // NOREF OptimizeReferences = optNoReferences; break; case 'I': // NOICF EnableCOMDATFolding = optNoFolding; break; case 'N': // WIN98 OptimizeForWindows98 = optWin98Yes; break; case 'W': // NOWIN98 OptimizeForWindows98 = optWin98No; break; default: found = false; } } break; case 0x34468a2: // /ORDER:@filename FunctionOrder = option+8; break; case 0x00344a4: // /OUT:filename OutputFile = option+5; break; case 0x0034482: // /PDB:filename ProgramDatabaseFile = option+5; break; case 0xa2ad314: // /PDBSTRIPPED:pdb_file_name StripPrivateSymbols = option+13; break; case 0x6a09535: // /RELEASE SetChecksum = _True; break; case 0x348857b: // /STACK:reserve[,commit] { QStringList both = QString(option+7).split(","); StackReserveSize = both[0].toLongLong(); if(both.size() == 2) StackCommitSize = both[1].toLongLong(); } break; case 0x75AA4D8: // /SAFESEH:{NO} if (config->CompilerVersion >= NET2010) ImageHasSafeExceptionHandlers = (option[8] == ':') ? _False : _True; else AdditionalOptions += option; break; case 0x9B3C00D: case 0x78dc00d: // /SUBSYSTEM:{CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|WINDOWSCE}[,major[.minor]] { // Split up in subsystem, and version number QStringList both = QString(option+11).split(","); switch (elfHash(both[0].toLatin1().constData())) { case 0x8438445: // CONSOLE SubSystem = subSystemConsole; break; case 0xbe29493: // WINDOWS SubSystem = subSystemWindows; break; // The following are undocumented, so add them to AdditionalOptions case 0x240949e: // EFI_APPLICATION case 0xe617652: // EFI_BOOT_SERVICE_DRIVER case 0x9af477d: // EFI_ROM case 0xd34df42: // EFI_RUNTIME_DRIVER case 0x5268ea5: // NATIVE case 0x05547e8: // POSIX case 0x2949c95: // WINDOWSCE case 0x4B69795: // windowsce AdditionalOptions += option; break; default: found = false; } } break; case 0x8b654de: // /SWAPRUN:{NET | CD} if(*(option+9) == 'N') SwapRunFromNet = _True; else if(*(option+9) == 'C') SwapRunFromCD = _True; else found = false; break; case 0x34906d4: // /TLBID:id TypeLibraryResourceID = QString(option+7).toLongLong(); break; case 0x4907494: // /TLBOUT:[path\]filename TypeLibraryFile = option+8; break; case 0x976b525: // /TSAWARE[:NO] if(*(option+8) == ':') TerminalServerAware = termSvrAwareNo; else TerminalServerAware = termSvrAwareYes; break; case 0xaa67735: // /VERBOSE[:lib] if(*(option+9) == ':') { ShowProgress = linkProgressLibs; AdditionalOptions += option; } else { ShowProgress = linkProgressAll; } break; case 0xaa77f7e: // /VERSION:major[.minor] Version = option+9; break; case 0x0034c50: // /WS[:NO] if (config->CompilerVersion >= NET2010) { if(*(option+3) == ':') TreatWarningsAsErrors = _False; else TreatWarningsAsErrors = _True; } else { AdditionalOptions += option; } break; default: AdditionalOptions += option; break; } if(!found) { if (!config->suppressUnknownOptionWarnings) unknownOptionWarning("Linker", option); AdditionalOptions += option; } return found; } // VCManifestTool --------------------------------------------------- VCManifestTool::VCManifestTool() : EmbedManifest(unset) { } bool VCManifestTool::parseOption(const char *option) { Q_UNUSED(option); // ### implement if we introduce QMAKE_MT_FLAGS return false; } // VCMIDLTool ------------------------------------------------------- VCMIDLTool::VCMIDLTool() : DefaultCharType(midlCharUnsigned), EnableErrorChecks(midlDisableAll), ErrorCheckAllocations(unset), ErrorCheckBounds(unset), ErrorCheckEnumRange(unset), ErrorCheckRefPointers(unset), ErrorCheckStubData(unset), GenerateStublessProxies(unset), GenerateTypeLibrary(unset), IgnoreStandardIncludePath(unset), MkTypLibCompatible(unset), StructMemberAlignment(midlAlignNotSet), SuppressStartupBanner(unset), TargetEnvironment(midlTargetNotSet), ValidateParameters(unset), WarnAsError(unset), WarningLevel(midlWarningLevel_0), ApplicationConfigurationMode(unset), ValidateAllParameters(unset), SuppressCompilerWarnings(unset), LocaleID(-1) { } bool VCMIDLTool::parseOption(const char* option) { #ifdef USE_DISPLAY_HASH displayHash("/D name[=def]"); displayHash("/I directory-list"); displayHash("/Oi"); displayHash("/Oic"); displayHash("/Oicf"); displayHash("/Oif"); displayHash("/Os"); displayHash("/U name"); displayHash("/WX"); displayHash("/W{0|1|2|3|4}"); displayHash("/Zp {N}"); displayHash("/Zs"); displayHash("/acf filename"); displayHash("/align {N}"); displayHash("/app_config"); displayHash("/c_ext"); displayHash("/char ascii7"); displayHash("/char signed"); displayHash("/char unsigned"); displayHash("/client none"); displayHash("/client stub"); displayHash("/confirm"); displayHash("/cpp_cmd cmd_line"); displayHash("/cpp_opt options"); displayHash("/cstub filename"); displayHash("/dlldata filename"); displayHash("/env win32"); displayHash("/env win64"); displayHash("/error all"); displayHash("/error allocation"); displayHash("/error bounds_check"); displayHash("/error enum"); displayHash("/error none"); displayHash("/error ref"); displayHash("/error stub_data"); displayHash("/h filename"); displayHash("/header filename"); displayHash("/iid filename"); displayHash("/lcid"); displayHash("/mktyplib203"); displayHash("/ms_ext"); displayHash("/ms_union"); displayHash("/msc_ver "); displayHash("/newtlb"); displayHash("/no_cpp"); displayHash("/no_def_idir"); displayHash("/no_default_epv"); displayHash("/no_format_opt"); displayHash("/no_warn"); displayHash("/nocpp"); displayHash("/nologo"); displayHash("/notlb"); displayHash("/o filename"); displayHash("/oldnames"); displayHash("/oldtlb"); displayHash("/osf"); displayHash("/out directory"); displayHash("/pack {N}"); displayHash("/prefix all"); displayHash("/prefix client"); displayHash("/prefix server"); displayHash("/prefix switch"); displayHash("/protocol all"); displayHash("/protocol dce"); displayHash("/protocol ndr64"); displayHash("/proxy filename"); displayHash("/robust"); displayHash("/rpcss"); displayHash("/savePP"); displayHash("/server none"); displayHash("/server stub"); displayHash("/sstub filename"); displayHash("/syntax_check"); displayHash("/target {system}"); displayHash("/tlb filename"); displayHash("/use_epv"); displayHash("/win32"); displayHash("/win64"); #endif bool found = true; int offset = 0; const uint optionHash = elfHash(option); if (config->CompilerVersion < NET2010) { switch (optionHash) { case 0x5b1cb97: // /app_config case 0x5a2fc64: // /client {none|stub} case 0x35aabb2: // /cstub filename case 0x64ceb12: // /newtlb case 0x556dbee: // /no_warn case 0x662bb12: // /oldtlb case 0x69c9cf2: // /server {none|stub} case 0x36aabb2: // /sstub filename AdditionalOptions += option; return true; } } switch(optionHash) { case 0x0000334: // /D name[=def] PreprocessorDefinitions += option+3; break; case 0x0000339: // /I directory-list AdditionalIncludeDirectories += option+3; break; case 0x0345f96: // /Oicf case 0x00345f6: // /Oif GenerateStublessProxies = _True; break; case 0x0000345: // /U name UndefinePreprocessorDefinitions += option+3; break; case 0x00034c8: // /WX WarnAsError = _True; break; case 0x3582fde: // /align {N} offset = 3; Q_FALLTHROUGH(); case 0x0003510: // /Zp {N} switch (*(option+offset+4)) { case '1': StructMemberAlignment = (*(option+offset+5) == '\0') ? midlAlignSingleByte : midlAlignSixteenBytes; break; case '2': StructMemberAlignment = midlAlignTwoBytes; break; case '4': StructMemberAlignment = midlAlignFourBytes; break; case '8': StructMemberAlignment = midlAlignEightBytes; break; default: found = false; } break; case 0x5b1cb97: // /app_config ApplicationConfigurationMode = _True; break; case 0x0359e82: // /char {ascii7|signed|unsigned} switch(*(option+6)) { case 'a': DefaultCharType = midlCharAscii7; break; case 's': DefaultCharType = midlCharSigned; break; case 'u': DefaultCharType = midlCharUnsigned; break; default: found = false; } break; case 0x5a2fc64: // /client {none|stub} if(*(option+8) == 's') GenerateClientFiles = "Stub"; else GenerateClientFiles = "None"; break; case 0xa766524: // /cpp_opt options CPreprocessOptions += option+9; break; case 0x35aabb2: // /cstub filename ClientStubFile = option+7; break; case 0xb32abf1: // /dlldata filename DLLDataFileName = option + 9; break; case 0x0035c56: // /env {win32|win64} TargetEnvironment = (*(option+8) == '6') ? midlTargetWin64 : midlTargetWin32; break; case 0x35c9962: // /error {all|allocation|bounds_check|enum|none|ref|stub_data} EnableErrorChecks = midlEnableCustom; switch (*(option+7)) { case 'a': if(*(option+10) == '\0') EnableErrorChecks = midlEnableAll; else ErrorCheckAllocations = _True; break; case 'b': ErrorCheckBounds = _True; break; case 'e': ErrorCheckEnumRange = _True; break; case 'n': EnableErrorChecks = midlDisableAll; break; case 'r': ErrorCheckRefPointers = _True; break; case 's': ErrorCheckStubData = _True; break; default: found = false; } break; case 0x5eb7af2: // /header filename offset = 5; Q_FALLTHROUGH(); case 0x0000358: // /h filename HeaderFileName = option + offset + 3; break; case 0x0035ff4: // /iid filename InterfaceIdentifierFileName = option+5; break; case 0x64b7933: // /mktyplib203 MkTypLibCompatible = _True; break; case 0x64ceb12: // /newtlb TypeLibFormat = "NewFormat"; break; case 0x8e0b0a2: // /no_def_idir IgnoreStandardIncludePath = _True; break; case 0x65635ef: // /nologo SuppressStartupBanner = _True; break; case 0x695e9f4: // /no_robust ValidateAllParameters = _False; break; case 0x3656b22: // /notlb GenerateTypeLibrary = _True; break; case 0x556dbee: // /no_warn SuppressCompilerWarnings = _True; break; case 0x000035f: // /o filename RedirectOutputAndErrors = option+3; break; case 0x662bb12: // /oldtlb TypeLibFormat = "OldFormat"; break; case 0x00366c4: // /out directory OutputDirectory = option+5; break; case 0x36796f9: // /proxy filename ProxyFileName = option+7; break; case 0x6959c94: // /robust ValidateParameters = _True; break; case 0x6a88df4: // /target {system} if(*(option+11) == '6') TargetEnvironment = midlTargetWin64; else TargetEnvironment = midlTargetWin32; break; case 0x69c9cf2: // /server {none|stub} if(*(option+8) == 's') GenerateServerFiles = "Stub"; else GenerateServerFiles = "None"; break; case 0x36aabb2: // /sstub filename ServerStubFile = option+7; break; case 0x0036b22: // /tlb filename TypeLibraryName = option+5; break; case 0x36e0162: // /win32 TargetEnvironment = midlTargetWin32; break; case 0x36e0194: // /win64 TargetEnvironment = midlTargetWin64; break; case 0x0003459: // /Oi case 0x00345f3: // /Oic case 0x0003463: // /Os case 0x0003513: // /Zs case 0x0035796: // /acf filename case 0x3595cf4: // /c_ext case 0xa64d3dd: // /confirm case 0xa765b64: // /cpp_cmd cmd_line case 0x03629f4: // /lcid case 0x6495cc4: // /ms_ext case 0x96c7a1e: // /ms_union case 0x4996fa2: // /msc_ver case 0x6555a40: // /no_cpp case 0xf64d6a6: // /no_default_epv case 0x6dd9384: // /no_format_opt case 0x3655a70: // /nocpp case 0x2b455a3: // /oldnames case 0x0036696: // /osf case 0x036679b: // /pack {N} case 0x678bd38: // /prefix {all|client|server|switch} case 0x96b702c: // /protocol {all|dce|ndr64} case 0x3696aa3: // /rpcss case 0x698ca60: // /savePP case 0xce9b12b: // /syntax_check case 0xc9b5f16: // /use_epv AdditionalOptions += option; break; default: // /W{0|1|2|3|4} case if(*(option+1) == 'W') { switch (*(option+2)) { case '0': WarningLevel = midlWarningLevel_0; break; case '1': WarningLevel = midlWarningLevel_1; break; case '2': WarningLevel = midlWarningLevel_2; break; case '3': WarningLevel = midlWarningLevel_3; break; case '4': WarningLevel = midlWarningLevel_4; break; default: found = false; } } break; } if(!found) warn_msg(WarnLogic, "Could not parse MIDL option: %s", option); return true; } // VCLibrarianTool -------------------------------------------------- VCLibrarianTool::VCLibrarianTool() : IgnoreAllDefaultLibraries(unset), SuppressStartupBanner(_True) { } // VCCustomBuildTool ------------------------------------------------ VCCustomBuildTool::VCCustomBuildTool() { ToolName = "VCCustomBuildTool"; } // VCResourceCompilerTool ------------------------------------------- VCResourceCompilerTool::VCResourceCompilerTool() : Culture(rcUseDefault), IgnoreStandardIncludePath(unset), ShowProgress(linkProgressNotSet), SuppressStartupBanner(unset) { } // VCDeploymentTool -------------------------------------------- VCDeploymentTool::VCDeploymentTool() : RegisterOutput(registerNo) { DeploymentTag = "DeploymentTool"; RemoteDirectory = ""; } VCEventTool::VCEventTool(const QString &eventName) : ExcludedFromBuild(unset) { EventName = eventName; ToolName = "VC"; ToolName += eventName; ToolName += "Tool"; } // VCPostBuildEventTool --------------------------------------------- VCPostBuildEventTool::VCPostBuildEventTool() : VCEventTool("PostBuildEvent") { } // VCPreBuildEventTool ---------------------------------------------- VCPreBuildEventTool::VCPreBuildEventTool() : VCEventTool("PreBuildEvent") { } // VCPreLinkEventTool ----------------------------------------------- VCPreLinkEventTool::VCPreLinkEventTool() : VCEventTool("PreLinkEvent") { } // VCConfiguration -------------------------------------------------- VCConfiguration::VCConfiguration() : ATLMinimizesCRunTimeLibraryUsage(unset), BuildBrowserInformation(unset), CharacterSet(charSetNotSet), ConfigurationType(typeApplication), RegisterOutput(unset), UseOfATL(useATLNotSet), UseOfMfc(useMfcStdWin), WholeProgramOptimization(unset) { compiler.config = this; linker.config = this; idl.config = this; } // VCFilter --------------------------------------------------------- VCFilter::VCFilter() : ParseFiles(unset), Config(nullptr) { useCustomBuildTool = false; useCompilerTool = false; } void VCFilter::addFile(const QString& filename) { Files += VCFilterFile(filename); } void VCFilter::addFile(const VCFilterFile& fileInfo) { Files += VCFilterFile(fileInfo); } void VCFilter::addFiles(const QStringList& fileList) { for (int i = 0; i < fileList.size(); ++i) addFile(fileList.at(i)); } void VCFilter::addFiles(const ProStringList& fileList) { for (int i = 0; i < fileList.size(); ++i) addFile(fileList.at(i).toQString()); } void VCFilter::modifyPCHstage(QString str) { const bool isHFile = (str == Project->precompH); const bool pchThroughSourceFile = !Project->precompSource.isEmpty(); if (isHFile && pchThroughSourceFile && Project->autogenPrecompSource) { useCustomBuildTool = true; QString toFile(Project->precompSource); CustomBuildTool.Description = "Generating precompiled header source file '" + toFile + "' ..."; CustomBuildTool.Outputs += toFile; QStringList lines; CustomBuildTool.CommandLine += "echo /*-------------------------------------------------------------------- >" + toFile; lines << "* Precompiled header source file used by Visual Studio.NET to generate"; lines << "* the .pch file."; lines << "*"; lines << "* Due to issues with the dependencies checker within the IDE, it"; lines << "* sometimes fails to recompile the PCH file, if we force the IDE to"; lines << "* create the PCH file directly from the header file."; lines << "*"; lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was"; lines << "* specified, and is used as the common stdafx.cpp. The file is only"; lines << QLatin1String("* generated when creating ") + (Config->CompilerVersion < NET2010 ? ".vcproj" : ".vcxproj") + " project files, and is not used for"; lines << "* command line compilations by nmake."; lines << "*"; lines << "* WARNING: All changes made in this file will be lost."; lines << "--------------------------------------------------------------------*/"; lines << "#include \"" + Project->precompHFilename + "\""; for (const QString &line : std::as_const(lines)) CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile; return; } useCompilerTool = true; const bool isPrecompSource = pchThroughSourceFile && (str == Project->precompSource); if (isPrecompSource) { CompilerTool.UsePrecompiledHeader = pchCreateUsingSpecific; if (Project->autogenPrecompSource) CompilerTool.PrecompiledHeaderThrough = Project->precompHFilename; CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)"); return; } bool isCFile = false; for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) { if (str.endsWith(*it)) { isCFile = true; break; } } bool pchCompatible = (isCFile == Project->pchIsCFile); if (!pchCompatible) { CompilerTool.UsePrecompiledHeader = pchNone; CompilerTool.PrecompiledHeaderThrough = QLatin1String("$(NOINHERIT)"); CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)"); } } VCFilterFile VCFilter::findFile(const QString &filePath, bool *found) const { for (int i = 0; i < Files.size(); ++i) { const VCFilterFile &f = Files.at(i); if (f.file == filePath) { *found = true; return f; } } *found = false; return VCFilterFile(); } bool VCFilter::addExtraCompiler(const VCFilterFile &info) { const QStringList &extraCompilers = Project->extraCompilerSources.value(info.file); if (extraCompilers.isEmpty()) return false; QString inFile = info.file; // is the extracompiler rule on a file with a built in compiler? const QString objectMappedFile = Project->extraCompilerOutputs.value(inFile); bool hasBuiltIn = false; if (!objectMappedFile.isEmpty()) { hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile); // Remove the fake file suffix we've added initially to generate correct command lines. inFile.chop(Project->customBuildToolFilterFileSuffix.size()); // qDebug("*** Extra compiler file has object mapped file '%s' => '%s'", qPrintable(inFile), qPrintable(objectMappedFile.join(' '))); } CustomBuildTool.AdditionalDependencies.clear(); CustomBuildTool.CommandLine.clear(); CustomBuildTool.Description.clear(); CustomBuildTool.Outputs.clear(); CustomBuildTool.ToolPath.clear(); CustomBuildTool.ToolName = QLatin1String(_VCCustomBuildTool); for (int x = 0; x < extraCompilers.size(); ++x) { const QString &extraCompilerName = extraCompilers.at(x); if (!Project->verifyExtraCompiler(extraCompilerName, inFile) && !hasBuiltIn) continue; // All information about the extra compiler QString tmp_out = Project->project->first(ProKey(extraCompilerName + ".output")).toQString(); QString tmp_cmd = Project->project->values(ProKey(extraCompilerName + ".commands")).join(' '); QString tmp_cmd_name = Project->project->values(ProKey(extraCompilerName + ".name")).join(' '); QStringList tmp_dep = Project->project->values(ProKey(extraCompilerName + ".depends")).toQStringList(); QString tmp_dep_cmd = Project->project->values(ProKey(extraCompilerName + ".depend_command")).join(' '); const ProStringList &configs = Project->project->values(ProKey(extraCompilerName + ".CONFIG")); bool combined = configs.indexOf("combine") != -1; QString cmd, cmd_name, out; QStringList deps, inputs; // Variabel replacement of output name out = Option::fixPathToTargetOS(Project->replaceExtraCompilerVariables( tmp_out, inFile, QString(), MakefileGenerator::NoShell), false); // If file has built-in compiler, we've swapped the input and output of // the command, as we in Visual Studio cannot have a Custom Buildstep on // a file which uses a built-in compiler. We would in this case only get // the result from the extra compiler. If 'hasBuiltIn' is true, we know // that we're actually on the _output_file_ of the result, and we // therefore swap inFile and out below, since the extra-compiler still // must see it as the original way. If the result also has a built-in // compiler, too bad.. if (hasBuiltIn) { out = inFile; inFile = objectMappedFile; } // Dependency for the output if (!tmp_dep.isEmpty()) deps = tmp_dep; if (!tmp_dep_cmd.isEmpty()) { Project->callExtraCompilerDependCommand(extraCompilerName, tmp_dep_cmd, inFile, out, true, // dep_lines &deps, configs.contains("dep_existing_only"), true /* checkCommandAvailability */); } for (int i = 0; i < deps.size(); ++i) deps[i] = Option::fixPathToTargetOS( Project->replaceExtraCompilerVariables( deps.at(i), inFile, out, MakefileGenerator::NoShell), false); // Command for file if (combined) { // Add dependencies for each file const ProStringList &tmp_in = Project->project->values(ProKey(extraCompilerName + ".input")); for (int a = 0; a < tmp_in.size(); ++a) { const ProStringList &files = Project->project->values(tmp_in.at(a).toKey()); for (int b = 0; b < files.size(); ++b) { QString file = files.at(b).toQString(); deps += Project->findDependencies(file); inputs += Option::fixPathToTargetOS(file, false); } } deps = inputs + deps; // input files themselves too.. // Replace variables for command w/all input files cmd = Project->replaceExtraCompilerVariables(tmp_cmd, inputs, QStringList(out), MakefileGenerator::TargetShell); } else { deps.prepend(inFile); // input file itself too.. cmd = Project->replaceExtraCompilerVariables(tmp_cmd, inFile, out, MakefileGenerator::TargetShell); } // Name for command if (!tmp_cmd_name.isEmpty()) { cmd_name = Project->replaceExtraCompilerVariables( tmp_cmd_name, inFile, out, MakefileGenerator::NoShell); } else { int space = cmd.indexOf(' '); if (space != -1) cmd_name = cmd.left(space); else cmd_name = cmd; cmd_name = cmd_name.trimmed(); } // Fixify paths for (int i = 0; i < deps.size(); ++i) deps[i] = Option::fixPathToTargetOS(deps[i], false); // Output in info.additionalFile ----------- if (!CustomBuildTool.Description.isEmpty()) CustomBuildTool.Description += ", "; CustomBuildTool.Description += cmd_name; CustomBuildTool.CommandLine += VCToolBase::fixCommandLine(cmd.trimmed()); int space = cmd.indexOf(' '); QFileInfo finf(cmd.left(space)); if (CustomBuildTool.ToolPath.isEmpty()) CustomBuildTool.ToolPath += Option::fixPathToTargetOS(finf.path()); CustomBuildTool.Outputs += out; deps += CustomBuildTool.AdditionalDependencies; // Make sure that all deps are only once QStringList uniqDeps; for (int c = 0; c < deps.size(); ++c) { QString aDep = deps.at(c); if (!aDep.isEmpty()) uniqDeps << aDep; } uniqDeps.removeDuplicates(); CustomBuildTool.AdditionalDependencies = uniqDeps; } // Ensure that none of the output files are also dependencies. Or else, the custom buildstep // will be rebuild every time, even if nothing has changed. for (const QString &output : std::as_const(CustomBuildTool.Outputs)) CustomBuildTool.AdditionalDependencies.removeAll(output); useCustomBuildTool = !CustomBuildTool.CommandLine.isEmpty(); return useCustomBuildTool; } // VCProjectSingleConfig -------------------------------------------- const VCFilter &VCProjectSingleConfig::filterByName(const QString &name) const { if (name == "Root Files") return RootFiles; if (name == "Source Files") return SourceFiles; if (name == "Header Files") return HeaderFiles; if (name == "Generated Files") return GeneratedFiles; if (name == "LexYacc Files") return LexYaccFiles; if (name == "Translation Files") return TranslationFiles; if (name == "Form Files") return FormFiles; if (name == "Resource Files") return ResourceFiles; if (name == "Deployment Files") return DeploymentFiles; if (name == "Distribution Files") return DistributionFiles; return filterForExtraCompiler(name); } const VCFilter &VCProjectSingleConfig::filterForExtraCompiler(const QString &compilerName) const { for (int i = 0; i < ExtraCompilersFiles.size(); ++i) if (ExtraCompilersFiles.at(i).Name == compilerName) return ExtraCompilersFiles.at(i); static VCFilter nullFilter; return nullFilter; } // Tree file generation --------------------------------------------- void TreeNode::generateXML(XmlOutput &xml, const QString &tagName, VCProject &tool, const QString &filter) { if (children.size()) { // Filter ChildrenMap::ConstIterator it, end = children.constEnd(); if (!tagName.isEmpty()) { xml << tag("Filter") << attr("Name", tagName) << attr("Filter", ""); } // First round, do nested filters for (it = children.constBegin(); it != end; ++it) if ((*it)->children.size()) (*it)->generateXML(xml, it.key(), tool, filter); // Second round, do leafs for (it = children.constBegin(); it != end; ++it) if (!(*it)->children.size()) (*it)->generateXML(xml, it.key(), tool, filter); if (!tagName.isEmpty()) xml << closetag("Filter"); } else { // Leaf VCProjectWriter::outputFileConfigs(tool, xml, info, filter); } } // Flat file generation --------------------------------------------- void FlatNode::generateXML(XmlOutput &xml, const QString &/*tagName*/, VCProject &tool, const QString &filter) { if (children.size()) { ChildrenMapFlat::ConstIterator it = children.constBegin(); ChildrenMapFlat::ConstIterator end = children.constEnd(); for (; it != end; ++it) { VCProjectWriter::outputFileConfigs(tool, xml, (*it), filter); } } } void VCProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool) { xml << decl("1.0", "Windows-1252") << tag(_VisualStudioProject) << attrS(_ProjectType, "Visual C++") << attrS(_Version, tool.Version) << attrS(_Name, tool.Name) << attrS(_ProjectGUID, tool.ProjectGUID) << attrS(_Keyword, tool.Keyword) << attrS(_SccProjectName, tool.SccProjectName) << attrS(_SccLocalPath, tool.SccLocalPath) << tag(_Platforms) << tag(_Platform) << attrS(_Name, tool.PlatformName) << closetag(_Platforms) << tag(_Configurations); write(xml, tool.Configuration); xml << closetag(_Configurations) << tag(q_Files); // Add this configuration into a multi-config project, since that's where we have the flat/tree // XML output functionality VCProject tempProj; tempProj.SingleProjects += tool; outputFilter(tempProj, xml, "Source Files"); outputFilter(tempProj, xml, "Header Files"); outputFilter(tempProj, xml, "Generated Files"); outputFilter(tempProj, xml, "LexYacc Files"); outputFilter(tempProj, xml, "Translation Files"); outputFilter(tempProj, xml, "Form Files"); outputFilter(tempProj, xml, "Resource Files"); outputFilter(tempProj, xml, "Deployment Files"); outputFilter(tempProj, xml, "Distribution Files"); QSet extraCompilersInProject; for (int i = 0; i < tool.ExtraCompilersFiles.size(); ++i) { const QString &compilerName = tool.ExtraCompilersFiles.at(i).Name; if (!extraCompilersInProject.contains(compilerName)) { extraCompilersInProject += compilerName; tempProj.ExtraCompilers += compilerName; } } for (int x = 0; x < tempProj.ExtraCompilers.size(); ++x) { outputFilter(tempProj, xml, tempProj.ExtraCompilers.at(x)); } outputFilter(tempProj, xml, "Root Files"); xml << closetag(q_Files) << tag(_Globals) << data(); // No "/>" end tag } void VCProjectWriter::write(XmlOutput &xml, VCProject &tool) { if (tool.SingleProjects.size() == 0) { warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output"); return; } xml << decl("1.0", "Windows-1252") << tag(_VisualStudioProject) << attrS(_ProjectType, "Visual C++") << attrS(_Version, tool.Version) << attrS(_Name, tool.Name) << attrS(_ProjectGUID, tool.ProjectGUID) << attrS(_Keyword, tool.Keyword) << attrS(_SccProjectName, tool.SccProjectName) << attrS(_SccLocalPath, tool.SccLocalPath) << tag(_Platforms) << tag(_Platform) << attrS(_Name, tool.PlatformName) << closetag(_Platforms) << tag(_Configurations); // Output each configuration for (int i = 0; i < tool.SingleProjects.size(); ++i) write(xml, tool.SingleProjects.at(i).Configuration); xml << closetag(_Configurations) << tag(q_Files); outputFilter(tool, xml, "Source Files"); outputFilter(tool, xml, "Header Files"); outputFilter(tool, xml, "Generated Files"); outputFilter(tool, xml, "LexYacc Files"); outputFilter(tool, xml, "Translation Files"); outputFilter(tool, xml, "Form Files"); outputFilter(tool, xml, "Resource Files"); outputFilter(tool, xml, "Deployment Files"); outputFilter(tool, xml, "Distribution Files"); for (int x = 0; x < tool.ExtraCompilers.size(); ++x) { outputFilter(tool, xml, tool.ExtraCompilers.at(x)); } outputFilter(tool, xml, "Root Files"); xml << closetag(q_Files) << tag(_Globals) << data(); // No "/>" end tag } void VCProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool) { xml << tag(_Tool) << attrS(_Name, _VCCLCompilerTool) << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories) << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories) << attrS(_AssemblerListingLocation, tool.AssemblerListingLocation) << attrE(_AssemblerOutput, tool.AssemblerOutput, /*ifNot*/ asmListingNone) << attrE(_BasicRuntimeChecks, tool.BasicRuntimeChecks, /*ifNot*/ runtimeBasicCheckNone) << attrE(_BrowseInformation, tool.BrowseInformation, /*ifNot*/ brInfoNone) << attrS(_BrowseInformationFile, tool.BrowseInformationFile) << attrT(_BufferSecurityCheck, tool.BufferSecurityCheck) << attrE(_CallingConvention, tool.CallingConvention, /*ifNot*/ callConventionDefault) << attrE(_CompileAs, tool.CompileAs, compileAsDefault) << attrE(_CompileAsManaged, tool.CompileAsManaged, /*ifNot*/ managedDefault) << attrT(_CompileOnly, tool.CompileOnly) << attrE(_DebugInformationFormat, tool.DebugInformationFormat, /*ifNot*/ debugUnknown) << attrT(_Detect64BitPortabilityProblems, tool.Detect64BitPortabilityProblems) << attrT(_DisableLanguageExtensions, tool.DisableLanguageExtensions) << attrX(_DisableSpecificWarnings, tool.DisableSpecificWarnings) << attrE(_EnableEnhancedInstructionSet, tool.EnableEnhancedInstructionSet, /*ifnot*/ archNotSet) << attrT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations) << attrT(_EnableFunctionLevelLinking, tool.EnableFunctionLevelLinking) << attrT(_EnableIntrinsicFunctions, tool.EnableIntrinsicFunctions) << xformExceptionHandlingNET2005(tool.ExceptionHandling, tool.config->CompilerVersion) << attrT(_ExpandAttributedSource, tool.ExpandAttributedSource) << attrE(_FavorSizeOrSpeed, tool.FavorSizeOrSpeed, /*ifNot*/ favorNone) << attrE(_FloatingPointModel, tool.FloatingPointModel, /*ifNot*/ floatingPointNotSet) << attrT(_FloatingPointExceptions, tool.FloatingPointExceptions) << attrT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope) << attrX(_ForcedIncludeFiles, tool.ForcedIncludeFiles) << attrX(_ForcedUsingFiles, tool.ForcedUsingFiles) << attrE(_GeneratePreprocessedFile, tool.GeneratePreprocessedFile, /*ifNot*/ preprocessUnknown) << attrT(_GlobalOptimizations, tool.GlobalOptimizations) << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) << attrT(_ImproveFloatingPointConsistency, tool.ImproveFloatingPointConsistency) << attrE(_InlineFunctionExpansion, tool.InlineFunctionExpansion, /*ifNot*/ expandDefault) << attrT(_KeepComments, tool.KeepComments) << attrT(_MinimalRebuild, tool.MinimalRebuild) << attrS(_ObjectFile, tool.ObjectFile) << attrT(_OmitFramePointers, tool.OmitFramePointers) << attrT(_OpenMP, tool.OpenMP) << attrE(_Optimization, tool.Optimization, /*ifNot*/ optimizeDefault) << attrE(_OptimizeForProcessor, tool.OptimizeForProcessor, /*ifNot*/ procOptimizeBlended) << attrT(_OptimizeForWindowsApplication, tool.OptimizeForWindowsApplication) << attrS(_OutputFile, tool.OutputFile) << attrS(_PrecompiledHeaderFile, tool.PrecompiledHeaderFile) << attrS(_PrecompiledHeaderThrough, tool.PrecompiledHeaderThrough) << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions) << (tool.ProgramDataBaseFileName.isNull() ? noxml() : attr(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName)) << attrE(_RuntimeLibrary, tool.RuntimeLibrary, /*ifNot*/ rtUnknown) << attrT(_RuntimeTypeInfo, tool.RuntimeTypeInfo) << attrT(_ShowIncludes, tool.ShowIncludes) << attrT(_SmallerTypeCheck, tool.SmallerTypeCheck) << attrT(_StringPooling, tool.StringPooling) << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ alignNotSet) << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) << attrT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType) << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration) << attrT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions) << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions) << xformUsePrecompiledHeaderForNET2005(tool.UsePrecompiledHeader, tool.config->CompilerVersion) << attrT(_WarnAsError, tool.WarnAsError) << attrE(_WarningLevel, tool.WarningLevel, /*ifNot*/ warningLevelUnknown) << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization) << attrE(_CompileForArchitecture, tool.CompileForArchitecture, /*ifNot*/ archUnknown) << attrT(_InterworkCalls, tool.InterworkCalls) << closetag(_Tool); } void VCProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool) { xml << tag(_Tool) << attrS(_Name, _VCLinkerTool) << attrX(_AdditionalDependencies, tool.AdditionalDependencies, " ") << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories) << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrX(_AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly) << attrS(_BaseAddress, tool.BaseAddress) << attrT(_DataExecutionPrevention, tool.DataExecutionPrevention) << attrX(_DelayLoadDLLs, tool.DelayLoadDLLs) << attrE(_EnableCOMDATFolding, tool.EnableCOMDATFolding, /*ifNot*/ optFoldingDefault) << attrS(_EntryPointSymbol, tool.EntryPointSymbol) << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences) << attrS(_FunctionOrder, tool.FunctionOrder) << attrT(_GenerateDebugInformation, tool.GenerateDebugInformation) << attrT(_GenerateMapFile, tool.GenerateMapFile) << attrL(_HeapCommitSize, tool.HeapCommitSize, /*ifNot*/ -1) << attrL(_HeapReserveSize, tool.HeapReserveSize, /*ifNot*/ -1) << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames) << attrT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL) << attrT(_IgnoreImportLibrary, tool.IgnoreImportLibrary) << attrS(_ImportLibrary, tool.ImportLibrary) << attrE(_LargeAddressAware, tool.LargeAddressAware, /*ifNot*/ addrAwareDefault) << attrT(_LinkDLL, tool.LinkDLL) << attrE(_LinkIncremental, tool.LinkIncremental, /*ifNot*/ linkIncrementalDefault) << attrE(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration) << attrS(_LinkToManagedResourceFile, tool.LinkToManagedResourceFile) << attrT(_MapExports, tool.MapExports) << attrS(_MapFileName, tool.MapFileName) << attrT(_MapLines, tool.MapLines) << attrS(_MergedIDLBaseFileName, tool.MergedIDLBaseFileName) << attrS(_MergeSections, tool.MergeSections) << attrS(_MidlCommandFile, tool.MidlCommandFile) << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) << attrE(_OptimizeForWindows98, tool.OptimizeForWindows98, /*ifNot*/ optWin98Default) << attrE(_OptimizeReferences, tool.OptimizeReferences, /*ifNot*/ optReferencesDefault) << attrS(_OutputFile, tool.OutputFile) << attr(_ProgramDatabaseFile, tool.ProgramDatabaseFile) << attrT(_RandomizedBaseAddress, tool.RandomizedBaseAddress) << attrT(_RegisterOutput, tool.RegisterOutput) << attrT(_ResourceOnlyDLL, tool.ResourceOnlyDLL) << attrT(_SetChecksum, tool.SetChecksum) << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet) << attrL(_StackCommitSize, tool.StackCommitSize, /*ifNot*/ -1) << attrL(_StackReserveSize, tool.StackReserveSize, /*ifNot*/ -1) << attrS(_StripPrivateSymbols, tool.StripPrivateSymbols) << attrE(_SubSystem, tool.SubSystem) << attrT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL) << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) << attrT(_SwapRunFromCD, tool.SwapRunFromCD) << attrT(_SwapRunFromNet, tool.SwapRunFromNet) << attrE(_TargetMachine, tool.TargetMachine, /*ifNot*/ machineNotSet) << attrE(_TerminalServerAware, tool.TerminalServerAware, /*ifNot*/ termSvrAwareDefault) << attrT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration) << attrS(_TypeLibraryFile, tool.TypeLibraryFile) << attrL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ rcUseDefault) << attrS(_Version, tool.Version) << attrT(_GenerateManifest, tool.GenerateManifest) << closetag(_Tool); } void VCProjectWriter::write(XmlOutput &xml, const VCManifestTool &tool) { xml << tag(_Tool) << attrS(_Name, _VCManifestTool) << attrT(_EmbedManifest, tool.EmbedManifest) << closetag(_Tool); } void VCProjectWriter::write(XmlOutput &xml, const VCMIDLTool &tool) { xml << tag(_Tool) << attrS(_Name, _VCMIDLTool) << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories) << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrX(_CPreprocessOptions, tool.CPreprocessOptions) << attrE(_DefaultCharType, tool.DefaultCharType) << attrS(_DLLDataFileName, tool.DLLDataFileName) << attrE(_EnableErrorChecks, tool.EnableErrorChecks) << attrT(_ErrorCheckAllocations, tool.ErrorCheckAllocations) << attrT(_ErrorCheckBounds, tool.ErrorCheckBounds) << attrT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange) << attrT(_ErrorCheckRefPointers, tool.ErrorCheckRefPointers) << attrT(_ErrorCheckStubData, tool.ErrorCheckStubData) << attrX(_FullIncludePath, tool.FullIncludePath) << attrT(_GenerateStublessProxies, tool.GenerateStublessProxies) << attrT(_GenerateTypeLibrary, tool.GenerateTypeLibrary) << attrS(_HeaderFileName, tool.HeaderFileName) << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) << attrS(_InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName) << attrT(_MkTypLibCompatible, tool.MkTypLibCompatible) << attrS(_OutputDirectory, tool.OutputDirectory) << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions) << attrS(_ProxyFileName, tool.ProxyFileName) << attrS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors) << attrE(_StructMemberAlignment, tool.StructMemberAlignment, /*ifNot*/ midlAlignNotSet) << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) << attrE(_TargetEnvironment, tool.TargetEnvironment, /*ifNot*/ midlTargetNotSet) << attrS(_TypeLibraryName, tool.TypeLibraryName) << attrX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions) << attrT(_ValidateParameters, tool.ValidateParameters) << attrT(_WarnAsError, tool.WarnAsError) << attrE(_WarningLevel, tool.WarningLevel) << closetag(_Tool); } void VCProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool) { xml << tag(_Tool) << attrS(_Name, tool.ToolName) << attrX(_AdditionalDependencies, tool.AdditionalDependencies, ";") << attrS(_CommandLine, tool.CommandLine.join(vcCommandSeparator())) << attrS(_Description, tool.Description) << attrX(_Outputs, tool.Outputs, ";") << attrS(_Path, tool.ToolPath) << closetag(_Tool); } void VCProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool) { xml << tag(_Tool) << attrS(_Name, _VCLibrarianTool) << attrX(_AdditionalDependencies, tool.AdditionalDependencies) << attrX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories) << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrX(_ExportNamedFunctions, tool.ExportNamedFunctions) << attrX(_ForceSymbolReferences, tool.ForceSymbolReferences) << attrT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) << attrX(_IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames) << attrS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) << attrS(_OutputFile, tool.OutputFile) << attrT(_SuppressStartupBanner, tool.SuppressStartupBanner) << closetag(_Tool); } void VCProjectWriter::write(XmlOutput &xml, const VCResourceCompilerTool &tool) { xml << tag(_Tool) << attrS(_Name, _VCResourceCompilerTool) << attrS(_Path, tool.ToolPath) << attrX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories) << attrX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrE(_Culture, tool.Culture, /*ifNot*/ rcUseDefault) << attrX(_FullIncludePath, tool.FullIncludePath) << attrT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) << attrX(_PreprocessorDefinitions, tool.PreprocessorDefinitions) << attrS(_ResourceOutputFileName, tool.ResourceOutputFileName) << attrE(_ShowProgress, tool.ShowProgress, /*ifNot*/ linkProgressNotSet) << closetag(_Tool); } void VCProjectWriter::write(XmlOutput &xml, const VCEventTool &tool) { xml << tag(_Tool) << attrS(_Name, tool.ToolName) << attrS(_Path, tool.ToolPath) << attrS(_CommandLine, tool.CommandLine.join(vcCommandSeparator())) << attrS(_Description, tool.Description) << attrT(_ExcludedFromBuild, tool.ExcludedFromBuild) << closetag(_Tool); } void VCProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool) { if (tool.AdditionalFiles.isEmpty()) return; xml << tag(tool.DeploymentTag) << attrS(_RemoteDirectory, tool.RemoteDirectory) << attrE(_RegisterOutput, tool.RegisterOutput) << attrS(_AdditionalFiles, tool.AdditionalFiles) << closetag(tool.DeploymentTag); } void VCProjectWriter::write(XmlOutput &xml, const VCWinDeployQtTool &tool) { Q_UNUSED(xml); Q_UNUSED(tool); } void VCProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool) { xml << tag(_Configuration) << attrS(_Name, tool.Name) << attrS(_OutputDirectory, tool.OutputDirectory) << attrT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage) << attrT(_BuildBrowserInformation, tool.BuildBrowserInformation) << attrE(_CharacterSet, tool.CharacterSet, /*ifNot*/ charSetNotSet) << attrE(_ConfigurationType, tool.ConfigurationType) << attrS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean) << attrS(_ImportLibrary, tool.ImportLibrary) << attrS(_IntermediateDirectory, tool.IntermediateDirectory) << attrS(_PrimaryOutput, tool.PrimaryOutput) << attrS(_ProgramDatabase, tool.ProgramDatabase) << attrT(_RegisterOutput, tool.RegisterOutput) << attrE(_UseOfATL, tool.UseOfATL, /*ifNot*/ useATLNotSet) << attrE(_UseOfMfc, tool.UseOfMfc) << attrT(_WholeProgramOptimization, tool.WholeProgramOptimization); write(xml, tool.compiler); if (tool.ConfigurationType == typeStaticLibrary) write(xml, tool.librarian); else write(xml, tool.linker); write(xml, tool.manifestTool); write(xml, tool.idl); write(xml, tool.postBuild); write(xml, tool.preBuild); write(xml, tool.preLink); write(xml, tool.resource); write(xml, tool.deployment); xml << closetag(_Configuration); } void VCProjectWriter::write(XmlOutput &xml, VCFilter &tool) { if(!tool.Files.size()) return; if (!tool.Name.isEmpty()) { xml << tag(_Filter) << attrS(_Name, tool.Name) << attrS(_Filter, tool.Filter) << attrS(_UniqueIdentifier, tool.Guid) << attrT(_ParseFiles, tool.ParseFiles); } for (int i = 0; i < tool.Files.size(); ++i) { const VCFilterFile &info = tool.Files.at(i); xml << tag(q_File) << attrS(_RelativePath, Option::fixPathToTargetOS(info.file)) << data(); // In case no custom builds, to avoid "/>" endings outputFileConfig(tool, xml, tool.Files.at(i).file); xml << closetag(q_File); } if (!tool.Name.isEmpty()) xml << closetag(_Filter); } // outputs a given filter for all existing configurations of a project void VCProjectWriter::outputFilter(VCProject &project, XmlOutput &xml, const QString &filtername) { QScopedPointer root; if (project.SingleProjects.at(0).flat_files) root.reset(new FlatNode); else root.reset(new TreeNode); QString name, extfilter, guid; triState parse = unset; for (int i = 0; i < project.SingleProjects.size(); ++i) { const VCFilter filter = project.SingleProjects.at(i).filterByName(filtername); // Merge all files in this filter to root tree for (int x = 0; x < filter.Files.size(); ++x) root->addElement(filter.Files.at(x)); // Save filter setting from first filter. Next filters // may differ but we cannot handle that. (ex. extfilter) if (name.isEmpty()) { name = filter.Name; extfilter = filter.Filter; parse = filter.ParseFiles; guid = filter.Guid; } } if (!root->hasElements()) return; // Actual XML output ---------------------------------- if (!name.isEmpty()) { xml << tag(_Filter) << attrS(_Name, name) << attrS(_Filter, extfilter) << attrS(_UniqueIdentifier, guid) << attrT(_ParseFiles, parse); } root->generateXML(xml, "", project, filtername); // output root tree if (!name.isEmpty()) xml << closetag(_Filter); } // Output all configurations (by filtername) for a file (by info) // A filters config output is in VCFilter.outputFileConfig() void VCProjectWriter::outputFileConfigs(VCProject &project, XmlOutput &xml, const VCFilterFile &info, const QString &filtername) { xml << tag(q_File) << attrS(_RelativePath, Option::fixPathToTargetOS(info.file)); for (int i = 0; i < project.SingleProjects.size(); ++i) { VCFilter filter = project.SingleProjects.at(i).filterByName(filtername); if (filter.Config) // only if the filter is not empty outputFileConfig(filter, xml, info.file); } xml << closetag(q_File); } void VCProjectWriter::outputFileConfig(VCFilter &filter, XmlOutput &xml, const QString &filename) { // Clearing each filter tool filter.useCustomBuildTool = false; filter.useCompilerTool = false; filter.CustomBuildTool = VCCustomBuildTool(); filter.CompilerTool = VCCLCompilerTool(); // Unset some default options filter.CustomBuildTool.config = filter.Config; filter.CompilerTool.BufferSecurityCheck = unset; filter.CompilerTool.DebugInformationFormat = debugUnknown; filter.CompilerTool.ExceptionHandling = ehDefault; filter.CompilerTool.GeneratePreprocessedFile = preprocessUnknown; filter.CompilerTool.Optimization = optimizeDefault; filter.CompilerTool.ProgramDataBaseFileName.clear(); filter.CompilerTool.RuntimeLibrary = rtUnknown; filter.CompilerTool.WarningLevel = warningLevelUnknown; filter.CompilerTool.config = filter.Config; bool inBuild; VCFilterFile info = filter.findFile(filename, &inBuild); inBuild &= !info.excludeFromBuild; if (inBuild) { filter.addExtraCompiler(info); if(filter.Project->usePCH) filter.modifyPCHstage(info.file); } else { // Excluded files uses an empty compiler stage if(info.excludeFromBuild) filter.useCompilerTool = true; } // Actual XML output ---------------------------------- if (filter.useCustomBuildTool || filter.useCompilerTool || !inBuild) { xml << tag(_FileConfiguration) << attr(_Name, filter.Config->Name) << (!inBuild ? attrS(_ExcludedFromBuild, "true") : noxml()); if (filter.useCustomBuildTool) filter.Project->projectWriter->write(xml, filter.CustomBuildTool); if (filter.useCompilerTool) filter.Project->projectWriter->write(xml, filter.CompilerTool); xml << closetag(_FileConfiguration); } } QT_END_NAMESPACE