// 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 "msbuild_objectmodel.h" #include "msvc_objectmodel.h" #include "msvc_vcproj.h" #include "msvc_vcxproj.h" #include #include #include #include #include QT_BEGIN_NAMESPACE // XML Tags --------------------------------------------------------- const char _CLCompile[] = "ClCompile"; const char _ItemGroup[] = "ItemGroup"; const char _Link[] = "Link"; const char _Lib[] = "Lib"; const char _Midl[] = "Midl"; const char _ResourceCompile[] = "ResourceCompile"; // XML Properties --------------------------------------------------- const char _AddModuleNamesToAssembly[] = "AddModuleNamesToAssembly"; const char _AdditionalDependencies[] = "AdditionalDependencies"; const char _AdditionalIncludeDirectories[] = "AdditionalIncludeDirectories"; const char _AdditionalLibraryDirectories[] = "AdditionalLibraryDirectories"; const char _AdditionalManifestDependencies[] = "AdditionalManifestDependencies"; const char _AdditionalOptions[] = "AdditionalOptions"; const char _AdditionalUsingDirectories[] = "AdditionalUsingDirectories"; const char _AllowIsolation[] = "AllowIsolation"; const char _ApplicationConfigurationMode[] = "ApplicationConfigurationMode"; const char _AssemblerListingLocation[] = "AssemblerListingLocation"; const char _AssemblerOutput[] = "AssemblerOutput"; const char _AssemblyDebug[] = "AssemblyDebug"; const char _AssemblyLinkResource[] = "AssemblyLinkResource"; 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 _CallingConvention[] = "CallingConvention"; const char _CharacterSet[] = "CharacterSet"; const char _ClientStubFile[] = "ClientStubFile"; const char _CLRImageType[] = "CLRImageType"; const char _CLRSupportLastError[] = "CLRSupportLastError"; const char _CLRThreadAttribute[] = "CLRThreadAttribute"; const char _CLRUnmanagedCodeCheck[] = "CLRUnmanagedCodeCheck"; const char _Command[] = "Command"; const char _CompileAs[] = "CompileAs"; const char _CompileAsManaged[] = "CompileAsManaged"; const char _CompileAsWinRT[] = "CompileAsWinRT"; const char _ConfigurationType[] = "ConfigurationType"; const char _CPreprocessOptions[] = "CPreprocessOptions"; const char _CreateHotpatchableImage[] = "CreateHotpatchableImage"; const char _Culture[] = "Culture"; const char _DataExecutionPrevention[] = "DataExecutionPrevention"; const char _DebugInformationFormat[] = "DebugInformationFormat"; const char _DefaultCharType[] = "DefaultCharType"; const char _DelayLoadDLLs[] = "DelayLoadDLLs"; const char _DelaySign[] = "DelaySign"; const char _DeleteExtensionsOnClean[] = "DeleteExtensionsOnClean"; const char _DisableLanguageExtensions[] = "DisableLanguageExtensions"; const char _DisableSpecificWarnings[] = "DisableSpecificWarnings"; const char _DLLDataFileName[] = "DLLDataFileName"; const char _EmbedManagedResourceFile[] = "EmbedManagedResourceFile"; const char _EmbedManifest[] = "EmbedManifest"; const char _EnableCOMDATFolding[] = "EnableCOMDATFolding"; const char _EnableUAC[] = "EnableUAC"; const char _EnableErrorChecks[] = "EnableErrorChecks"; const char _EnableEnhancedInstructionSet[] = "EnableEnhancedInstructionSet"; const char _EnableFiberSafeOptimizations[] = "EnableFiberSafeOptimizations"; const char _EnablePREfast[] = "EnablePREfast"; 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 _ErrorReporting[] = "ErrorReporting"; const char _ExceptionHandling[] = "ExceptionHandling"; 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 _FunctionLevelLinking[] = "FunctionLevelLinking"; const char _FunctionOrder[] = "FunctionOrder"; const char _GenerateClientFiles[] = "GenerateClientFiles"; const char _GenerateDebugInformation[] = "GenerateDebugInformation"; const char _GenerateManifest[] = "GenerateManifest"; const char _GenerateMapFile[] = "GenerateMapFile"; const char _GenerateServerFiles[] = "GenerateServerFiles"; const char _GenerateStublessProxies[] = "GenerateStublessProxies"; const char _GenerateTypeLibrary[] = "GenerateTypeLibrary"; const char _GenerateWindowsMetadata[] = "GenerateWindowsMetadata"; const char _GenerateXMLDocumentationFiles[] = "GenerateXMLDocumentationFiles"; const char _HeaderFileName[] = "HeaderFileName"; const char _HeapCommitSize[] = "HeapCommitSize"; const char _HeapReserveSize[] = "HeapReserveSize"; const char _IgnoreAllDefaultLibraries[] = "IgnoreAllDefaultLibraries"; const char _IgnoreEmbeddedIDL[] = "IgnoreEmbeddedIDL"; const char _IgnoreImportLibrary[] = "IgnoreImportLibrary"; const char _ImageHasSafeExceptionHandlers[] = "ImageHasSafeExceptionHandlers"; const char _IgnoreSpecificDefaultLibraries[] = "IgnoreSpecificDefaultLibraries"; const char _IgnoreStandardIncludePath[] = "IgnoreStandardIncludePath"; const char _ImportLibrary[] = "ImportLibrary"; const char _InlineFunctionExpansion[] = "InlineFunctionExpansion"; const char _IntrinsicFunctions[] = "IntrinsicFunctions"; const char _InterfaceIdentifierFileName[] = "InterfaceIdentifierFileName"; const char _IntermediateDirectory[] = "IntermediateDirectory"; const char _KeyContainer[] = "KeyContainer"; const char _KeyFile[] = "KeyFile"; const char _LanguageStandard[] = "LanguageStandard"; const char _LanguageStandard_C[] = "LanguageStandard_C"; const char _LargeAddressAware[] = "LargeAddressAware"; const char _LinkDLL[] = "LinkDLL"; const char _LinkErrorReporting[] = "LinkErrorReporting"; const char _LinkIncremental[] = "LinkIncremental"; const char _LinkStatus[] = "LinkStatus"; const char _LinkTimeCodeGeneration[] = "LinkTimeCodeGeneration"; const char _LocaleID[] = "LocaleID"; const char _ManifestFile[] = "ManifestFile"; const char _MapExports[] = "MapExports"; const char _MapFileName[] = "MapFileName"; const char _MergedIDLBaseFileName[] = "MergedIDLBaseFileName"; const char _MergeSections[] = "MergeSections"; const char _Message[] = "Message"; const char _MidlCommandFile[] = "MidlCommandFile"; const char _MinimalRebuild[] = "MinimalRebuild"; const char _MkTypLibCompatible[] = "MkTypLibCompatible"; const char _ModuleDefinitionFile[] = "ModuleDefinitionFile"; const char _MultiProcessorCompilation[] = "MultiProcessorCompilation"; const char _Name[] = "Name"; const char _NoEntryPoint[] = "NoEntryPoint"; const char _ObjectFileName[] = "ObjectFileName"; const char _OmitDefaultLibName[] = "OmitDefaultLibName"; const char _OmitFramePointers[] = "OmitFramePointers"; const char _OpenMPSupport[] = "OpenMPSupport"; const char _Optimization[] = "Optimization"; const char _OptimizeReferences[] = "OptimizeReferences"; const char _OutputDirectory[] = "OutputDirectory"; const char _OutputFile[] = "OutputFile"; const char _PlatformToolSet[] = "PlatformToolset"; const char _PrecompiledHeader[] = "PrecompiledHeader"; const char _PrecompiledHeaderFile[] = "PrecompiledHeaderFile"; const char _PrecompiledHeaderOutputFile[] = "PrecompiledHeaderOutputFile"; const char _PreprocessorDefinitions[] = "PreprocessorDefinitions"; const char _PreprocessKeepComments[] = "PreprocessKeepComments"; const char _PreprocessOutputPath[] = "PreprocessOutputPath"; const char _PreprocessSuppressLineNumbers[] = "PreprocessSuppressLineNumbers"; const char _PreprocessToFile[] = "PreprocessToFile"; const char _PreventDllBinding[] = "PreventDllBinding"; const char _PrimaryOutput[] = "PrimaryOutput"; const char _ProcessorNumber[] = "ProcessorNumber"; 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 _ResourceOutputFileName[] = "ResourceOutputFileName"; const char _RuntimeLibrary[] = "RuntimeLibrary"; const char _RuntimeTypeInfo[] = "RuntimeTypeInfo"; const char _SectionAlignment[] = "SectionAlignment"; const char _ServerStubFile[] = "ServerStubFile"; 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 _SuppressCompilerWarnings[] = "SuppressCompilerWarnings"; 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 _TreatLinkerWarningAsErrors[] = "TreatLinkerWarningAsErrors"; const char _TreatSpecificWarningsAsErrors[] = "TreatSpecificWarningsAsErrors"; const char _TreatWarningAsError[] = "TreatWarningAsError"; const char _TreatWChar_tAsBuiltInType[] = "TreatWChar_tAsBuiltInType"; const char _TurnOffAssemblyGeneration[] = "TurnOffAssemblyGeneration"; const char _TypeLibFormat[] = "TypeLibFormat"; const char _TypeLibraryFile[] = "TypeLibraryFile"; const char _TypeLibraryName[] = "TypeLibraryName"; const char _TypeLibraryResourceID[] = "TypeLibraryResourceID"; const char _UACExecutionLevel[] = "UACExecutionLevel"; const char _UACUIAccess[] = "UACUIAccess"; const char _UndefineAllPreprocessorDefinitions[]= "UndefineAllPreprocessorDefinitions"; const char _UndefinePreprocessorDefinitions[] = "UndefinePreprocessorDefinitions"; const char _UseFullPaths[] = "UseFullPaths"; const char _UseOfATL[] = "UseOfATL"; const char _UseOfMfc[] = "UseOfMfc"; const char _UseUnicodeForAssemblerListing[] = "UseUnicodeForAssemblerListing"; const char _ValidateAllParameters[] = "ValidateAllParameters"; const char _Version[] = "Version"; const char _WarnAsError[] = "WarnAsError"; const char _WarningLevel[] = "WarningLevel"; const char _WholeProgramOptimization[] = "WholeProgramOptimization"; const char _WindowsMetadataFile[] = "WindowsMetadataFile"; const char _XMLDocumentationFileName[] = "XMLDocumentationFileName"; // XmlOutput stream functions ------------------------------ inline XmlOutput::xml_output attrTagT(const char *name, const triState v) { if(v == unset) return noxml(); return tagValue(name, (v == _True ? "true" : "false")); } inline XmlOutput::xml_output attrTagL(const char *name, qint64 v) { return tagValue(name, QString::number(v)); } /*ifNot version*/ inline XmlOutput::xml_output attrTagL(const char *name, qint64 v, qint64 ifn) { if (v == ifn) return noxml(); return tagValue(name, QString::number(v)); } inline XmlOutput::xml_output attrTagS(const char *name, const QString &v) { if(v.isEmpty()) return noxml(); return tagValue(name, v); } inline XmlOutput::xml_output attrTagX(const char *name, const QStringList &v, const char *s = ",") { if(v.isEmpty()) return noxml(); QStringList temp = v; temp.append(QString("%(%1)").arg(name)); return tagValue(name, temp.join(s)); } inline XmlOutput::xml_output valueTagX(const QStringList &v, const char *s = " ") { if(v.isEmpty()) return noxml(); return valueTag(v.join(s)); } inline XmlOutput::xml_output valueTagDefX(const QStringList &v, const QString &tagName, const char *s = " ") { if(v.isEmpty()) return noxml(); QStringList temp = v; temp.append(QString("%(%1)").arg(tagName)); return valueTag(temp.join(s)); } inline XmlOutput::xml_output valueTagT( const triState v) { if(v == unset) return noxml(); return valueTag(v == _True ? "true" : "false"); } static QString commandLinesForOutput(QStringList commands) { // MSBuild puts the contents of the custom commands into a batch file and calls 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. static QString errchk = QStringLiteral("if errorlevel 1 goto VCEnd"); for (int i = commands.size() - 2; i >= 0; --i) { if (!commands.at(i).startsWith("rem", Qt::CaseInsensitive)) commands.insert(i + 1, errchk); } return commands.join("\r\n"); } static QString unquote(const QString &value) { QString result = value; result.replace(QLatin1String("\\\""), QLatin1String("\"")); return result; } static QStringList unquote(const QStringList &values) { QStringList result; result.reserve(values.size()); for (int i = 0; i < values.size(); ++i) result << unquote(values.at(i)); return result; } // Tree file generation --------------------------------------------- void XTreeNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &tool, const QString &filter) { if (children.size()) { // Filter QString tempFilterName; ChildrenMap::ConstIterator it, end = children.constEnd(); if (!tagName.isEmpty()) { tempFilterName.append(filter); tempFilterName.append("\\"); tempFilterName.append(tagName); xmlFilter << tag(_ItemGroup); xmlFilter << tag("Filter") << attrTag("Include", tempFilterName) << closetag(); xmlFilter << closetag(); } // First round, do nested filters for (it = children.constBegin(); it != end; ++it) if ((*it)->children.size()) { if ( !tempFilterName.isEmpty() ) (*it)->generateXML(xml, xmlFilter, it.key(), tool, tempFilterName); else (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter); } // Second round, do leafs for (it = children.constBegin(); it != end; ++it) if (!(*it)->children.size()) { if ( !tempFilterName.isEmpty() ) (*it)->generateXML(xml, xmlFilter, it.key(), tool, tempFilterName); else (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter); } } else { // Leaf xml << tag(_ItemGroup); xmlFilter << tag(_ItemGroup); VCXProjectWriter::outputFileConfigs(tool, xml, xmlFilter, info, filter); xmlFilter << closetag(); xml << closetag(); } } // Flat file generation --------------------------------------------- void XFlatNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &/*tagName*/, VCProject &tool, const QString &filter) { if (children.size()) { ChildrenMapFlat::ConstIterator it = children.constBegin(); ChildrenMapFlat::ConstIterator end = children.constEnd(); xml << tag(_ItemGroup); xmlFilter << tag(_ItemGroup); for (; it != end; ++it) { VCXProjectWriter::outputFileConfigs(tool, xml, xmlFilter, (*it), filter); } xml << closetag(); xmlFilter << closetag(); } } void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool) { xml.setIndentString(" "); xml << decl("1.0", "utf-8") << tag("Project") << attrTag("DefaultTargets","Build") << attrTagToolsVersion(tool.Configuration) << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003") << tag("ItemGroup") << attrTag("Label", "ProjectConfigurations"); xml << tag("ProjectConfiguration") << attrTag("Include" , tool.Configuration.Name) << tagValue("Configuration", tool.Configuration.ConfigurationName) << tagValue("Platform", tool.PlatformName) << closetag(); xml << closetag() << tag("PropertyGroup") << attrTag("Label", "Globals") << tagValue("ProjectGuid", tool.ProjectGUID) << tagValue("RootNamespace", tool.Name) << tagValue("Keyword", tool.Keyword) << closetag(); // config part. xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); write(xml, tool.Configuration); const QString condition = generateCondition(tool.Configuration); xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); // Extension settings xml << tag("ImportGroup") << attrTag("Label", "ExtensionSettings") << closetag(); // PropertySheets xml << tag("ImportGroup") << attrTag("Condition", condition) << attrTag("Label", "PropertySheets"); xml << tag("Import") << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props") << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") << closetag() << closetag(); // UserMacros xml << tag("PropertyGroup") << attrTag("Label", "UserMacros") << closetag(); xml << tag("PropertyGroup"); if ( !tool.Configuration.OutputDirectory.isEmpty() ) { xml<< tag("OutDir") << attrTag("Condition", condition) << valueTag(tool.Configuration.OutputDirectory); } if ( !tool.Configuration.IntermediateDirectory.isEmpty() ) { xml<< tag("IntDir") << attrTag("Condition", condition) << valueTag(tool.Configuration.IntermediateDirectory); } if ( !tool.Configuration.PrimaryOutput.isEmpty() ) { xml<< tag("TargetName") << attrTag("Condition", condition) << valueTag(tool.Configuration.PrimaryOutput); } if (!tool.Configuration.PrimaryOutputExtension.isEmpty()) { xml<< tag("TargetExt") << attrTag("Condition", condition) << valueTag(tool.Configuration.PrimaryOutputExtension); } if ( tool.Configuration.linker.IgnoreImportLibrary != unset) { xml<< tag("IgnoreImportLibrary") << attrTag("Condition", condition) << valueTagT(tool.Configuration.linker.IgnoreImportLibrary); } if ( tool.Configuration.linker.LinkIncremental != linkIncrementalDefault) { const triState ts = (tool.Configuration.linker.LinkIncremental == linkIncrementalYes ? _True : _False); xml<< tag("LinkIncremental") << attrTag("Condition", condition) << valueTagT(ts); } if ( tool.Configuration.preBuild.ExcludedFromBuild != unset ) { xml<< tag("PreBuildEventUseInBuild") << attrTag("Condition", condition) << valueTagT(!tool.Configuration.preBuild.ExcludedFromBuild); } if ( tool.Configuration.preLink.ExcludedFromBuild != unset ) { xml<< tag("PreLinkEventUseInBuild") << attrTag("Condition", condition) << valueTagT(!tool.Configuration.preLink.ExcludedFromBuild); } if ( tool.Configuration.postBuild.ExcludedFromBuild != unset ) { xml<< tag("PostBuildEventUseInBuild") << attrTag("Condition", condition) << valueTagT(!tool.Configuration.postBuild.ExcludedFromBuild); } xml << closetag(); xml << tag("ItemDefinitionGroup") << attrTag("Condition", condition); // ClCompile write(xml, tool.Configuration.compiler); // Link write(xml, tool.Configuration.linker); // Midl write(xml, tool.Configuration.idl); // ResourceCompiler write(xml, tool.Configuration.resource); // Post build event if ( tool.Configuration.postBuild.ExcludedFromBuild != unset ) write(xml, tool.Configuration.postBuild); // Pre build event if ( tool.Configuration.preBuild.ExcludedFromBuild != unset ) write(xml, tool.Configuration.preBuild); // Pre link event if ( tool.Configuration.preLink.ExcludedFromBuild != unset ) write(xml, tool.Configuration.preLink); xml << closetag(); QFile filterFile; filterFile.setFileName(Option::output.fileName().append(".filters")); filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); QTextStream ts(&filterFile); XmlOutput xmlFilter(ts, XmlOutput::NoConversion); xmlFilter.setIndentString(" "); xmlFilter << decl("1.0", "utf-8") << tag("Project") << attrTagToolsVersion(tool.Configuration) << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); xmlFilter << tag("ItemGroup"); VCProject tempProj; tempProj.SingleProjects += tool; addFilters(tempProj, xmlFilter, "Form Files"); addFilters(tempProj, xmlFilter, "Generated Files"); addFilters(tempProj, xmlFilter, "Header Files"); addFilters(tempProj, xmlFilter, "LexYacc Files"); addFilters(tempProj, xmlFilter, "Resource Files"); addFilters(tempProj, xmlFilter, "Source Files"); addFilters(tempProj, xmlFilter, "Translation Files"); addFilters(tempProj, xmlFilter, "Deployment Files"); addFilters(tempProj, xmlFilter, "Distribution Files"); tempProj.ExtraCompilers.reserve(tool.ExtraCompilersFiles.size()); std::transform(tool.ExtraCompilersFiles.cbegin(), tool.ExtraCompilersFiles.cend(), std::back_inserter(tempProj.ExtraCompilers), [] (const VCFilter &filter) { return filter.Name; }); tempProj.ExtraCompilers.removeDuplicates(); for (int x = 0; x < tempProj.ExtraCompilers.size(); ++x) addFilters(tempProj, xmlFilter, tempProj.ExtraCompilers.at(x)); xmlFilter << closetag(); outputFilter(tempProj, xml, xmlFilter, "Source Files"); outputFilter(tempProj, xml, xmlFilter, "Header Files"); outputFilter(tempProj, xml, xmlFilter, "Generated Files"); outputFilter(tempProj, xml, xmlFilter, "LexYacc Files"); outputFilter(tempProj, xml, xmlFilter, "Translation Files"); outputFilter(tempProj, xml, xmlFilter, "Form Files"); outputFilter(tempProj, xml, xmlFilter, "Resource Files"); outputFilter(tempProj, xml, xmlFilter, "Deployment Files"); outputFilter(tempProj, xml, xmlFilter, "Distribution Files"); for (int x = 0; x < tempProj.ExtraCompilers.size(); ++x) { outputFilter(tempProj, xml, xmlFilter, tempProj.ExtraCompilers.at(x)); } outputFilter(tempProj, xml, xmlFilter, "Root Files"); xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets"); xml << tag("ImportGroup") << attrTag("Label", "ExtensionTargets") << closetag(); } void VCXProjectWriter::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.setIndentString(" "); xml << decl("1.0", "utf-8") << tag("Project") << attrTag("DefaultTargets","Build") << attrTagToolsVersion(tool.SingleProjects.first().Configuration) << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003") << tag("ItemGroup") << attrTag("Label", "ProjectConfigurations"); for (int i = 0; i < tool.SingleProjects.size(); ++i) { xml << tag("ProjectConfiguration") << attrTag("Include" , tool.SingleProjects.at(i).Configuration.Name) << tagValue("Configuration", tool.SingleProjects.at(i).Configuration.ConfigurationName) << tagValue("Platform", tool.SingleProjects.at(i).PlatformName) << closetag(); } xml << closetag() << tag("PropertyGroup") << attrTag("Label", "Globals") << tagValue("ProjectGuid", tool.ProjectGUID) << tagValue("RootNamespace", tool.Name) << tagValue("Keyword", tool.Keyword); if (!tool.WindowsTargetPlatformVersion.isEmpty()) xml << tagValue("WindowsTargetPlatformVersion", tool.WindowsTargetPlatformVersion); if (!tool.WindowsTargetPlatformMinVersion.isEmpty()) xml << tagValue("WindowsTargetPlatformMinVersion", tool.WindowsTargetPlatformMinVersion); xml << closetag(); // config part. xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); for (int i = 0; i < tool.SingleProjects.size(); ++i) write(xml, tool.SingleProjects.at(i).Configuration); xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); // Extension settings xml << tag("ImportGroup") << attrTag("Label", "ExtensionSettings") << closetag(); // PropertySheets for (int i = 0; i < tool.SingleProjects.size(); ++i) { xml << tag("ImportGroup") << attrTag("Condition", generateCondition(tool.SingleProjects.at(i).Configuration)) << attrTag("Label", "PropertySheets"); xml << tag("Import") << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props") << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") << closetag() << closetag(); } // UserMacros xml << tag("PropertyGroup") << attrTag("Label", "UserMacros") << closetag(); xml << tag("PropertyGroup"); for (int i = 0; i < tool.SingleProjects.size(); ++i) { const VCConfiguration &config = tool.SingleProjects.at(i).Configuration; const QString condition = generateCondition(config); if (!config.OutputDirectory.isEmpty()) { xml << tag("OutDir") << attrTag("Condition", condition) << valueTag(config.OutputDirectory); } if (!config.IntermediateDirectory.isEmpty()) { xml << tag("IntDir") << attrTag("Condition", condition) << valueTag(config.IntermediateDirectory); } if (!config.PrimaryOutput.isEmpty()) { xml << tag("TargetName") << attrTag("Condition", condition) << valueTag(config.PrimaryOutput); } if (!config.PrimaryOutputExtension.isEmpty()) { xml << tag("TargetExt") << attrTag("Condition", condition) << valueTag(config.PrimaryOutputExtension); } if (config.linker.IgnoreImportLibrary != unset) { xml << tag("IgnoreImportLibrary") << attrTag("Condition", condition) << valueTagT(config.linker.IgnoreImportLibrary); } if (config.linker.LinkIncremental != linkIncrementalDefault) { const triState ts = (config.linker.LinkIncremental == linkIncrementalYes ? _True : _False); xml << tag("LinkIncremental") << attrTag("Condition", condition) << valueTagT(ts); } const triState generateManifest = config.linker.GenerateManifest; if (generateManifest != unset) { xml << tag("GenerateManifest") << attrTag("Condition", condition) << valueTagT(generateManifest); } if (config.preBuild.ExcludedFromBuild != unset) { xml << tag("PreBuildEventUseInBuild") << attrTag("Condition", condition) << valueTagT(!config.preBuild.ExcludedFromBuild); } if (config.preLink.ExcludedFromBuild != unset) { xml << tag("PreLinkEventUseInBuild") << attrTag("Condition", condition) << valueTagT(!config.preLink.ExcludedFromBuild); } if (config.postBuild.ExcludedFromBuild != unset) { xml << tag("PostBuildEventUseInBuild") << attrTag("Condition", condition) << valueTagT(!config.postBuild.ExcludedFromBuild); } } xml << closetag(); for (int i = 0; i < tool.SingleProjects.size(); ++i) { const VCConfiguration &config = tool.SingleProjects.at(i).Configuration; xml << tag("ItemDefinitionGroup") << attrTag("Condition", generateCondition(config)); // ClCompile write(xml, config.compiler); // Librarian / Linker if (config.ConfigurationType == typeStaticLibrary) write(xml, config.librarian); else write(xml, config.linker); // Midl write(xml, config.idl); // ResourceCompiler write(xml, config.resource); // Post build event if (config.postBuild.ExcludedFromBuild != unset) write(xml, config.postBuild); // Pre build event if (config.preBuild.ExcludedFromBuild != unset) write(xml, config.preBuild); // Pre link event if (config.preLink.ExcludedFromBuild != unset) write(xml, config.preLink); xml << closetag(); // windeployqt if (!config.windeployqt.ExcludedFromBuild) write(xml, config.windeployqt); } // The file filters are added in a separate file for MSBUILD. QFile filterFile; filterFile.setFileName(Option::output.fileName().append(".filters")); filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); QTextStream ts(&filterFile); XmlOutput xmlFilter(ts, XmlOutput::NoConversion); xmlFilter.setIndentString(" "); xmlFilter << decl("1.0", "utf-8") << tag("Project") << attrTagToolsVersion(tool.SingleProjects.first().Configuration) << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); xmlFilter << tag("ItemGroup"); addFilters(tool, xmlFilter, "Form Files"); addFilters(tool, xmlFilter, "Generated Files"); addFilters(tool, xmlFilter, "Header Files"); addFilters(tool, xmlFilter, "LexYacc Files"); addFilters(tool, xmlFilter, "Resource Files"); addFilters(tool, xmlFilter, "Source Files"); addFilters(tool, xmlFilter, "Translation Files"); addFilters(tool, xmlFilter, "Deployment Files"); addFilters(tool, xmlFilter, "Distribution Files"); for (int x = 0; x < tool.ExtraCompilers.size(); ++x) addFilters(tool, xmlFilter, tool.ExtraCompilers.at(x)); xmlFilter << closetag(); outputFilter(tool, xml, xmlFilter, "Source Files"); outputFilter(tool, xml, xmlFilter, "Header Files"); outputFilter(tool, xml, xmlFilter, "Generated Files"); outputFilter(tool, xml, xmlFilter, "LexYacc Files"); outputFilter(tool, xml, xmlFilter, "Translation Files"); outputFilter(tool, xml, xmlFilter, "Form Files"); outputFilter(tool, xml, xmlFilter, "Resource Files"); outputFilter(tool, xml, xmlFilter, "Deployment Files"); outputFilter(tool, xml, xmlFilter, "Distribution Files"); for (int x = 0; x < tool.ExtraCompilers.size(); ++x) { outputFilter(tool, xml, xmlFilter, tool.ExtraCompilers.at(x)); } outputFilter(tool, xml, xmlFilter, "Root Files"); xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets") << tag("ImportGroup") << attrTag("Label", "ExtensionTargets") << closetag(); } static inline QString toString(asmListingOption option) { switch (option) { case asmListingNone: break; case asmListingAsmMachine: return "AssemblyAndMachineCode"; case asmListingAsmMachineSrc: return "All"; case asmListingAsmSrc: return "AssemblyAndSourceCode"; case asmListingAssemblyOnly: return "AssemblyCode"; } return QString(); } static inline QString toString(basicRuntimeCheckOption option) { switch (option) { case runtimeBasicCheckNone: return ""; case runtimeCheckStackFrame: return "StackFrameRuntimeCheck"; case runtimeCheckUninitVariables: return "UninitializedLocalUsageCheck"; case runtimeBasicCheckAll: return "EnableFastChecks"; } return QString(); } static inline QString toString(callingConventionOption option) { switch (option) { case callConventionDefault: break; case callConventionCDecl: return "Cdecl"; case callConventionFastCall: return "FastCall"; case callConventionStdCall: return "StdCall"; } return QString(); } static inline QString toString(CompileAsOptions option) { switch (option) { case compileAsDefault: break; case compileAsC: return "CompileAsC"; case compileAsCPlusPlus: return "CompileAsCpp"; } return QString(); } static inline QString toString(compileAsManagedOptions option) { switch (option) { case managedDefault: case managedAssemblySafe: break; case managedAssembly: return "true"; case managedAssemblyPure: return "Safe"; case managedAssemblyOldSyntax: return "OldSyntax"; } return QString(); } static inline QString toString(debugOption option, DotNET compilerVersion) { switch (option) { case debugUnknown: case debugLineInfoOnly: break; case debugDisabled: if (compilerVersion <= NET2010) break; return "None"; case debugOldStyleInfo: return "OldStyle"; case debugEditAndContinue: return "EditAndContinue"; case debugEnabled: return "ProgramDatabase"; } return QString(); } static inline QString toString(enhancedInstructionSetOption option) { switch (option) { case archNotSet: break; case archSSE: return "StreamingSIMDExtensions"; case archSSE2: return "StreamingSIMDExtensions2"; } return QString(); } static inline QString toString(exceptionHandling option) { switch (option) { case ehDefault: break; case ehNone: return "false"; case ehNoSEH: return "Sync"; case ehSEH: return "Async"; } return QString(); } static inline QString toString(favorSizeOrSpeedOption option) { switch (option) { case favorNone: break; case favorSize: return "Size"; case favorSpeed: return "Speed"; } return QString(); } static inline QString toString(floatingPointModel option) { switch (option) { case floatingPointNotSet: break; case floatingPointFast: return "Fast"; case floatingPointPrecise: return "Precise"; case floatingPointStrict: return "Strict"; } return QString(); } static inline QString toString(inlineExpansionOption option) { switch (option) { case expandDefault: break; case expandDisable: return "Disabled"; case expandOnlyInline: return "OnlyExplicitInline"; case expandAnySuitable: return "AnySuitable"; } return QString(); } static inline QString toString(optimizeOption option) { switch (option) { case optimizeCustom: case optimizeDefault: break; case optimizeDisabled: return "Disabled"; case optimizeMinSpace: return "MinSpace"; case optimizeMaxSpeed: return "MaxSpeed"; case optimizeFull: return "Full"; } return QString(); } static inline QString toString(pchOption option) { switch (option) { case pchUnset: case pchGenerateAuto: break; case pchNone: return "NotUsing"; case pchCreateUsingSpecific: return "Create"; case pchUseUsingSpecific: return "Use"; } return QString(); } static inline QString toString(runtimeLibraryOption option) { switch (option) { case rtUnknown: case rtSingleThreaded: case rtSingleThreadedDebug: break; case rtMultiThreaded: return "MultiThreaded"; case rtMultiThreadedDLL: return "MultiThreadedDLL"; case rtMultiThreadedDebug: return "MultiThreadedDebug"; case rtMultiThreadedDebugDLL: return "MultiThreadedDebugDLL"; } return QString(); } static inline QString toString(structMemberAlignOption option) { switch (option) { case alignNotSet: break; case alignSingleByte: return "1Byte"; case alignTwoBytes: return "2Bytes"; case alignFourBytes: return "4Bytes"; case alignEightBytes: return "8Bytes"; case alignSixteenBytes: return "16Bytes"; } return QString(); } static inline QString toString(warningLevelOption option) { switch (option) { case warningLevelUnknown: break; case warningLevel_0: return "TurnOffAllWarnings"; case warningLevel_1: return "Level1"; case warningLevel_2: return "Level2"; case warningLevel_3: return "Level3"; case warningLevel_4: return "Level4"; } return QString(); } static inline QString toString(optLinkTimeCodeGenType option) { switch (option) { case optLTCGDefault: break; case optLTCGEnabled: return "UseLinkTimeCodeGeneration"; case optLTCGIncremental: return "UseFastLinkTimeCodeGeneration"; case optLTCGInstrument: return "PGInstrument"; case optLTCGOptimize: return "PGOptimization"; case optLTCGUpdate: return "PGUpdate"; } return QString(); } static inline QString toString(subSystemOption option) { switch (option) { case subSystemNotSet: break; case subSystemConsole: return "Console"; case subSystemWindows: return "Windows"; } return QString(); } static inline QString toString(triState genDebugInfo, linkerDebugOption option) { switch (genDebugInfo) { case unset: break; case _False: return "false"; case _True: if (option == linkerDebugOptionFastLink) return "DebugFastLink"; else if (option == linkerDebugOptionFull) return "DebugFull"; return "true"; } return QString(); } static inline QString toString(machineTypeOption option) { switch (option) { case machineNotSet: break; case machineX86: return "MachineX86"; case machineX64: return "MachineX64"; } return QString(); } static inline QString toString(midlCharOption option) { switch (option) { case midlCharUnsigned: return "Unsigned"; case midlCharSigned: return "Signed"; case midlCharAscii7: return "Ascii"; } return QString(); } static inline QString toString(midlErrorCheckOption option) { switch (option) { case midlEnableCustom: break; case midlDisableAll: return "None"; case midlEnableAll: return "All"; } return QString(); } static inline QString toString(midlStructMemberAlignOption option) { switch (option) { case midlAlignNotSet: break; case midlAlignSingleByte: return "1"; case midlAlignTwoBytes: return "2"; case midlAlignFourBytes: return "4"; case midlAlignEightBytes: return "8"; case midlAlignSixteenBytes: return "16"; } return QString(); } static inline QString toString(midlTargetEnvironment option) { switch (option) { case midlTargetNotSet: break; case midlTargetWin32: return "Win32"; case midlTargetWin64: return "X64"; } return QString(); } static inline QString toString(midlWarningLevelOption option) { switch (option) { case midlWarningLevel_0: return "0"; case midlWarningLevel_1: return "1"; case midlWarningLevel_2: return "2"; case midlWarningLevel_3: return "3"; case midlWarningLevel_4: return "4"; } return QString(); } static inline QString toString(enumResourceLangID option) { if (option == 0) return QString(); else return QString::number(qlonglong(option)); } static inline QString toString(charSet option) { switch (option) { case charSetNotSet: return "NotSet"; case charSetUnicode: return "Unicode"; case charSetMBCS: return "MultiByte"; } return QString(); } static inline QString toString(ConfigurationTypes option) { switch (option) { case typeUnknown: case typeGeneric: break; case typeApplication: return "Application"; case typeDynamicLibrary: return "DynamicLibrary"; case typeStaticLibrary: return "StaticLibrary"; } return QString(); } static inline QString toString(useOfATL option) { switch (option) { case useATLNotSet: break; case useATLStatic: return "Static"; case useATLDynamic: return "Dynamic"; } return QString(); } static inline QString toString(useOfMfc option) { switch (option) { case useMfcStdWin: break; case useMfcStatic: return "Static"; case useMfcDynamic: return "Dynamic"; } return QString(); } static inline triState toTriState(browseInfoOption option) { switch (option) { case brInfoNone: return _False; case brAllInfo: case brNoLocalSymbols: return _True; } return unset; } static inline triState toTriState(preprocessOption option) { switch (option) { case preprocessUnknown: break; case preprocessNo: return _False; case preprocessNoLineNumbers: case preprocessYes: return _True; } return unset; } static inline triState toTriState(optFoldingType option) { switch (option) { case optFoldingDefault: break; case optNoFolding: return _False; case optFolding: return _True; } return unset; } static inline triState toTriState(addressAwarenessType option) { switch (option) { case addrAwareDefault: return unset; case addrAwareNoLarge: return _False; case addrAwareLarge: return _True; } return unset; } static inline triState toTriState(linkIncrementalType option) { switch (option) { case linkIncrementalDefault: return unset; case linkIncrementalNo: return _False; case linkIncrementalYes: return _True; } return unset; } static inline triState toTriState(linkProgressOption option) { switch (option) { case linkProgressNotSet: return unset; case linkProgressAll: case linkProgressLibs: return _True; } return unset; } static inline triState toTriState(optRefType option) { switch (option) { case optReferencesDefault: return unset; case optNoReferences: return _False; case optReferences: return _True; } return unset; } static inline triState toTriState(termSvrAwarenessType option) { switch (option) { case termSvrAwareDefault: return unset; case termSvrAwareNo: return _False; case termSvrAwareYes: return _True; } return unset; } static XmlOutput::xml_output fixedProgramDataBaseFileNameOutput(const VCCLCompilerTool &tool) { if (tool.config->CompilerVersion >= NET2012 && tool.DebugInformationFormat == debugDisabled && tool.ProgramDataBaseFileName.isEmpty()) { // Force the creation of an empty tag to work-around Visual Studio bug. See QTBUG-35570. return tagValue(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName); } return attrTagS(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName); } void VCXProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool) { xml << tag(_CLCompile) << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";") << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrTagX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories, ";") << attrTagS(_AssemblerListingLocation, tool.AssemblerListingLocation) << attrTagS(_AssemblerOutput, toString(tool.AssemblerOutput)) << attrTagS(_BasicRuntimeChecks, toString(tool.BasicRuntimeChecks)) << attrTagT(_BrowseInformation, toTriState(tool.BrowseInformation)) << attrTagS(_BrowseInformationFile, tool.BrowseInformationFile) << attrTagT(_BufferSecurityCheck, tool.BufferSecurityCheck) << attrTagS(_CallingConvention, toString(tool.CallingConvention)) << attrTagS(_CompileAs, toString(tool.CompileAs)) << attrTagS(_CompileAsManaged, toString(tool.CompileAsManaged)) << attrTagT(_CompileAsWinRT, tool.CompileAsWinRT) << attrTagT(_CreateHotpatchableImage, tool.CreateHotpatchableImage) << attrTagS(_DebugInformationFormat, toString(tool.DebugInformationFormat, tool.config->CompilerVersion)) << attrTagT(_DisableLanguageExtensions, tool.DisableLanguageExtensions) << attrTagX(_DisableSpecificWarnings, tool.DisableSpecificWarnings, ";") << attrTagS(_EnableEnhancedInstructionSet, toString(tool.EnableEnhancedInstructionSet)) << attrTagT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations) << attrTagT(_EnablePREfast, tool.EnablePREfast) << attrTagS(_ErrorReporting, tool.ErrorReporting) << attrTagS(_ExceptionHandling, toString(tool.ExceptionHandling)) << attrTagT(_ExpandAttributedSource, tool.ExpandAttributedSource) << attrTagS(_FavorSizeOrSpeed, toString(tool.FavorSizeOrSpeed)) << attrTagT(_FloatingPointExceptions, tool.FloatingPointExceptions) << attrTagS(_FloatingPointModel, toString(tool.FloatingPointModel)) << attrTagT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope) << attrTagX(_ForcedIncludeFiles, tool.ForcedIncludeFiles, ";") << attrTagX(_ForcedUsingFiles, tool.ForcedUsingFiles, ";") << attrTagT(_FunctionLevelLinking, tool.EnableFunctionLevelLinking) << attrTagT(_GenerateXMLDocumentationFiles, tool.GenerateXMLDocumentationFiles) << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) << attrTagS(_InlineFunctionExpansion, toString(tool.InlineFunctionExpansion)) << attrTagT(_IntrinsicFunctions, tool.EnableIntrinsicFunctions) << attrTagT(_MinimalRebuild, tool.MinimalRebuild) << attrTagT(_MultiProcessorCompilation, tool.MultiProcessorCompilation) << attrTagS(_LanguageStandard, tool.LanguageStandard) << attrTagS(_LanguageStandard_C, tool.LanguageStandard_C) << attrTagS(_ObjectFileName, tool.ObjectFile) << attrTagT(_OmitDefaultLibName, tool.OmitDefaultLibName) << attrTagT(_OmitFramePointers, tool.OmitFramePointers) << attrTagT(_OpenMPSupport, tool.OpenMP) << attrTagS(_Optimization, toString(tool.Optimization)) << attrTagS(_PrecompiledHeader, toString(tool.UsePrecompiledHeader)) << attrTagS(_PrecompiledHeaderFile, tool.PrecompiledHeaderThrough) << attrTagS(_PrecompiledHeaderOutputFile, tool.PrecompiledHeaderFile) << attrTagT(_PreprocessKeepComments, tool.KeepComments) << attrTagX(_PreprocessorDefinitions, unquote(tool.PreprocessorDefinitions), ";") << attrTagS(_PreprocessOutputPath, tool.PreprocessOutputPath) << attrTagT(_PreprocessSuppressLineNumbers, tool.PreprocessSuppressLineNumbers) << attrTagT(_PreprocessToFile, toTriState(tool.GeneratePreprocessedFile)) << fixedProgramDataBaseFileNameOutput(tool) << attrTagS(_ProcessorNumber, tool.MultiProcessorCompilationProcessorCount) << attrTagS(_RuntimeLibrary, toString(tool.RuntimeLibrary)) << attrTagT(_RuntimeTypeInfo, tool.RuntimeTypeInfo) << attrTagT(_ShowIncludes, tool.ShowIncludes) << attrTagT(_SmallerTypeCheck, tool.SmallerTypeCheck) << attrTagT(_StringPooling, tool.StringPooling) << attrTagS(_StructMemberAlignment, toString(tool.StructMemberAlignment)) << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) << attrTagX(_TreatSpecificWarningsAsErrors, tool.TreatSpecificWarningsAsErrors, ";") << attrTagT(_TreatWarningAsError, tool.WarnAsError) << attrTagT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType) << attrTagT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions) << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";") << attrTagT(_UseFullPaths, tool.DisplayFullPaths) << attrTagT(_UseUnicodeForAssemblerListing, tool.UseUnicodeForAssemblerListing) << attrTagS(_WarningLevel, toString(tool.WarningLevel)) << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization) << attrTagS(_XMLDocumentationFileName, tool.XMLDocumentationFileName) << closetag(_CLCompile); } void VCXProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool) { xml << tag(_Link) << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";") << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";") << attrTagX(_AdditionalManifestDependencies, tool.AdditionalManifestDependencies, ";") << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrTagX(_AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly, ";") << attrTagT(_AllowIsolation, tool.AllowIsolation) << attrTagT(_AssemblyDebug, tool.AssemblyDebug) << attrTagX(_AssemblyLinkResource, tool.AssemblyLinkResource, ";") << attrTagS(_BaseAddress, tool.BaseAddress) << attrTagS(_CLRImageType, tool.CLRImageType) << attrTagS(_CLRSupportLastError, tool.CLRSupportLastError) << attrTagS(_CLRThreadAttribute, tool.CLRThreadAttribute) << attrTagT(_CLRUnmanagedCodeCheck, tool.CLRUnmanagedCodeCheck) << attrTagT(_DataExecutionPrevention, tool.DataExecutionPrevention) << attrTagX(_DelayLoadDLLs, tool.DelayLoadDLLs, ";") << attrTagT(_DelaySign, tool.DelaySign) << attrTagS(_EmbedManagedResourceFile, tool.LinkToManagedResourceFile) << attrTagT(_EnableCOMDATFolding, toTriState(tool.EnableCOMDATFolding)) << attrTagT(_EnableUAC, tool.EnableUAC) << attrTagS(_EntryPointSymbol, tool.EntryPointSymbol) << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";") << attrTagS(_FunctionOrder, tool.FunctionOrder) << attrTagS(_GenerateDebugInformation, toString(tool.GenerateDebugInformation, tool.DebugInfoOption)) << attrTagT(_GenerateManifest, tool.GenerateManifest) << attrTagT(_GenerateWindowsMetadata, tool.GenerateWindowsMetadata) << attrTagS(_WindowsMetadataFile, tool.GenerateWindowsMetadata == _True ? tool.WindowsMetadataFile : QString()) << attrTagT(_GenerateMapFile, tool.GenerateMapFile) << attrTagL(_HeapCommitSize, tool.HeapCommitSize, /*ifNot*/ -1) << attrTagL(_HeapReserveSize, tool.HeapReserveSize, /*ifNot*/ -1) << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) << attrTagT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL) << attrTagT(_IgnoreImportLibrary, tool.IgnoreImportLibrary) << attrTagT(_ImageHasSafeExceptionHandlers, tool.ImageHasSafeExceptionHandlers) << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreDefaultLibraryNames, ";") << attrTagS(_ImportLibrary, tool.ImportLibrary) << attrTagS(_KeyContainer, tool.KeyContainer) << attrTagS(_KeyFile, tool.KeyFile) << attrTagT(_LargeAddressAware, toTriState(tool.LargeAddressAware)) << attrTagT(_LinkDLL, (tool.config->ConfigurationType == typeDynamicLibrary ? _True : unset)) << attrTagS(_LinkErrorReporting, tool.LinkErrorReporting) << attrTagT(_LinkIncremental, toTriState(tool.LinkIncremental)) << attrTagT(_LinkStatus, toTriState(tool.ShowProgress)) << attrTagS(_LinkTimeCodeGeneration, toString(tool.LinkTimeCodeGeneration)) << attrTagS(_ManifestFile, tool.ManifestFile) << attrTagT(_MapExports, tool.MapExports) << attrTagS(_MapFileName, tool.MapFileName) << attrTagS(_MergedIDLBaseFileName, tool.MergedIDLBaseFileName) << attrTagS(_MergeSections, tool.MergeSections) << attrTagS(_MidlCommandFile, tool.MidlCommandFile) << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) << attrTagT(_NoEntryPoint, tool.ResourceOnlyDLL) << attrTagT(_OptimizeReferences, toTriState(tool.OptimizeReferences)) << attrTagS(_OutputFile, tool.OutputFile) << attrTagT(_PreventDllBinding, tool.PreventDllBinding) << attrTagS(_ProgramDatabaseFile, tool.ProgramDatabaseFile) << attrTagT(_RandomizedBaseAddress, tool.RandomizedBaseAddress) << attrTagT(_RegisterOutput, tool.RegisterOutput) << attrTagL(_SectionAlignment, tool.SectionAlignment, /*ifNot*/ -1) << attrTagT(_SetChecksum, tool.SetChecksum) << attrTagL(_StackCommitSize, tool.StackCommitSize, /*ifNot*/ -1) << attrTagL(_StackReserveSize, tool.StackReserveSize, /*ifNot*/ -1) << attrTagS(_StripPrivateSymbols, tool.StripPrivateSymbols) << attrTagS(_SubSystem, toString(tool.SubSystem)) // << attrTagT(_SupportNobindOfDelayLoadedDLL, tool.SupportNobindOfDelayLoadedDLL) << attrTagT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL) << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) << attrTagT(_SwapRunFromCD, tool.SwapRunFromCD) << attrTagT(_SwapRunFromNet, tool.SwapRunFromNet) << attrTagS(_TargetMachine, toString(tool.TargetMachine)) << attrTagT(_TerminalServerAware, toTriState(tool.TerminalServerAware)) << attrTagT(_TreatLinkerWarningAsErrors, tool.TreatWarningsAsErrors) << attrTagT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration) << attrTagS(_TypeLibraryFile, tool.TypeLibraryFile) << attrTagL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ 0) << attrTagS(_UACExecutionLevel, tool.UACExecutionLevel) << attrTagT(_UACUIAccess, tool.UACUIAccess) << attrTagS(_Version, tool.Version) << closetag(_Link); } void VCXProjectWriter::write(XmlOutput &xml, const VCMIDLTool &tool) { xml << tag(_Midl) << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";") << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrTagT(_ApplicationConfigurationMode, tool.ApplicationConfigurationMode) << attrTagS(_ClientStubFile, tool.ClientStubFile) << attrTagX(_CPreprocessOptions, tool.CPreprocessOptions, " ") << attrTagS(_DefaultCharType, toString(tool.DefaultCharType)) << attrTagS(_DLLDataFileName, tool.DLLDataFileName) << attrTagS(_EnableErrorChecks, toString(tool.EnableErrorChecks)) << attrTagT(_ErrorCheckAllocations, tool.ErrorCheckAllocations) << attrTagT(_ErrorCheckBounds, tool.ErrorCheckBounds) << attrTagT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange) << attrTagT(_ErrorCheckRefPointers, tool.ErrorCheckRefPointers) << attrTagT(_ErrorCheckStubData, tool.ErrorCheckStubData) << attrTagS(_GenerateClientFiles, tool.GenerateClientFiles) << attrTagS(_GenerateServerFiles, tool.GenerateServerFiles) << attrTagT(_GenerateStublessProxies, tool.GenerateStublessProxies) << attrTagT(_GenerateTypeLibrary, tool.GenerateTypeLibrary) << attrTagS(_HeaderFileName, tool.HeaderFileName) << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) << attrTagS(_InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName) << attrTagL(_LocaleID, tool.LocaleID, /*ifNot*/ -1) << attrTagT(_MkTypLibCompatible, tool.MkTypLibCompatible) << attrTagS(_OutputDirectory, tool.OutputDirectory) << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";") << attrTagS(_ProxyFileName, tool.ProxyFileName) << attrTagS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors) << attrTagS(_ServerStubFile, tool.ServerStubFile) << attrTagS(_StructMemberAlignment, toString(tool.StructMemberAlignment)) << attrTagT(_SuppressCompilerWarnings, tool.SuppressCompilerWarnings) << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) << attrTagS(_TargetEnvironment, toString(tool.TargetEnvironment)) << attrTagS(_TypeLibFormat, tool.TypeLibFormat) << attrTagS(_TypeLibraryName, tool.TypeLibraryName) << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";") << attrTagT(_ValidateAllParameters, tool.ValidateAllParameters) << attrTagT(_WarnAsError, tool.WarnAsError) << attrTagS(_WarningLevel, toString(tool.WarningLevel)) << closetag(_Midl); } void VCXProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool) { const QString condition = generateCondition(*tool.config); if ( !tool.AdditionalDependencies.isEmpty() ) { xml << tag("AdditionalInputs") << attrTag("Condition", condition) << valueTagDefX(tool.AdditionalDependencies, "AdditionalInputs", ";"); } if( !tool.CommandLine.isEmpty() ) { xml << tag("Command") << attrTag("Condition", condition) << valueTag(commandLinesForOutput(tool.CommandLine)); } if ( !tool.Description.isEmpty() ) { xml << tag("Message") << attrTag("Condition", condition) << valueTag(tool.Description); } if ( !tool.Outputs.isEmpty() ) { xml << tag("Outputs") << attrTag("Condition", condition) << valueTagDefX(tool.Outputs, "Outputs", ";"); } } void VCXProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool) { xml << tag(_Lib) << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";") << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";") << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrTagX(_ExportNamedFunctions, tool.ExportNamedFunctions, ";") << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";") << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreDefaultLibraryNames, ";") << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) << attrTagS(_OutputFile, tool.OutputFile) << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) << closetag(_Lib); } void VCXProjectWriter::write(XmlOutput &xml, const VCResourceCompilerTool &tool) { xml << tag(_ResourceCompile) << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";") << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") << attrTagS(_Culture, toString(tool.Culture)) << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";") << attrTagS(_ResourceOutputFileName, tool.ResourceOutputFileName) << attrTagT(_ShowProgress, toTriState(tool.ShowProgress)) << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) << closetag(_ResourceCompile); } void VCXProjectWriter::write(XmlOutput &xml, const VCEventTool &tool) { xml << tag(tool.EventName) << tag(_Command) << valueTag(commandLinesForOutput(tool.CommandLine)) << tag(_Message) << valueTag(tool.Description) << closetag(tool.EventName); } void VCXProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool) { Q_UNUSED(xml); Q_UNUSED(tool); // SmartDevice deployment not supported in VS 2010 } void VCXProjectWriter::write(XmlOutput &xml, const VCWinDeployQtTool &tool) { const QString name = QStringLiteral("WinDeployQt_") + tool.config->Name; xml << tag("Target") << attrTag(_Name, name) << attrTag("Condition", generateCondition(*tool.config)) << attrTag("Inputs", "$(OutDir)\\$(TargetName).exe") << attrTag("Outputs", tool.Record) << tag(_Message) << attrTag("Text", tool.CommandLine) << closetag() << tag("Exec") << attrTag("Command", tool.CommandLine) << closetag() << closetag() << tag("Target") << attrTag(_Name, QStringLiteral("PopulateWinDeployQtItems_") + tool.config->Name) << attrTag("Condition", generateCondition(*tool.config)) << attrTag("AfterTargets", "Link") << attrTag("DependsOnTargets", name) << tag("ReadLinesFromFile") << attrTag("File", tool.Record) << tag("Output") << attrTag("TaskParameter", "Lines") << attrTag("ItemName", "DeploymentItems") << closetag() << closetag() << tag(_ItemGroup) << tag("None") << attrTag("Include", "@(DeploymentItems)") << attrTagT("DeploymentContent", _True) << closetag() << closetag() << closetag(); } void VCXProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool) { xml << tag("PropertyGroup") << attrTag("Condition", generateCondition(tool)) << attrTag("Label", "Configuration") << attrTagS(_PlatformToolSet, tool.PlatformToolSet) << attrTagS(_OutputDirectory, tool.OutputDirectory) << attrTagT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage) << attrTagT(_BuildBrowserInformation, tool.BuildBrowserInformation) << attrTagS(_CharacterSet, toString(tool.CharacterSet)) << attrTagS(_ConfigurationType, toString(tool.ConfigurationType)) << attrTagS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean) << attrTagS(_ImportLibrary, tool.ImportLibrary) << attrTagS(_IntermediateDirectory, tool.IntermediateDirectory) << attrTagS(_PrimaryOutput, tool.PrimaryOutput) << attrTagS(_ProgramDatabase, tool.ProgramDatabase) << attrTagT(_RegisterOutput, tool.RegisterOutput) << attrTagS(_UseOfATL, toString(tool.UseOfATL)) << attrTagS(_UseOfMfc, toString(tool.UseOfMfc)) << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization) << attrTagT(_EmbedManifest, tool.manifestTool.EmbedManifest) << closetag(); } void VCXProjectWriter::write(XmlOutput &xml, VCFilter &tool) { Q_UNUSED(xml); Q_UNUSED(tool); // unused in this generator } void VCXProjectWriter::addFilters(VCProject &project, XmlOutput &xmlFilter, const QString &filtername) { bool added = false; for (int i = 0; i < project.SingleProjects.size(); ++i) { const VCFilter filter = project.SingleProjects.at(i).filterByName(filtername); if(!filter.Files.isEmpty() && !added) { xmlFilter << tag("Filter") << attrTag("Include", filtername) << attrTagS("UniqueIdentifier", filter.Guid) << attrTagS("Extensions", filter.Filter) << attrTagT("ParseFiles", filter.ParseFiles) << closetag(); } } } // outputs a given filter for all existing configurations of a project void VCXProjectWriter::outputFilter(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filtername) { QScopedPointer root; if (project.SingleProjects.at(0).flat_files) root.reset(new XFlatNode); else root.reset(new XTreeNode); 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)); } if (!root->hasElements()) return; root->generateXML(xml, xmlFilter, "", project, filtername); // output root tree } static QString stringBeforeFirstBackslash(const QString &str) { int idx = str.indexOf(QLatin1Char('\\')); return idx == -1 ? str : str.left(idx); } // Output all configurations (by filtername) for a file (by info) // A filters config output is in VCFilter.outputFileConfig() void VCXProjectWriter::outputFileConfigs(VCProject &project, XmlOutput &xml, XmlOutput &xmlFilter, const VCFilterFile &info, const QString &filtername) { // In non-flat mode the filter names have directory suffixes, e.g. "Generated Files\subdir". const QString cleanFilterName = stringBeforeFirstBackslash(filtername); // We need to check if the file has any custom build step. // If there is one then it has to be included with "CustomBuild Include" bool hasCustomBuildStep = false; QVarLengthArray data(project.SingleProjects.size()); for (int i = 0; i < project.SingleProjects.size(); ++i) { data[i].filter = project.SingleProjects.at(i).filterByName(cleanFilterName); if (!data[i].filter.Config) // only if the filter is not empty continue; VCFilter &filter = data[i].filter; // Clearing each filter tool filter.useCustomBuildTool = false; filter.useCompilerTool = false; filter.CustomBuildTool = VCCustomBuildTool(); filter.CustomBuildTool.config = filter.Config; filter.CompilerTool = VCCLCompilerTool(); filter.CompilerTool.config = filter.Config; VCFilterFile fileInFilter = filter.findFile(info.file, &data[i].inBuild); data[i].info = fileInFilter; data[i].inBuild &= !fileInFilter.excludeFromBuild; if (data[i].inBuild && filter.addExtraCompiler(fileInFilter)) hasCustomBuildStep = true; } bool fileAdded = false; for (int i = 0; i < project.SingleProjects.size(); ++i) { OutputFilterData *d = &data[i]; if (!d->filter.Config) // only if the filter is not empty continue; if (outputFileConfig(d, xml, xmlFilter, info.file, filtername, fileAdded, hasCustomBuildStep)) { fileAdded = true; } } if ( !fileAdded ) outputFileConfig(xml, xmlFilter, info.file, filtername); xml << closetag(); xmlFilter << closetag(); } bool VCXProjectWriter::outputFileConfig(OutputFilterData *d, XmlOutput &xml, XmlOutput &xmlFilter, const QString &filename, const QString &fullFilterName, bool fileAdded, bool hasCustomBuildStep) { VCFilter &filter = d->filter; if (d->inBuild) { if (filter.Project->usePCH) filter.modifyPCHstage(filename); } else { // Excluded files uses an empty compiler stage if (d->info.excludeFromBuild) filter.useCompilerTool = true; } // Actual XML output ---------------------------------- if (hasCustomBuildStep || filter.useCustomBuildTool || filter.useCompilerTool || !d->inBuild || filter.Name.startsWith("Deployment Files")) { if (hasCustomBuildStep || filter.useCustomBuildTool) { if (!fileAdded) { fileAdded = true; xmlFilter << tag("CustomBuild") << attrTag("Include", Option::fixPathToTargetOS(filename)) << attrTagS("Filter", fullFilterName); xml << tag("CustomBuild") << attrTag("Include", Option::fixPathToTargetOS(filename)); if (filter.Name.startsWith("Form Files") || filter.Name.startsWith("Generated Files") || filter.Name.startsWith("Resource Files") || filter.Name.startsWith("Deployment Files")) xml << attrTagS("FileType", "Document"); } filter.Project->projectWriter->write(xml, filter.CustomBuildTool); } if (!fileAdded) { fileAdded = true; outputFileConfig(xml, xmlFilter, filename, fullFilterName); } const QString condition = generateCondition(*filter.Config); if (!d->inBuild) { xml << tag("ExcludedFromBuild") << attrTag("Condition", condition) << valueTag("true"); } if (filter.Name.startsWith("Deployment Files") && d->inBuild) { xml << tag("DeploymentContent") << attrTag("Condition", condition) << valueTag("true"); } if (filter.useCompilerTool) { if ( !filter.CompilerTool.ForcedIncludeFiles.isEmpty() ) { xml << tag("ForcedIncludeFiles") << attrTag("Condition", condition) << valueTagX(filter.CompilerTool.ForcedIncludeFiles); } if ( !filter.CompilerTool.PrecompiledHeaderThrough.isEmpty() ) { xml << tag("PrecompiledHeaderFile") << attrTag("Condition", condition) << valueTag(filter.CompilerTool.PrecompiledHeaderThrough); } if (filter.CompilerTool.UsePrecompiledHeader != pchUnset) { xml << tag("PrecompiledHeader") << attrTag("Condition", condition) << valueTag(toString(filter.CompilerTool.UsePrecompiledHeader)); } } } return fileAdded; } static bool isFileClCompatible(const QString &filePath) { auto filePathEndsWith = [&filePath] (const QString &ext) { return filePath.endsWith(ext, Qt::CaseInsensitive); }; return std::any_of(Option::cpp_ext.cbegin(), Option::cpp_ext.cend(), filePathEndsWith) || std::any_of(Option::c_ext.cbegin(), Option::c_ext.cend(), filePathEndsWith); } void VCXProjectWriter::outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter, const QString &filePath, const QString &filterName) { const QString nativeFilePath = Option::fixPathToTargetOS(filePath); if (filterName.startsWith("Source Files")) { xmlFilter << tag("ClCompile") << attrTag("Include", nativeFilePath) << attrTagS("Filter", filterName); xml << tag("ClCompile") << attrTag("Include", nativeFilePath); } else if (filterName.startsWith("Header Files")) { xmlFilter << tag("ClInclude") << attrTag("Include", nativeFilePath) << attrTagS("Filter", filterName); xml << tag("ClInclude") << attrTag("Include", nativeFilePath); } else if (filterName.startsWith("Generated Files") || filterName.startsWith("Form Files")) { if (filePath.endsWith(".h")) { xmlFilter << tag("ClInclude") << attrTag("Include", nativeFilePath) << attrTagS("Filter", filterName); xml << tag("ClInclude") << attrTag("Include", nativeFilePath); } else if (isFileClCompatible(filePath)) { xmlFilter << tag("ClCompile") << attrTag("Include", nativeFilePath) << attrTagS("Filter", filterName); xml << tag("ClCompile") << attrTag("Include", nativeFilePath); } else if (filePath.endsWith(".res")) { xmlFilter << tag("CustomBuild") << attrTag("Include", nativeFilePath) << attrTagS("Filter", filterName); xml << tag("CustomBuild") << attrTag("Include", nativeFilePath); } else { xmlFilter << tag("CustomBuild") << attrTag("Include", nativeFilePath) << attrTagS("Filter", filterName); xml << tag("CustomBuild") << attrTag("Include", nativeFilePath); } } else if (filterName.startsWith("Root Files")) { if (filePath.endsWith(".rc")) { xmlFilter << tag("ResourceCompile") << attrTag("Include", nativeFilePath); xml << tag("ResourceCompile") << attrTag("Include", nativeFilePath); } } else { xmlFilter << tag("None") << attrTag("Include", nativeFilePath) << attrTagS("Filter", filterName); xml << tag("None") << attrTag("Include", nativeFilePath); } } QString VCXProjectWriter::generateCondition(const VCConfiguration &config) { return QStringLiteral("'$(Configuration)|$(Platform)'=='") + config.Name + QLatin1Char('\''); } XmlOutput::xml_output VCXProjectWriter::attrTagToolsVersion(const VCConfiguration &config) { if (config.CompilerVersion >= NET2013) return noxml(); return attrTag("ToolsVersion", "4.0"); } QT_END_NAMESPACE