Наша сборка Qt VS Tools
giy
2022-09-02 ca47896204482bf4a6979e3838bf7f09f61cebeb
QtVsTools.Core/MsBuildProject.cs
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt VS Tools.
@@ -30,22 +30,22 @@
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using QtVsTools.Core.QtMsBuild;
using System.Text.RegularExpressions;
using Microsoft.Build.Construction;
using Microsoft.Build.Execution;
using Microsoft.Build.Evaluation;
using QtVsTools.VisualStudio;
using QtVsTools.SyntaxAnalysis;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
namespace QtVsTools.Core
{
    using QtMsBuild;
    using SyntaxAnalysis;
    using static HelperFunctions;
    using static RegExpr;
    using static SyntaxAnalysis.RegExpr;
    public class MsBuildProject
    {
@@ -65,7 +65,8 @@
            User,
            Count
        }
        MsBuildXmlFile[] files = new MsBuildXmlFile[(int)Files.Count];
        readonly MsBuildXmlFile[] files = new MsBuildXmlFile[(int)Files.Count];
        MsBuildProject()
        {
@@ -94,7 +95,7 @@
            }
        }
        private static XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
        private static readonly XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
        public static MsBuildProject Load(string pathToProject)
        {
@@ -293,12 +294,8 @@
            if (ConfigCondition == null)
                return false;
            // Get default Qt dir
            string defaultQtDir = null;
            var defaultVersionName = QtVersionManager.The().GetDefaultVersion();
            var defaultVersion = QtVersionManager.The().GetVersionInfo(defaultVersionName);
            if (defaultVersion != null)
                defaultQtDir = defaultVersion.qtDir;
            // Get project configurations
            var configs = this[Files.Project].xml
@@ -314,15 +311,6 @@
                .FirstOrDefault();
            if (globals == null)
                return false;
            // Get project configuration properties
            var configProps = this[Files.Project].xml
                .Elements(ns + "Project")
                .Elements(ns + "PropertyGroup")
                .Where(pg =>
                    (string)pg.Attribute("Label") == "Configuration"
                    && pg.Attribute("Condition") != null)
                .ToDictionary(pg => (string)pg.Attribute("Condition"));
            // Set Qt project format version
            var projKeyword = globals
@@ -386,10 +374,8 @@
                foreach (var pg in uncategorizedPropertyGroups) {
                    foreach (var p in pg.Elements().ToList()) {
                        var condition = p.Attribute("Condition") ?? pg.Attribute("Condition");
                        XElement configPropertyGroup = null;
                        if (condition != null)
                            propertyGroups.TryGetValue((string)condition, out configPropertyGroup);
                        if (configPropertyGroup != null) {
                        if (condition != null && propertyGroups
                            .TryGetValue((string)condition, out XElement configPropertyGroup)) {
                            p.Remove();
                            p.SetAttributeValue("Condition", null);
                            configPropertyGroup.Add(p);
@@ -535,12 +521,10 @@
                foreach (var configQtSettings in qtSettings) {
                    var configCondition = (string)configQtSettings.Attribute("Condition");
                    XElement oldConfigQtInstall;
                    if (oldQtInstall.TryGetValue(configCondition, out oldConfigQtInstall))
                    if (oldQtInstall.TryGetValue(configCondition, out XElement oldConfigQtInstall))
                        configQtSettings.Add(oldConfigQtInstall);
                    XElement oldConfigQtSettings;
                    if (oldQtSettings.TryGetValue(configCondition, out oldConfigQtSettings)) {
                    if (oldQtSettings.TryGetValue(configCondition, out XElement oldConfigQtSettings)) {
                        foreach (var qtSetting in oldConfigQtSettings.Elements())
                            configQtSettings.Add(qtSetting);
                    }
@@ -600,6 +584,11 @@
                .Elements(ns + "ItemDefinitionGroup")
                .Elements(ns + "Link");
            var resourceCompiler = this[Files.Project].xml
                .Elements(ns + "Project")
                .Elements(ns + "ItemDefinitionGroup")
                .Elements(ns + "ResourceCompile");
            // Qt module names, to copy to QtModules property
            var moduleNames = new HashSet<string>();
@@ -613,9 +602,9 @@
            var moduleLibs = new HashSet<string>();
            // Go through all known Qt modules and check which ones are currently being used
            foreach (var module in QtModules.Instance.GetAvailableModules()) {
            foreach (var module in QtModules.Instance.GetAvailableModules(defaultVersion.qtMajor)) {
                if (IsModuleUsed(module, compiler, linker)) {
                if (IsModuleUsed(module, compiler, linker, resourceCompiler)) {
                    // Qt module names, to copy to QtModules property
                    if (!string.IsNullOrEmpty(module.proVarQT))
@@ -670,6 +659,12 @@
                    .Select(x => Unquote(x))
                    // Exclude paths rooted on $(QTDIR)
                    .Where(x => !x.StartsWith("$(QTDIR)", IGNORE_CASE))));
            }
            // Remove Qt module macros from resource compiler properties
            foreach (var defines in resourceCompiler.Elements(ns + "PreprocessorDefinitions")) {
                defines.SetValue(string.Join(";", defines.Value.Split(';')
                    .Where(x => !moduleDefines.Contains(x))));
            }
            // Add Qt module names to QtModules project property
@@ -778,7 +773,8 @@
        bool IsModuleUsed(
            QtModule module,
            IEnumerable<XElement> compiler,
            IEnumerable<XElement> linker)
            IEnumerable<XElement> linker,
            IEnumerable<XElement> resourceCompiler)
        {
            // Module .lib is present in linker additional dependencies
            if (linker.Elements(ns + "AdditionalDependencies")
@@ -788,8 +784,15 @@
                return true;
            }
            // Module macro is present in pre-processor definitions
            // Module macro is present in the compiler pre-processor definitions
            if (compiler.Elements(ns + "PreprocessorDefinitions")
                .SelectMany(x => x.Value.Split(';'))
                .Any(x => module.Defines.Contains(x))) {
                return true;
            }
            // Module macro is present in resource compiler pre-processor definitions
            if (resourceCompiler.Elements(ns + "PreprocessorDefinitions")
                .SelectMany(x => x.Value.Split(';'))
                .Any(x => module.Defines.Contains(x))) {
                return true;
@@ -958,9 +961,9 @@
                        commandLine = replace(row.itemName, commandLine);
                    //
                    //   * Configuration/platform, e.g. x64\Debug --> $(Platform)\$(Configuration)
                    commandLine = commandLine
                        .Replace(configName, "$(Configuration)",
                            StringComparison.InvariantCultureIgnoreCase)
                    //   * ignore any word other than the expected configuration, e.g. lrelease.exe
                    commandLine = Regex.Replace(commandLine, @"\b" + configName + @"\b",
                            "$(Configuration)", RegexOptions.IgnoreCase)
                        .Replace(platformName, "$(Platform)",
                            StringComparison.InvariantCultureIgnoreCase);
@@ -969,8 +972,7 @@
                        evaluator.Properties.Add(configProp.Name.LocalName, (string)configProp);
                    if (!qtMsBuild.SetCommandLine(itemType, item, commandLine, evaluator)) {
                        int lineNumber = 1;
                        var errorLine = row.command as IXmlLineInfo;
                        if (errorLine != null && errorLine.HasLineInfo())
                        if (row.command is IXmlLineInfo errorLine && errorLine.HasLineInfo())
                            lineNumber = errorLine.LineNumber;
                        Messages.Print(string.Format(
@@ -1059,8 +1061,7 @@
                    return (string)cbt.Attribute("Include");
                }
            }
            string ouputFile;
            if (!properties.TryGetValue(QtMoc.Property.InputFile, out ouputFile))
            if (!properties.TryGetValue(QtMoc.Property.InputFile, out string ouputFile))
                return (string)cbt.Attribute("Include");
            return ouputFile;
        }
@@ -1085,8 +1086,7 @@
                        Path.IsPathRooted(x) ? x : Path.Combine(projDir, x)));
                var outputItems = new List<XElement>();
                foreach (var outputFile in outputFiles) {
                    List<XElement> mocOutput = null;
                    if (projItemsByPath.TryGetValue(outputFile, out mocOutput)) {
                    if (projItemsByPath.TryGetValue(outputFile, out List<XElement> mocOutput)) {
                        outputItems.AddRange(mocOutput);
                        hasGeneratedFiles |= hasGeneratedFiles ? true : mocOutput
                            .Where(x => !x.Elements(ns + "ExcludedFromBuild")
@@ -1469,17 +1469,16 @@
        class MSBuildEvaluator : IVSMacroExpander, IDisposable
        {
            MsBuildXmlFile projFile;
            string tempProjFilePath;
            XElement evaluateTarget;
            XElement evaluateProperty;
            ProjectRootElement projRoot;
            public Dictionary<string, string> expansionCache;
            private readonly MsBuildXmlFile projFile;
            private string tempProjFilePath;
            private XElement evaluateTarget;
            private XElement evaluateProperty;
            private ProjectRootElement projRoot;
            private readonly Dictionary<string, string> expansionCache;
            public Dictionary<string, string> Properties
            {
                get;
                private set;
            }
            public MSBuildEvaluator(MsBuildXmlFile projFile)
@@ -1522,8 +1521,7 @@
            public string ExpandString(string stringToExpand)
            {
                string expandedString;
                if (TryExpansionCache(stringToExpand, out expandedString))
                if (TryExpansionCache(stringToExpand, out string expandedString))
                    return expandedString;
                if (evaluateTarget == null) {
@@ -1649,7 +1647,7 @@
            return true;
        }
        static Regex ConditionParser =
        static readonly Regex ConditionParser =
            new Regex(@"\'\$\(Configuration[^\)]*\)\|\$\(Platform[^\)]*\)\'\=\=\'([^\']+)\'");
        class MsBuildConverterProvider : IPropertyStorageProvider