diff options
author | Miguel Costa <miguel.costa@qt.io> | 2022-02-10 13:54:21 +0100 |
---|---|---|
committer | Miguel Costa <miguel.costa@qt.io> | 2022-02-11 11:47:20 +0000 |
commit | 3c16ccccb46f978d94540400ad715fd2a1d4df35 (patch) | |
tree | bea7ab773a977e52a32cd9042c7467b3aaa96011 | |
parent | da286a21d05828993a935b2fefc59ff8fb7e79cc (diff) |
Fix background build warnings
Change-Id: I18a58723209b459e94c3412f026e82ba5eca5f6e
Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
-rw-r--r-- | QtVsTools.Package/Editors/Editor.QtDesigner.cs | 2 | ||||
-rw-r--r-- | QtVsTools.Package/Package/QtProjectContextMenu.cs | 2 | ||||
-rw-r--r-- | QtVsTools.Package/Package/QtSolutionContextMenu.cs | 2 | ||||
-rw-r--r-- | QtVsTools.Package/Package/Translation.cs | 3 | ||||
-rw-r--r-- | QtVsTools.Package/QtMsBuild/QtProjectBuild.cs | 296 | ||||
-rw-r--r-- | QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs | 12 | ||||
-rw-r--r-- | QtVsTools.Package/QtMsBuild/QtProjectTracker.cs | 33 |
7 files changed, 193 insertions, 157 deletions
diff --git a/QtVsTools.Package/Editors/Editor.QtDesigner.cs b/QtVsTools.Package/Editors/Editor.QtDesigner.cs index 9aa580a9..49c988a9 100644 --- a/QtVsTools.Package/Editors/Editor.QtDesigner.cs +++ b/QtVsTools.Package/Editors/Editor.QtDesigner.cs @@ -65,7 +65,7 @@ namespace QtVsTools.Editors Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread(); var project = document.ProjectItem?.ContainingProject; - if (project == null || !QtProjectTracker.IsTracked(project)) + if (project == null || !QtProjectTracker.IsTracked(project.FullName)) return; string filePath = document.FullName; string[] itemId = new[] { document.ProjectItem?.Name }; diff --git a/QtVsTools.Package/Package/QtProjectContextMenu.cs b/QtVsTools.Package/Package/QtProjectContextMenu.cs index 21c7cc49..eac1c052 100644 --- a/QtVsTools.Package/Package/QtProjectContextMenu.cs +++ b/QtVsTools.Package/Package/QtProjectContextMenu.cs @@ -175,7 +175,7 @@ namespace QtVsTools break; case CommandId.ProjectRefreshIntelliSense: { var selectedProject = HelperFunctions.GetSelectedProject(QtVsToolsPackage.Instance.Dte); - var tracker = QtProjectTracker.Get(selectedProject); + var tracker = QtProjectTracker.Get(selectedProject, selectedProject.FullName); QtProjectIntellisense.Refresh(tracker.Project); } break; diff --git a/QtVsTools.Package/Package/QtSolutionContextMenu.cs b/QtVsTools.Package/Package/QtSolutionContextMenu.cs index 561e92c3..a10f86a7 100644 --- a/QtVsTools.Package/Package/QtSolutionContextMenu.cs +++ b/QtVsTools.Package/Package/QtSolutionContextMenu.cs @@ -162,7 +162,7 @@ namespace QtVsTools case (int)CommandId.SolutionEnableProjectTracking: { foreach (var project in HelperFunctions.ProjectsInSolution(dte)) { if (HelperFunctions.IsQtProject(project)) - QtProjectTracker.Get(project); + QtProjectTracker.Get(project, project.FullName); } } break; diff --git a/QtVsTools.Package/Package/Translation.cs b/QtVsTools.Package/Package/Translation.cs index 7607a34b..ab5d6aaa 100644 --- a/QtVsTools.Package/Package/Translation.cs +++ b/QtVsTools.Package/Package/Translation.cs @@ -150,7 +150,8 @@ namespace QtVsTools if (selectedFiles != null) properties["SelectedFiles"] = string.Join(";", selectedFiles); - QtProjectBuild.StartBuild(project, activeConfigId, properties, new[] { target }); + QtProjectBuild.StartBuild( + project, project.FullName, activeConfigId, properties, new[] { target }); } } diff --git a/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs b/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs index f2b3d1da..88fdf800 100644 --- a/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs +++ b/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs @@ -69,6 +69,7 @@ namespace QtVsTools.QtMsBuild .GetService<SVsTaskStatusCenterService, IVsTaskStatusCenterService>()); EnvDTE.Project Project { get; set; } + VCProject VcProject { get; set; } UnconfiguredProject UnconfiguredProject { get; set; } ConfiguredProject ConfiguredProject { get; set; } Dictionary<string, string> Properties { get; set; } @@ -79,6 +80,7 @@ namespace QtVsTools.QtMsBuild public static void StartBuild( EnvDTE.Project project, + string projectPath, string configName, Dictionary<string, string> properties, IEnumerable<string> targets, @@ -89,11 +91,13 @@ namespace QtVsTools.QtMsBuild if (configName == null) throw new ArgumentException("Configuration name cannot be null."); - _ = Task.Run(() => StartBuildAsync(project, configName, properties, targets, verbosity)); + _ = Task.Run(() => StartBuildAsync( + project, projectPath, configName, properties, targets, verbosity)); } public static async Task StartBuildAsync( EnvDTE.Project project, + string projectPath, string configName, Dictionary<string, string> properties, IEnumerable<string> targets, @@ -105,16 +109,16 @@ namespace QtVsTools.QtMsBuild throw new ArgumentException("Configuration name cannot be null."); RequestTimer.Restart(); + var tracker = QtProjectTracker.Get(project, projectPath); + await tracker.Initialized; + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { Messages.Print(string.Format( "{0:HH:mm:ss.FFF} QtProjectBuild({1}): Request [{2}] {3}", DateTime.Now, Thread.CurrentThread.ManagedThreadId, - configName, project.FullName)); + configName, tracker.UnconfiguredProject.FullPath)); } - var tracker = QtProjectTracker.Get(project); - await tracker.Initialized; - var knownConfigs = await tracker.UnconfiguredProject.Services .ProjectConfigurationsService.GetKnownProjectConfigurationsAsync(); @@ -133,6 +137,7 @@ namespace QtVsTools.QtMsBuild BuildQueue.Enqueue(new QtProjectBuild() { Project = project, + VcProject = tracker.VcProject, UnconfiguredProject = tracker.UnconfiguredProject, ConfiguredProject = configuredProject, Properties = properties?.ToDictionary(x => x.Key, x => x.Value), @@ -200,6 +205,134 @@ namespace QtVsTools.QtMsBuild } } + async Task<bool> BuildProjectAsync(ProjectWriteLockReleaser writeAccess) + { + var msBuildProject = await writeAccess.GetProjectAsync(ConfiguredProject); + + var solutionPath = QtProjectTracker.SolutionPath; + var configProps = new Dictionary<string, string>( + ConfiguredProject.ProjectConfiguration.Dimensions.ToImmutableDictionary()) + { + { "SolutionPath", solutionPath }, + { "SolutionFileName", Path.GetFileName(solutionPath) }, + { "SolutionName", Path.GetFileNameWithoutExtension(solutionPath) }, + { "SolutionExt", Path.GetExtension(solutionPath) }, + { "SolutionDir", Path.GetDirectoryName(solutionPath).TrimEnd('\\') + '\\' } + }; + + foreach (var property in Properties) + configProps[property.Key] = property.Value; + + var projectInstance = new ProjectInstance(msBuildProject.Xml, + configProps, null, new ProjectCollection()); + + var loggerVerbosity = LoggerVerbosity; + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) + loggerVerbosity = QtVsToolsPackage.Instance.Options.BuildLoggerVerbosity; + var buildParams = new BuildParameters() + { + Loggers = (loggerVerbosity != LoggerVerbosity.Quiet) + ? new[] { new QtProjectLogger() { Verbosity = loggerVerbosity } } + : null + }; + + var buildRequest = new BuildRequestData(projectInstance, + Targets.ToArray(), + hostServices: null, + flags: BuildRequestDataFlags.ProvideProjectStateAfterBuild); + + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { + Messages.Print(string.Format( + "{0:HH:mm:ss.FFF} QtProjectBuild({1}): Build [{2}] {3}", + DateTime.Now, Thread.CurrentThread.ManagedThreadId, + ConfiguredProject.ProjectConfiguration.Name, + UnconfiguredProject.FullPath)); + Messages.Print("=== Targets"); + foreach (var target in buildRequest.TargetNames) + Messages.Print(string.Format(" {0}", target)); + Messages.Print("=== Properties"); + foreach (var property in Properties) { + Messages.Print(string.Format(" {0}={1}", + property.Key, property.Value)); + } + } + + BuildResult result = null; + while (result == null) { + try { + result = BuildManager.DefaultBuildManager.Build( + buildParams, buildRequest); + } catch (InvalidOperationException) { + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { + Messages.Print(string.Format( + "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] " + + "Warning: Another build is in progress; waiting...", + DateTime.Now, + Thread.CurrentThread.ManagedThreadId, + ConfiguredProject.ProjectConfiguration.Name)); + } + await Task.Delay(3000); + } + } + + if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { + string resMsg; + StringBuilder resInfo = new StringBuilder(); + if (result?.OverallResult == BuildResultCode.Success) { + resMsg = "Build ok"; + } else { + resMsg = "Build FAIL"; + if (result == null) { + resInfo.AppendLine("####### Build returned 'null'"); + } else { + resInfo.AppendLine("####### Build returned 'Failure' code"); + if (result.ResultsByTarget != null) { + foreach (var tr in result.ResultsByTarget) { + var res = tr.Value; + if (res.ResultCode != TargetResultCode.Failure) + continue; + resInfo.AppendFormat("### Target '{0}' FAIL\r\n", tr.Key); + if (res.Items != null && res.Items.Length > 0) { + resInfo.AppendFormat( + "Items: {0}\r\n", string.Join(", ", res.Items + .Select(it => it.ItemSpec))); + } + var e = tr.Value?.Exception; + if (e != null) { + resInfo.AppendFormat( + "Exception: {0}\r\nStacktrace:\r\n{1}\r\n", + e.Message, e.StackTrace); + } + } + } + } + } + Messages.Print(string.Format( + "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] {3}\r\n{4}", + DateTime.Now, Thread.CurrentThread.ManagedThreadId, + ConfiguredProject.ProjectConfiguration.Name, + resMsg, resInfo.ToString())); + } + + bool ok = false; + if (result == null + || result.ResultsByTarget == null + || result.OverallResult != BuildResultCode.Success) { + Messages.Print(string.Format("{0}: background build FAILED!", + Path.GetFileName(UnconfiguredProject.FullPath))); + } else { + var checkResults = result.ResultsByTarget + .Where(x => Targets.Contains(x.Key)) + .Select(x => x.Value); + ok = checkResults.Any() + && checkResults.All(x => x.ResultCode == TargetResultCode.Success); + if (ok) + msBuildProject.MarkDirty(); + } + await writeAccess.ReleaseAsync(); + return ok; + } + async Task BuildAsync() { if (LoggerVerbosity != LoggerVerbosity.Quiet) { @@ -209,7 +342,7 @@ namespace QtVsTools.QtMsBuild * Properties: {1} * Targets: {2} ", - /*{0}*/ Project.Name, + /*{0}*/ Path.GetFileNameWithoutExtension(UnconfiguredProject.FullPath), /*{1}*/ string.Join("", Properties .Select(property => string.Format(@" {0} = {1}", /*{0}*/ property.Key, /*{1}*/ property.Value))), @@ -220,148 +353,38 @@ namespace QtVsTools.QtMsBuild bool ok = false; try { - ProjectWriteLockReleaser writeAccess; var timer = ConcurrentStopwatch.StartNew(); while (timer.IsRunning) { try { - writeAccess = await lockService.WriteLockAsync(); +#if VS2017 + using (var writeAccess = await lockService.WriteLockAsync()) + ok = await BuildProjectAsync(writeAccess); +#else + await lockService.WriteLockAsync( + async (ProjectWriteLockReleaser writeAccess) => + { + ok = await BuildProjectAsync(writeAccess); + }); +#endif timer.Stop(); } catch (InvalidOperationException) { if (timer.ElapsedMilliseconds >= 5000) throw; +#if VS2017 using (var readAccess = await lockService.ReadLockAsync()) await readAccess.ReleaseAsync(); +#else + await lockService.ReadLockAsync( + async (ProjectLockReleaser readAccess) => + { + await readAccess.ReleaseAsync(); + }); +#endif } } - using (writeAccess) { - var msBuildProject = await writeAccess.GetProjectAsync(ConfiguredProject); - - var solutionPath = QtProjectTracker.SolutionPath; - var configProps = new Dictionary<string, string>( - ConfiguredProject.ProjectConfiguration.Dimensions.ToImmutableDictionary()) - { - { "SolutionPath", solutionPath }, - { "SolutionFileName", Path.GetFileName(solutionPath) }, - { "SolutionName", Path.GetFileNameWithoutExtension(solutionPath) }, - { "SolutionExt", Path.GetExtension(solutionPath) }, - { "SolutionDir", Path.GetDirectoryName(solutionPath).TrimEnd('\\') + '\\' } - }; - - foreach (var property in Properties) - configProps[property.Key] = property.Value; - - var projectInstance = new ProjectInstance(msBuildProject.Xml, - configProps, null, new ProjectCollection()); - - var loggerVerbosity = LoggerVerbosity; - if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) - loggerVerbosity = QtVsToolsPackage.Instance.Options.BuildLoggerVerbosity; - var buildParams = new BuildParameters() - { - Loggers = (loggerVerbosity != LoggerVerbosity.Quiet) - ? new[] { new QtProjectLogger() { Verbosity = loggerVerbosity } } - : null - }; - - var buildRequest = new BuildRequestData(projectInstance, - Targets.ToArray(), - hostServices: null, - flags: BuildRequestDataFlags.ProvideProjectStateAfterBuild); - - if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { - Messages.Print(string.Format( - "{0:HH:mm:ss.FFF} QtProjectBuild({1}): Build [{2}] {3}", - DateTime.Now, Thread.CurrentThread.ManagedThreadId, - ConfiguredProject.ProjectConfiguration.Name, - UnconfiguredProject.FullPath)); - Messages.Print("=== Targets"); - foreach (var target in buildRequest.TargetNames) - Messages.Print(string.Format(" {0}", target)); - Messages.Print("=== Properties"); - foreach (var property in Properties) { - Messages.Print(string.Format(" {0}={1}", - property.Key, property.Value)); - } - } - - BuildResult result = null; - while (result == null) { - try { - result = BuildManager.DefaultBuildManager.Build( - buildParams, buildRequest); - } catch (InvalidOperationException) { - if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { - Messages.Print(string.Format( - "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] " - + "Warning: Another build is in progress; waiting...", - DateTime.Now, - Thread.CurrentThread.ManagedThreadId, - ConfiguredProject.ProjectConfiguration.Name)); - } - await Task.Delay(3000); - } - } - - if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { - string resMsg; - StringBuilder resInfo = new StringBuilder(); - if (result?.OverallResult == BuildResultCode.Success) { - resMsg = "Build ok"; - } else { - resMsg = "Build FAIL"; - if (result == null) { - resInfo.AppendLine("####### Build returned 'null'"); - } else { - resInfo.AppendLine("####### Build returned 'Failure' code"); - if (result.ResultsByTarget != null) { - foreach (var tr in result.ResultsByTarget) { - var res = tr.Value; - if (res.ResultCode != TargetResultCode.Failure) - continue; - resInfo.AppendFormat("### Target '{0}' FAIL\r\n", tr.Key); - if (res.Items != null && res.Items.Length > 0) { - resInfo.AppendFormat( - "Items: {0}\r\n", string.Join(", ", res.Items - .Select(it => it.ItemSpec))); - } - var e = tr.Value?.Exception; - if (e != null) { - resInfo.AppendFormat( - "Exception: {0}\r\nStacktrace:\r\n{1}\r\n", - e.Message, e.StackTrace); - } - } - } - } - } - Messages.Print(string.Format( - "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] {3}\r\n{4}", - DateTime.Now, Thread.CurrentThread.ManagedThreadId, - ConfiguredProject.ProjectConfiguration.Name, - resMsg, resInfo.ToString())); - } - - if (result == null - || result.ResultsByTarget == null - || result.OverallResult != BuildResultCode.Success) { - Messages.Print(string.Format("{0}: background build FAILED!", - Path.GetFileName(UnconfiguredProject.FullPath))); - } else { - var checkResults = result.ResultsByTarget - .Where(x => Targets.Contains(x.Key)) - .Select(x => x.Value); - ok = checkResults.Any() - && checkResults.All(x => x.ResultCode == TargetResultCode.Success); - if (ok) - msBuildProject.MarkDirty(); - } - await writeAccess.ReleaseAsync(); - } - if (ok) { - var vcProject = Project.Object as VCProject; - var vcConfigs = vcProject.Configurations as IVCCollection; + var vcConfigs = VcProject.Configurations as IVCCollection; var vcConfig = vcConfigs.Item(ConfiguredProject.ProjectConfiguration.Name) as VCConfiguration; var props = vcConfig.Rules.Item("QtRule10_Settings") as IVCRulePropertyStorage; props.SetPropertyValue("QtLastBackgroundBuild", DateTime.UtcNow.ToString("o")); @@ -375,7 +398,8 @@ namespace QtVsTools.QtMsBuild Messages.Print(string.Format( @" == {0}: build {1}", - Project.Name, ok ? "successful" : "ERROR")); + Path.GetFileNameWithoutExtension(UnconfiguredProject.FullPath), + ok ? "successful" : "ERROR")); } } } diff --git a/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs b/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs index 9765c286..01c22a16 100644 --- a/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs +++ b/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs @@ -47,7 +47,7 @@ namespace QtVsTools.QtMsBuild { Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread(); - if (project == null || !QtProjectTracker.IsTracked(project)) + if (project == null || !QtProjectTracker.IsTracked(project.FullName)) return; if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) { @@ -56,17 +56,19 @@ namespace QtVsTools.QtMsBuild DateTime.Now, Thread.CurrentThread.ManagedThreadId, (configId != null) ? configId : "(all configs)", project.FullName)); } - _ = Task.Run(() => RefreshAsync(project, configId, selectedFiles)); + string projectPath = project.FullName; + _ = Task.Run(() => RefreshAsync(project, projectPath, configId, selectedFiles)); } public static async Task RefreshAsync( EnvDTE.Project project, + string projectPath, string configId = null, IEnumerable<string> selectedFiles = null) { - if (project == null || !QtProjectTracker.IsTracked(project)) + if (project == null || !QtProjectTracker.IsTracked(projectPath)) return; - var tracker = QtProjectTracker.Get(project); + var tracker = QtProjectTracker.Get(project, projectPath); await tracker.Initialized; var properties = new Dictionary<string, string>(); @@ -88,7 +90,7 @@ namespace QtVsTools.QtMsBuild foreach (var config in configs) { await QtProjectBuild.StartBuildAsync( - project, config, properties, targets, + project, projectPath, config, properties, targets, LoggerVerbosity.Quiet); } } diff --git a/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs b/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs index 4a771c24..c9b0aa53 100644 --- a/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs +++ b/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs @@ -37,6 +37,7 @@ using Microsoft.VisualStudio.ProjectSystem; using Microsoft.VisualStudio.ProjectSystem.Properties; using Microsoft.VisualStudio.TaskStatusCenter; using Microsoft.VisualStudio.Threading; +using Microsoft.VisualStudio.VCProjectEngine; namespace QtVsTools.QtMsBuild { @@ -115,14 +116,14 @@ namespace QtVsTools.QtMsBuild } public EnvDTE.Project Project { get; private set; } + public VCProject VcProject { get; private set; } public UnconfiguredProject UnconfiguredProject { get; private set; } public EventWaitHandle Initialized { get; } List<Subscriber> Subscribers { get; set; } - public static bool IsTracked(EnvDTE.Project project) + public static bool IsTracked(string projectPath) { - ThreadHelper.ThrowIfNotOnUIThread(); - return Instances.ContainsKey(project.FullName); + return Instances.ContainsKey(projectPath); } public static void Add(EnvDTE.Project project) @@ -131,21 +132,19 @@ namespace QtVsTools.QtMsBuild return; ThreadHelper.ThrowIfNotOnUIThread(); - Get(project); + Get(project, project.FullName); } - public static QtProjectTracker Get(EnvDTE.Project project) + public static QtProjectTracker Get(EnvDTE.Project project, string projectPath) { - ThreadHelper.ThrowIfNotOnUIThread(); - lock (StaticCriticalSection) { - if (Instances.TryGetValue(project.FullName, out QtProjectTracker tracker)) + if (Instances.TryGetValue(projectPath, out QtProjectTracker tracker)) return tracker; tracker = new QtProjectTracker { Project = project, }; - Instances[project.FullName] = tracker; + Instances[projectPath] = tracker; InitQueue.Enqueue(tracker); if (InitDispatcher == null) InitDispatcher = Task.Run(InitDispatcherLoopAsync); @@ -168,11 +167,15 @@ namespace QtVsTools.QtMsBuild await Task.Delay(100); if (InitQueue.TryDequeue(out QtProjectTracker tracker)) { if (InitStatus == null) { - await QtVsToolsPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync(); + await QtVsToolsPackage.Instance.JoinableTaskFactory + .SwitchToMainThreadAsync(); tracker.BeginInitStatus(); await TaskScheduler.Default; } else { + await QtVsToolsPackage.Instance.JoinableTaskFactory + .SwitchToMainThreadAsync(); tracker.UpdateInitStatus(0); + await TaskScheduler.Default; } await tracker.InitializeAsync(); } @@ -190,9 +193,14 @@ namespace QtVsTools.QtMsBuild async Task InitializeAsync() { int p = 0; - UpdateInitStatus(p += 10); + UpdateInitStatus(p += 5); await QtVsToolsPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync(); + UpdateInitStatus(p += 5); + + VcProject = Project.Object as VCProject; + if (VcProject == null) + return; UpdateInitStatus(p += 10); var context = Project.Object as IVsBrowseObjectContext; @@ -283,8 +291,9 @@ namespace QtVsTools.QtMsBuild Subscribers = null; } project.ProjectUnloading -= OnProjectUnloadingAsync; - Instances.TryRemove(Project.FullName, out QtProjectTracker tracker); + Instances.TryRemove(project.UnconfiguredProject.FullPath, out QtProjectTracker _); } + await Task.Yield(); } void BeginInitStatus() |