From 28955625a024d212758ca992c250ecf8f18462f3 Mon Sep 17 00:00:00 2001 From: Miguel Costa Date: Tue, 19 Dec 2017 15:15:49 +0100 Subject: Fix bugs in handling of .cpp moc source Reworked the property definition strategy for Qt/MSBuild properties (i.e. deciding when to set properties at project or item level). The previous approach did not handle correctly the case of .cpp moc files. Also fixed a bug in RefreshMocStep that was causing build failure with .cpp moc files when the moc output path was modified in the Qt Project Settings dialog. Change-Id: Icae4ffa7aa42e679a4cfcb87ee866dc8f7f01cf6 Reviewed-by: Oliver Wolff --- src/qtprojectlib/QtMsBuild.cs | 223 ++++++++++++++++++++++++++---------------- src/qtprojectlib/QtProject.cs | 19 +++- 2 files changed, 155 insertions(+), 87 deletions(-) diff --git a/src/qtprojectlib/QtMsBuild.cs b/src/qtprojectlib/QtMsBuild.cs index ff22e1f4..539fe01a 100644 --- a/src/qtprojectlib/QtMsBuild.cs +++ b/src/qtprojectlib/QtMsBuild.cs @@ -124,20 +124,42 @@ namespace QtProjectLib.QtMsBuild public string PropertyValue; public object PropertyStorage; - public bool Matches(ItemPropertyChange newChange) + public void CopyFrom(ItemPropertyChange change) { - return - ConfigName == newChange.ConfigName - && ItemTypeName == newChange.ItemTypeName - && PropertyName == newChange.PropertyName - && ItemName == newChange.ItemName; + ConfigName = change.ConfigName; + ItemTypeName = change.ItemTypeName; + ItemName = change.ItemName; + PropertyName = change.PropertyName; + PropertyValue = change.PropertyValue; + PropertyStorage = change.PropertyStorage; } + + public bool IsMocSource + { + get + { + return ItemTypeName == QtMoc.ItemTypeName + && !HelperFunctions.IsHeaderFile(ItemName); + } + } + public string GroupKey { get { return string.Join(",", new string[] { - ConfigName, ItemTypeName, PropertyName, PropertyValue + ConfigName, ItemTypeName, PropertyName, PropertyValue, + IsMocSource.ToString() + }); + } + } + + public string Key + { + get + { + return string.Join(",", new string[] { + ConfigName, ItemTypeName, PropertyName, ItemName }); } } @@ -148,9 +170,23 @@ namespace QtProjectLib.QtMsBuild return provider.GetItems(GetProject(), itemType, configName); } - int GetItemCount(string itemType, string configName = "") + int GetItemCount(string itemType, bool? isMocSource = null, string configName = "") { - return GetItems(itemType, configName).Count(); + var items = GetItems(itemType, configName); + if (!isMocSource.HasValue) { + return items + .Count(); + } else if (!isMocSource.Value) { + return items.Where(x => + provider.GetItemType(x) != QtMoc.ItemTypeName + || HelperFunctions.IsHeaderFile(provider.GetItemName(x))) + .Count(); + } else { + return items.Where(x => + provider.GetItemType(x) == QtMoc.ItemTypeName + && !HelperFunctions.IsHeaderFile(provider.GetItemName(x))) + .Count(); + } } object GetProjectConfiguration(string configName) @@ -158,41 +194,59 @@ namespace QtProjectLib.QtMsBuild return provider.GetProjectConfiguration(GetProject(), configName); } - Dictionary> itemPropertyChanges + Dictionary itemPropertyChanges + = new Dictionary(); + Dictionary> itemPropertyChangesGrouped = new Dictionary>(); bool pendingChanges = false; - void AddChange(ItemPropertyChange change) + void AddChange(ItemPropertyChange newChange) { + ItemPropertyChange oldChange; + if (itemPropertyChanges.TryGetValue(newChange.Key, out oldChange)) { + if (oldChange.GroupKey == newChange.GroupKey) { + oldChange.CopyFrom(newChange); + return; + } else { + RemoveChange(oldChange); + } + } + List changeGroup; - if (!itemPropertyChanges.TryGetValue(change.GroupKey, out changeGroup)) { - itemPropertyChanges.Add( - change.GroupKey, + if (!itemPropertyChangesGrouped.TryGetValue(newChange.GroupKey, out changeGroup)) { + itemPropertyChangesGrouped.Add( + newChange.GroupKey, changeGroup = new List()); } - changeGroup.Add(change); + changeGroup.Add(newChange); + itemPropertyChanges.Add(newChange.Key, newChange); + } + + void RemoveChange(ItemPropertyChange change) + { + List changeGroup; + if (itemPropertyChangesGrouped.TryGetValue(change.GroupKey, out changeGroup)) { + changeGroup.Remove(change); + if (changeGroup.Count == 0) + itemPropertyChangesGrouped.Remove(change.GroupKey); + } + itemPropertyChanges.Remove(change.Key); } object GetProject() { - if (itemPropertyChanges.Count == 0) - return null; - var changeGroup = itemPropertyChanges.First().Value; - if (changeGroup == null) - return null; - var change = changeGroup.FirstOrDefault(); + var change = itemPropertyChanges.Values.FirstOrDefault(); if (change == null) return null; return provider.GetParentProject(change.PropertyStorage); } - - public bool BeginSetItemProperties() { if (pendingChanges) return false; itemPropertyChanges.Clear(); + itemPropertyChangesGrouped.Clear(); pendingChanges = true; return true; } @@ -226,81 +280,87 @@ namespace QtProjectLib.QtMsBuild if (!EndSetItemProperties()) return false; } else { - ItemPropertyChange oldChange = null; - List changeGroup; - if (itemPropertyChanges.TryGetValue(newChange.GroupKey, out changeGroup)) { - oldChange = changeGroup.Where(x => x.Matches(newChange)).FirstOrDefault(); - } - if (oldChange != null) - oldChange.PropertyValue = newChange.PropertyValue; - else - AddChange(newChange); + AddChange(newChange); } return true; } - public bool EndSetItemProperties() + bool SetGroupItemProperties(List changeGroup) { - if (!pendingChanges) + //grouped by configName, itemTypeName, propertyName, propertyValue, isMocSource + var firstChange = changeGroup.FirstOrDefault(); + if (firstChange == null) return false; + string configName = firstChange.ConfigName; + string itemTypeName = firstChange.ItemTypeName; + string propertyName = firstChange.PropertyName; + string propertyValue = firstChange.PropertyValue; + bool isMocSource = firstChange.IsMocSource; + int itemCount = GetItemCount(itemTypeName, isMocSource, configName); + int groupCount = changeGroup.Count; + object projConfig = GetProjectConfiguration(configName); + + if (!isMocSource && groupCount == itemCount) { + //all items are setting the same value for this property + // -> set at project level + if (!SetPropertyValueByName( + projConfig, + itemTypeName, + propertyName, + propertyValue)) { + return false; + } - foreach (var changeGroup in itemPropertyChanges.Values) { - //grouped by configName, itemTypeName, propertyName, propertyValue - var firstChange = changeGroup.FirstOrDefault(); - if (firstChange == null) - continue; - string configName = firstChange.ConfigName; - string itemTypeName = firstChange.ItemTypeName; - string propertyName = firstChange.PropertyName; - string propertyValue = firstChange.PropertyValue; - int itemCount = GetItemCount(itemTypeName, configName); - int groupCount = changeGroup.Count; - object projConfig = GetProjectConfiguration(configName); - - if (groupCount == itemCount) { - //all items are setting the same value for this property - // -> set at project level - if (!SetPropertyValueByName( - projConfig, - itemTypeName, - propertyName, - propertyValue)) { + // -> remove old property from each item + foreach (var change in changeGroup) { + if (!DeletePropertyByName( + change.PropertyStorage, + change.ItemTypeName, + change.PropertyName)) { return false; } - // -> remove old property from each item - foreach (var change in changeGroup) { - if (!DeletePropertyByName( + } + } else { + //different property values per item + // -> set at each item + foreach (var change in changeGroup) { + if (GetPropertyValueByName( + projConfig, + change.ItemTypeName, + change.PropertyName) != change.PropertyValue) { + if (!SetPropertyValueByName( change.PropertyStorage, change.ItemTypeName, - change.PropertyName)) { + change.PropertyName, + change.PropertyValue)) { return false; } } - } else { - //different property values per item - // -> set at each item - foreach (var change in changeGroup) { - if (GetPropertyValueByName( - projConfig, - change.ItemTypeName, - change.PropertyName) != change.PropertyValue) { - if (!SetPropertyValueByName( - change.PropertyStorage, - change.ItemTypeName, - change.PropertyName, - change.PropertyValue)) { - return false; - } - - } - } } } + return true; + } + + public bool EndSetItemProperties() + { + if (!pendingChanges) + return false; + + var changeGroupsNormal = itemPropertyChangesGrouped.Values + .Where(x => x.Any() && !x.First().IsMocSource); + foreach (var changeGroup in changeGroupsNormal) + SetGroupItemProperties(changeGroup); + + var changeGroupsMocSource = itemPropertyChangesGrouped.Values + .Where(x => x.Any() && x.First().IsMocSource); + foreach (var changeGroup in changeGroupsMocSource) + SetGroupItemProperties(changeGroup); itemPropertyChanges.Clear(); + itemPropertyChangesGrouped.Clear(); pendingChanges = false; return true; } @@ -321,15 +381,10 @@ namespace QtProjectLib.QtMsBuild ItemName = itemName, PropertyName = propertyName }; - - var changes = itemPropertyChanges.Values - .SelectMany(x => x) - .Where(x => x.Matches(change)); - - if (!changes.Any()) + if (!itemPropertyChanges.TryGetValue(change.Key, out change)) return null; - return changes.First().PropertyValue; + return change.PropertyValue; } public string GetPropertyChangedValue( diff --git a/src/qtprojectlib/QtProject.cs b/src/qtprojectlib/QtProject.cs index 69d18b9a..54aef57b 100644 --- a/src/qtprojectlib/QtProject.cs +++ b/src/qtprojectlib/QtProject.cs @@ -2575,7 +2575,7 @@ namespace QtProjectLib VCCustomBuildTool tool = null; VCFile mocable = null; var customBuildConfig = config; - if (isHeaderFile) { + if (isHeaderFile || vcfile.ItemType == QtMoc.ItemTypeName) { mocable = vcfile; if (vcfile.ItemType == "CustomBuild") tool = HelperFunctions.GetCustomBuildTool(config); @@ -2619,12 +2619,22 @@ namespace QtProjectLib StringComparison.OrdinalIgnoreCase) == -1) continue; - var srcMocFile = GetSourceFileForMocStep(mocable); - var cppFile = GetCppFileForMocStep(mocable); + VCFile srcMocFile, cppFile; + if (vcfile.ItemType == QtMoc.ItemTypeName + && HelperFunctions.IsSourceFile(vcfile.ItemName)) { + srcMocFile = cppFile = vcfile; + } else { + srcMocFile = GetSourceFileForMocStep(mocable); + cppFile = GetCppFileForMocStep(mocable); + } if (srcMocFile == null) continue; var mocableIsCPP = (srcMocFile == cppFile); + var cppItemType = (cppFile != null) ? cppFile.ItemType : ""; + if (cppFile != null && cppItemType != "ClCompile") + cppFile.ItemType = "ClCompile"; + string pchParameters = null; VCFileConfiguration defineIncludeConfig = null; CompilerToolWrapper compiler = null; @@ -2658,6 +2668,9 @@ namespace QtProjectLib pchParameters, outputFileName); + if (cppFile != null && cppItemType != "ClCompile") + cppFile.ItemType = cppItemType; + // The tool's command line automatically gets a trailing "\r\n". // We have to remove it to make the check below work. var origCommandLine = commandLine; -- cgit v1.2.3