aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel Costa <miguel.costa@qt.io>2018-03-22 18:12:06 +0100
committerMiguel Costa <miguel.costa@qt.io>2018-03-28 10:08:32 +0000
commitf553ff6cb8ccea033e639f02a2373dcf3a8a98fb (patch)
tree4c4d76a0beb01549fd560b459f54d8a79e25f92f
parentef0cf3b7ce3d4ce3cf9ccbf6384e0c9a7d7a2673 (diff)
Improve performance of conversion to Qt/MSBuild
Modified the conversion from custom build steps to Qt/MSBuild such that larger projects can be converted faster. The optimization focused on the code that removes generated items from the project: instead of looking at every item in the project, only .cpp files will now be checked if they are generated sources and should therefore be excluded from the project. To further speed up this process, added an index on the path of .cpp files. Additionally, to provide UI feedback during the conversion procedure, a progress dialog is now displayed when converting whole solutions. Task-number: QTVSADDINBUG-515 Change-Id: Ib9326554bcf99dbff8b6dd0c65d1a44e18ab68b1 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r--src/qtprojectlib/MsBuildProject.cs64
-rw-r--r--src/qtvstools/QtMsBuildConverter.cs65
-rw-r--r--src/qtvstools/Resources.resx10
3 files changed, 100 insertions, 39 deletions
diff --git a/src/qtprojectlib/MsBuildProject.cs b/src/qtprojectlib/MsBuildProject.cs
index aca3f4a8..06d78097 100644
--- a/src/qtprojectlib/MsBuildProject.cs
+++ b/src/qtprojectlib/MsBuildProject.cs
@@ -375,11 +375,12 @@ namespace QtProjectLib
}
bool RemoveGeneratedFiles(
+ string projDir,
List<CustomBuildEval> cbEvals,
string configName,
string itemName,
- IEnumerable<XElement> projectItems,
- IEnumerable<XElement> filterItems)
+ Dictionary<string, XElement> projItemsByPath,
+ Dictionary<string, XElement> filterItemsByPath)
{
//remove items with generated files
bool hasGeneratedFiles = false;
@@ -387,21 +388,21 @@ namespace QtProjectLib
.Where(x => x.ProjectConfig == configName && x.Identity == itemName)
.FirstOrDefault();
if (cbEval != null) {
- var outputFiles = cbEval.Outputs.Split(new char[] { ';' });
+ var outputFiles = cbEval.Outputs
+ .Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(x => HelperFunctions.CanonicalPath(
+ Path.IsPathRooted(x) ? x : Path.Combine(projDir, x)));
+ var outputItems = new List<XElement>();
foreach (var outputFile in outputFiles) {
- if (!string.IsNullOrEmpty(outputFile)) {
- var outputItems = new List<XElement>();
- outputItems.AddRange(projectItems
- .Where(x => HelperFunctions.PathEquals(
- outputFile, (string)x.Attribute("Include"))));
- outputItems.AddRange(filterItems
- .Where(x => HelperFunctions.PathEquals(
- outputFile, (string)x.Attribute("Include"))));
- hasGeneratedFiles |= outputItems.Any();
- foreach (var item in outputItems)
- item.Remove();
- }
+ XElement mocOutput = null;
+ if (projItemsByPath.TryGetValue(outputFile, out mocOutput))
+ outputItems.Add(mocOutput);
+ if (filterItemsByPath.TryGetValue(outputFile, out mocOutput))
+ outputItems.Add(mocOutput);
}
+ hasGeneratedFiles = outputItems.Any();
+ foreach (var item in outputItems)
+ item.Remove();
}
return hasGeneratedFiles;
}
@@ -413,26 +414,32 @@ namespace QtProjectLib
var qtMsBuild = new QtMsBuildContainer(new MsBuildConverterProvider());
qtMsBuild.BeginSetItemProperties();
+ var projDir = Path.GetDirectoryName(this[Files.Project].filePath);
+
var configurations = this[Files.Project].xml
.Elements(ns + "Project")
.Elements(ns + "ItemGroup")
.Elements(ns + "ProjectConfiguration");
- var projectItems = this[Files.Project].xml
+ var projItemsByPath = this[Files.Project].xml
.Elements(ns + "Project")
.Elements(ns + "ItemGroup")
- .Elements()
+ .Elements(ns + "ClCompile")
.Where(x => ((string)x.Attribute("Include"))
- .IndexOfAny(Path.GetInvalidPathChars()) == -1);
-
+ .IndexOfAny(Path.GetInvalidPathChars()) == -1)
+ .ToDictionary(x => HelperFunctions.CanonicalPath(
+ Path.Combine(projDir, (string)x.Attribute("Include"))),
+ StringComparer.InvariantCultureIgnoreCase);
- var filterItems = this[Files.Filters].xml
+ var filterItemsByPath = this[Files.Filters].xml
.Elements(ns + "Project")
.Elements(ns + "ItemGroup")
- .Elements()
- .Where(x => projectItems.Where(y =>
- ((string)x.Attribute("Include")).Equals((string)y.Attribute("Include"),
- StringComparison.InvariantCultureIgnoreCase)).Any());
+ .Elements(ns + "ClCompile")
+ .Where(x => ((string)x.Attribute("Include"))
+ .IndexOfAny(Path.GetInvalidPathChars()) == -1)
+ .ToDictionary(x => HelperFunctions.CanonicalPath(
+ Path.Combine(projDir, (string)x.Attribute("Include"))),
+ StringComparer.InvariantCultureIgnoreCase);
var cppIncludePaths = this[Files.Project].xml
.Elements(ns + "Project")
@@ -518,7 +525,8 @@ namespace QtProjectLib
//remove items with generated files
var hasGeneratedFiles = RemoveGeneratedFiles(
- cbEvals, configName, itemName, projectItems, filterItems);
+ projDir, cbEvals, configName, itemName,
+ projItemsByPath, filterItemsByPath);
//set properties
qtMsBuild.SetItemProperty(qtMoc,
@@ -559,7 +567,8 @@ namespace QtProjectLib
var configName = (string)qtRcc.Attribute("ConfigName");
//remove items with generated files
- RemoveGeneratedFiles(cbEvals, configName, itemName, projectItems, filterItems);
+ RemoveGeneratedFiles(projDir, cbEvals, configName, itemName,
+ projItemsByPath, filterItemsByPath);
//set properties
qtMsBuild.SetItemProperty(qtRcc,
@@ -582,7 +591,8 @@ namespace QtProjectLib
var configName = (string)qtUic.Attribute("ConfigName");
//remove items with generated files
- RemoveGeneratedFiles(cbEvals, configName, itemName, projectItems, filterItems);
+ RemoveGeneratedFiles(projDir, cbEvals, configName, itemName,
+ projItemsByPath, filterItemsByPath);
//set properties
qtMsBuild.SetItemProperty(qtUic,
diff --git a/src/qtvstools/QtMsBuildConverter.cs b/src/qtvstools/QtMsBuildConverter.cs
index 479129a2..23a76803 100644
--- a/src/qtvstools/QtMsBuildConverter.cs
+++ b/src/qtvstools/QtMsBuildConverter.cs
@@ -75,14 +75,64 @@ namespace QtVsTools
return WarningMessage(SR.GetString("CancelConvertingProject"));
}
- foreach (var project in projects) {
- if (!ProjectToQtMsBuild(project, false))
+ var projectPaths = projects.Select(x => x.FullName).ToList();
+
+ string solutionPath = solution.FileName;
+ solution.Close(true);
+
+ IVsThreadedWaitDialog2 waitDialog = null;
+ var waitDialogFactory = (IVsThreadedWaitDialogFactory)Vsix
+ .GetGlobalService(typeof(SVsThreadedWaitDialogFactory));
+ if (waitDialogFactory != null)
+ waitDialogFactory.CreateInstance(out waitDialog);
+ int projCount = 0;
+ if (waitDialog != null)
+ waitDialog.StartWaitDialogWithPercentageProgress(
+ SR.GetString("Resources_QtVsTools"),
+ SR.GetString("ConvertWait"),
+ null, null, null, true, 0, projectPaths.Count, 0);
+ bool canceled = false;
+ foreach (var projectPath in projectPaths) {
+ if (waitDialog != null)
+ waitDialog.UpdateProgress(string.Format(SR.GetString("ConvertProgress"),
+ projCount + 1, projectPaths.Count,
+ Path.GetFileNameWithoutExtension(projectPath)),
+ null, null, projCount, projectPaths.Count, false, out canceled);
+ if (canceled)
+ break;
+ if (!ConvertProject(projectPath))
return false;
+ ++projCount;
+ }
+ if (waitDialog != null) {
+ int dummy;
+ waitDialog.EndWaitDialog(out dummy);
+ }
+ Vsix.Instance.Dte.Solution.Open(solutionPath);
+ if (canceled && projCount < projectPaths.Count) {
+ MessageBox.Show(string.Format(SR.GetString("ConvertCanceled"),
+ projectPaths.Count - projCount), SR.GetString("Resources_QtVsTools"),
+ MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
return true;
}
+ static bool ConvertProject(string pathToProject)
+ {
+ var xmlProject = MsBuildProject.Load(pathToProject);
+ bool ok = (xmlProject != null);
+ if (ok)
+ ok = xmlProject.AddQtMsBuildReferences();
+ if (ok)
+ ok = xmlProject.ConvertCustomBuildToQtMsBuild();
+ if (ok)
+ ok = xmlProject.EnableMultiProcessorCompilation();
+ if (ok)
+ ok = xmlProject.Save();
+ return ok;
+ }
+
public static bool ProjectToQtMsBuild(EnvDTE.Project project, bool askConfirmation = true)
{
if (project == null)
@@ -134,16 +184,7 @@ namespace QtVsTools
string.Format("{0}\r\n{1}", projectName, e.Message)));
}
- var xmlProject = MsBuildProject.Load(pathToProject);
- bool ok = (xmlProject != null);
- if (ok)
- ok = xmlProject.AddQtMsBuildReferences();
- if (ok)
- ok = xmlProject.ConvertCustomBuildToQtMsBuild();
- if (ok)
- ok = xmlProject.EnableMultiProcessorCompilation();
- if (ok)
- ok = xmlProject.Save();
+ bool ok = ConvertProject(pathToProject);
try {
solution.ReloadProject(ref projectGuid);
} catch (Exception e) {
diff --git a/src/qtvstools/Resources.resx b/src/qtvstools/Resources.resx
index d716cd46..67f194f8 100644
--- a/src/qtvstools/Resources.resx
+++ b/src/qtvstools/Resources.resx
@@ -213,6 +213,16 @@
<data name="ConvertSaveConfirmation" xml:space="preserve">
<value>Projects must be saved before conversion. Save projects?</value>
</data>
+ <data name="ConvertWait" xml:space="preserve">
+ <value>Converting solution to Qt/MSBuild...</value>
+ </data>
+ <data name="ConvertProgress" xml:space="preserve">
+ <value>Converting solution to Qt/MSBuild...
+Converting project {0}/{1}: {2}...</value>
+ </data>
+ <data name="ConvertCanceled" xml:space="preserve">
+ <value>Conversion canceled. {0} projects were not converted.</value>
+ </data>
<data name="ErrorConvertingProject" xml:space="preserve">
<value>Error converting project {0}</value>
</data>