aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel Costa <miguel.costa@qt.io>2022-05-10 18:39:10 +0200
committerMiguel Costa <miguel.costa@qt.io>2022-05-16 14:51:54 +0000
commit9b518c7bb67a7529169434bd8826325f91e76d96 (patch)
tree260c6a923c003763ecd5205d63fb44354b982310
parentd7250825ea7758525ed164dd89fac084bdf70c1d (diff)
Improve intellisense performance for Qt projects
* Avoid running background builds when projects are loaded or changed. * Add outer/inner build targets also for design time builds. * Add project option to enable/disable running Qt tools in design-time. * Stop using project system notification subscriptions. * Detect relevant project changes using only DTE events. Change-Id: I7fe0508b2d9ed63c1e3f3b2741ee57ffad366527 Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
-rw-r--r--QtMSBuild/QtMSBuild.csproj4
-rw-r--r--QtMSBuild/QtMsBuild/qt_defaults.props3
-rw-r--r--QtMSBuild/QtMsBuild/qt_globals.targets98
-rw-r--r--QtMSBuild/QtMsBuild/qt_inner.targets138
-rw-r--r--QtMSBuild/QtMsBuild/qt_private.props46
-rw-r--r--QtMSBuild/QtMsBuild/qt_settings.xml8
-rw-r--r--QtMSBuild/QtMsBuild/qt_vars.targets6
-rw-r--r--QtVsTools.Package/Editors/Editor.QtDesigner.cs6
-rw-r--r--QtVsTools.Package/Package/DteEventsHandler.cs22
-rw-r--r--QtVsTools.Package/QtMsBuild/QtProjectBuild.cs42
-rw-r--r--QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs16
-rw-r--r--QtVsTools.Package/QtMsBuild/QtProjectTracker.cs78
12 files changed, 309 insertions, 158 deletions
diff --git a/QtMSBuild/QtMSBuild.csproj b/QtMSBuild/QtMSBuild.csproj
index 3e2a0e0e..a6140a9d 100644
--- a/QtMSBuild/QtMSBuild.csproj
+++ b/QtMSBuild/QtMSBuild.csproj
@@ -172,6 +172,10 @@
<SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
+ <Content Include="QtMSBuild\qt_inner.targets">
+ <SubType>Designer</SubType>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
<!--
///////////////////////////////////////////////////////////////////////////////////////////////
// Qt/MSBuild moc property pages and targets
diff --git a/QtMSBuild/QtMsBuild/qt_defaults.props b/QtMSBuild/QtMsBuild/qt_defaults.props
index 83f7c8e5..2d212157 100644
--- a/QtMSBuild/QtMsBuild/qt_defaults.props
+++ b/QtMSBuild/QtMsBuild/qt_defaults.props
@@ -71,6 +71,9 @@
<QtPathBinaries>bin</QtPathBinaries>
<QtPathLibraryExecutables>bin</QtPathLibraryExecutables>
+ <!--// Run Qt tools during design-time build -->
+ <QtToolsDesignTime>true</QtToolsDesignTime>
+
<!--// qmake template -->
<QtQMakeTemplate>vcapp</QtQMakeTemplate>
diff --git a/QtMSBuild/QtMsBuild/qt_globals.targets b/QtMSBuild/QtMsBuild/qt_globals.targets
index 661bc144..cddba5d0 100644
--- a/QtMSBuild/QtMsBuild/qt_globals.targets
+++ b/QtMSBuild/QtMsBuild/qt_globals.targets
@@ -84,6 +84,29 @@
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
+ // Set up inner build if Qt vars property file is outdated
+ // -->
+ <PropertyGroup Condition="'$(QtInnerBuild)' == ''">
+ <QtVarsOutdated>false</QtVarsOutdated>
+ <QtVarsOutdated
+ Condition="!Exists('$(QtVarsFilePath)')
+ OR '$(QtBkup_QtInstall)' != '$(QtInstall)'
+ OR '$(QtBkup_QtModules)' != '$(QtModules)'
+ OR '$(QtBkup_QtPathBinaries)' != '$(QtPathBinaries)'
+ OR '$(QtBkup_QtPathLibraryExecutables)' != '$(QtPathLibraryExecutables)'
+ OR '$(QtBkup_QtHeaderSearchPath)' != '$(QtHeaderSearchPath)'
+ OR '$(QtBkup_QtLibrarySearchPath)' != '$(QtLibrarySearchPath)'
+ OR '$(QtBkup_QtVars)' != '$(QtVars)'
+ OR '$(QtBkup_QMakeCodeLines)' != '$(QMakeCodeLines)'
+ OR '$(QtBkup_QtBuildConfig)' != '$(QtBuildConfig)'"
+ >true</QtVarsOutdated>
+ </PropertyGroup>
+
+ <!-- // Enable inner build targets -->
+ <Import Condition="'$(QtVarsOutdated)' == 'true'" Project="qt_inner.targets"/>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
/// TARGET QtGetDefaultClCompile
/////////////////////////////////////////////////////////////////////////////////////////////////
// Get default C++ properties
@@ -201,7 +224,8 @@
OR ('$(project_changed)' == 'true' AND '$(log_hash)' != '$(work_hash)')"
>true</do_work>
<skip_work
- Condition="'$(do_work)' != 'true' OR '$(DesignTimeBuild)' == 'true'"
+ Condition="'$(do_work)' != 'true'
+ OR ('$(QtDesignTimeBuild)' == 'true' AND '$(QtToolsDesignTime)' != 'true')"
>true</skip_work>
</PropertyGroup>
@@ -268,8 +292,7 @@
// -->
<QtRunWork
Condition="'$(ApplicationType)' != 'Linux' AND '@(QtWork)' != ''
- AND '%(QtWork.ParallelBuild)' == 'true'
- AND '$(DesignTimeBuild)' != 'true'"
+ AND '%(QtWork.ParallelBuild)' == 'true'"
QtWork="@(QtWork)" QtMaxProcs="$(QtMaxProcs)" QtDebug="$(QtDebug)">
<Output TaskParameter="Result" ItemName="QtWorkResult" />
</QtRunWork>
@@ -280,8 +303,7 @@
// -->
<QtRunWork
Condition="'$(ApplicationType)' != 'Linux' AND '@(QtWork)' != ''
- AND '%(QtWork.ParallelBuild)' != 'true'
- AND '$(DesignTimeBuild)' != 'true'"
+ AND '%(QtWork.ParallelBuild)' != 'true'"
QtWork="@(QtWork)" QtMaxProcs="1" QtDebug="$(QtDebug)">
<Output TaskParameter="Result" ItemName="QtWorkResult" />
</QtRunWork>
@@ -293,13 +315,13 @@
<!-- // Translate local paths to host paths -->
<Flatten
Condition="'$(ApplicationType)' == 'Linux'
- AND '@(QtWork)' != '' AND '$(DesignTimeBuild)' != 'true'"
+ AND '@(QtWork)' != '' AND '$(QtDesignTimeBuild)' != 'true'"
Items="@(QtWork)" Metadata="ResourceFiles">
<Output TaskParameter="Result" ItemName="ResourceFiles"/>
</Flatten>
<ItemGroup
Condition="'$(ApplicationType)' == 'Linux'
- AND '@(QtWork)' != '' AND '$(DesignTimeBuild)' != 'true'">
+ AND '@(QtWork)' != '' AND '$(QtDesignTimeBuild)' != 'true'">
<LocalPath Include="%(QtWork.Identity)">
<Name>InputPath</Name>
<Item>%(QtWork.Identity)</Item>
@@ -320,7 +342,7 @@
</ItemGroup>
<HostTranslatePaths
Condition="'$(ApplicationType)' == 'Linux'
- AND '@(QtWork)' != '' AND '$(DesignTimeBuild)' != 'true'"
+ AND '@(QtWork)' != '' AND '$(QtDesignTimeBuild)' != 'true'"
Items="@(LocalPath)" Names="InputPath;OutputPath">
<Output TaskParameter="Result" ItemName="HostPath"/>
</HostTranslatePaths>
@@ -332,7 +354,7 @@
<!-- // Run command -->
<HostExec
Condition="'$(ApplicationType)' == 'Linux'
- AND '%(Identity)' != '' AND '$(DesignTimeBuild)' != 'true'"
+ AND '%(Identity)' != '' AND '$(QtDesignTimeBuild)' != 'true'"
Message="@(QtWork->'%(WorkType) %(Identity)')"
Command="@(QtWork->'%(ToolPath) %(Options)')"
Inputs="@(InputPath)"
@@ -344,7 +366,7 @@
<!-- // Generate result item -->
<ItemGroup
Condition="'$(ApplicationType)' == 'Linux'
- AND '@(QtWork)' != '' AND '$(DesignTimeBuild)' != 'true'">
+ AND '@(QtWork)' != '' AND '$(QtDesignTimeBuild)' != 'true'">
<QtWorkResult Include="@(QtWork)">
<ExitCode>0</ExitCode>
</QtWorkResult>
@@ -354,9 +376,11 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// Save tracking log of files read during build; used by VS to check the up-to-date status
// -->
- <ItemGroup Condition="'$(DesignTimeBuild)' != 'true' AND '$(QtVSToolsBuild)' != 'true'">
+ <ItemGroup>
<read_log Include="^%(QtWorkResult.FullPath);%(QtWorkResult.AdditionalDependencies)"
- Condition="'%(QtWorkResult.ExitCode)' == '0' AND '%(QtWorkResult.DisableLog)' != 'true'">
+ Condition="'%(QtWorkResult.ExitCode)' == '0'
+ AND '%(QtWorkResult.DisableLog)' != 'true'
+ AND '%(QtWorkResult.Skipped)' != 'true'">
<WorkType>%(QtWorkResult.WorkType)</WorkType>
</read_log>
<read_log>
@@ -377,9 +401,11 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// Save tracking log of files written during build; used by VS to check the up-to-date status
// -->
- <ItemGroup Condition="'$(DesignTimeBuild)' != 'true' AND '$(QtVSToolsBuild)' != 'true'">
+ <ItemGroup>
<write_log Include="^%(QtWorkResult.FullPath);%(QtWorkResult.OutputFile)"
- Condition="'%(QtWorkResult.ExitCode)' == '0' AND '%(QtWorkResult.DisableLog)' != 'true'">
+ Condition="'%(QtWorkResult.ExitCode)' == '0'
+ AND '%(QtWorkResult.DisableLog)' != 'true'
+ AND '%(QtWorkResult.Skipped)' != 'true'">
<WorkType>%(QtWorkResult.WorkType)</WorkType>
</write_log>
<write_log>
@@ -398,7 +424,7 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// Log output files; this is used by VS to determine what files to delete on "Clean"
// -->
- <ItemGroup Condition="'$(DesignTimeBuild)' != 'true' AND '$(QtVSToolsBuild)' != 'true'">
+ <ItemGroup>
<clean_log Include="%(QtWorkResult.OutputFile)"
Condition="'%(QtWorkResult.ExitCode)' == '0'">
<Source>@(QtWorkResult, '|')</Source>
@@ -414,7 +440,7 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// Log calls to Qt tools; used in QtWorkPrepare to detect changes to the options of Qt tools
// -->
- <WriteLinesToFile Condition="'@(QtWorkLog)' != '' AND '$(DesignTimeBuild)' != 'true'"
+ <WriteLinesToFile Condition="'@(QtWorkLog)' != ''"
File="$(QtLogFilePath)"
Lines="@(QtWorkLog->'%(Identity)|%(Hash)')"
Overwrite="true" Encoding="Unicode"/>
@@ -425,8 +451,7 @@
// -->
<Error
Condition="'%(QtWorkResult.ExitCode)' != ''
- AND '%(QtWorkResult.ExitCode)' != '0'
- AND '$(DesignTimeBuild)' != 'true'"
+ AND '%(QtWorkResult.ExitCode)' != '0'"
File="%(QtWorkResult.Identity)" Code="%(QtWorkResult.ExitCode)"
Text="%(QtWorkResult.WorkType) (%(QtWorkResult.ToolPath))"/>
@@ -673,48 +698,13 @@
// -->
<Target
Name="Qt"
- DependsOnTargets="QtPrepare;QtWork;QtSetAdditionalOptions"
- BeforeTargets="FixupCLCompileOptions">
+ DependsOnTargets="QtPrepare;QtWork;QtSetAdditionalOptions">
<CriticalSection Lock="false" Name="$(ProjectGuid)" />
<OnError ExecuteTargets="QtLeaveCriticalSection_OnError"/>
</Target>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
- /// TARGET QtOuterBuild
- /////////////////////////////////////////////////////////////////////////////////////////////////
- // Run targets in $(QtOuterBuildDependsOn) and then recursively invoke build
- // -->
- <Target Name="QtOuterBuild" DependsOnTargets="$(QtOuterBuildDependsOn)">
- <!--// Invoke inner build: recursive build in second MSBuild instance -->
- <MSBuild
- Projects="$(MSBuildProjectFullPath)"
- Targets="Build"
- Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false">
- </MSBuild>
- <OnError ExecuteTargets="QtLeaveCriticalSection_OnError"/>
- </Target>
-
- <PropertyGroup
- Condition="'$(QtInnerBuild)' == '' AND '$(DesignTimeBuild)' != 'true'">
- <!--// Outer build: invoke inner build -->
- <BuildDependsOn>
- $(QtOuterBuildPrepare);
- QtOuterBuild;
- $(QtOuterBuildFinalize)
- </BuildDependsOn>
- <QtInnerBuild>$(MSBuildProjectFullPath)</QtInnerBuild>
- <RandomFileName>$([System.IO.Path]::GetRandomFileName())</RandomFileName>
- </PropertyGroup>
-
- <PropertyGroup
- Condition="'$(QtInnerBuild)' != '$(MSBuildProjectFullPath)' AND '$(DesignTimeBuild)' != 'true'">
- <!--// Dependent project inner build: skip build -->
- <BuildDependsOn>$(QtOuterBuildPrepare);$(QtOuterBuildFinalize)</BuildDependsOn>
- </PropertyGroup>
-
- <!--
- /////////////////////////////////////////////////////////////////////////////////////////////////
/// TARGET QtEnterCriticalSection_... / QtLeaveCriticalSection_InitializeBuildStatus
/////////////////////////////////////////////////////////////////////////////////////////////////
// Synchronize calls to InitializeBuildStatus
diff --git a/QtMSBuild/QtMsBuild/qt_inner.targets b/QtMSBuild/QtMsBuild/qt_inner.targets
new file mode 100644
index 00000000..a0675838
--- /dev/null
+++ b/QtMSBuild/QtMsBuild/qt_inner.targets
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt VS Tools.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+-->
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+ <PropertyGroup
+ Condition="'$(QtInnerBuild)' == ''">
+ <!--// Outer build: invoke inner build -->
+ <BuildDependsOn>
+ $(QtOuterBuildPrepare);
+ QtOuterBuild;
+ $(QtOuterBuildFinalize)
+ </BuildDependsOn>
+ <QtInnerBuild>$(MSBuildProjectFullPath)</QtInnerBuild>
+ <RandomFileName>$([System.IO.Path]::GetRandomFileName())</RandomFileName>
+ </PropertyGroup>
+
+ <PropertyGroup
+ Condition="'$(QtInnerBuild)' != '$(MSBuildProjectFullPath)'">
+ <!--// Dependent project inner build: skip build -->
+ <BuildDependsOn>$(QtOuterBuildPrepare);$(QtOuterBuildFinalize)</BuildDependsOn>
+ </PropertyGroup>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// TARGET QtOuterBuild
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ // Run targets in $(QtOuterBuildDependsOn) and then recursively invoke build
+ // -->
+ <Target Name="QtOuterBuild" DependsOnTargets="$(QtOuterBuildDependsOn)">
+ <!--// Invoke inner build: recursive build in second MSBuild instance -->
+ <MSBuild
+ Projects="$(MSBuildProjectFullPath)"
+ Targets="Build"
+ Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false">
+ </MSBuild>
+ <OnError ExecuteTargets="QtLeaveCriticalSection_OnError"/>
+ </Target>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// TARGET GetClCommandLineForReference
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // -->
+ <Target
+ Name="GetClCommandLineForReference"
+ DependsOnTargets="$(QtOuterBuildDependsOn)"
+ Returns="@(ClCommandLineForReference)">
+ <MSBuild
+ Projects="$(MSBuildProjectFullPath)"
+ Targets="GetClCommandLineForReference"
+ Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false">
+ <Output TaskParameter="TargetOutputs" ItemName="ClCommandLineForReference"/>
+ </MSBuild>
+ </Target>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// TARGET GetGeneratedFiles
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // -->
+ <Target
+ Name="GetGeneratedFiles"
+ DependsOnTargets="$(QtOuterBuildDependsOn)"
+ Returns="@(_GeneratedFiles)">
+ <MSBuild
+ Projects="$(MSBuildProjectFullPath)"
+ Targets="GetGeneratedFiles"
+ Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false">
+ <Output TaskParameter="TargetOutputs" ItemName="_GeneratedFiles"/>
+ </MSBuild>
+ </Target>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// TARGET GetProjectReferencesInfo
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // -->
+ <Target
+ Name="GetProjectReferencesInfo"
+ DependsOnTargets="$(QtOuterBuildDependsOn)"
+ Returns="@(_ProjectReferencesInfo)">
+ <MSBuild
+ Projects="$(MSBuildProjectFullPath)"
+ Targets="GetProjectReferencesInfo"
+ Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false">
+ <Output TaskParameter="TargetOutputs" ItemName="_ProjectReferencesInfo"/>
+ </MSBuild>
+ </Target>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// TARGET GetClCommandLines
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // -->
+ <Target
+ Name="GetClCommandLines"
+ DependsOnTargets="$(QtOuterBuildDependsOn)"
+ Returns="@(ClCommandLines)">
+ <MSBuild
+ Projects="$(MSBuildProjectFullPath)"
+ Targets="GetClCommandLines"
+ Properties="QtInnerBuild=$(MSBuildProjectFullPath);RandomFileName=$(RandomFileName);BuildProjectReferences=false">
+ <Output TaskParameter="TargetOutputs" ItemName="ClCommandLines"/>
+ </MSBuild>
+ </Target>
+</Project>
diff --git a/QtMSBuild/QtMsBuild/qt_private.props b/QtMSBuild/QtMsBuild/qt_private.props
index f688ae1e..007d87a9 100644
--- a/QtMSBuild/QtMsBuild/qt_private.props
+++ b/QtMSBuild/QtMsBuild/qt_private.props
@@ -57,6 +57,18 @@
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
+ // Check if design-time build
+ // -->
+ <PropertyGroup>
+ <QtDesignTimeBuild>false</QtDesignTimeBuild>
+ <QtDesignTimeBuild
+ Condition="'$(DesignTimeBuild)' == 'true'
+ OR '$(QtVSToolsBuild)' == 'true'"
+ >true</QtDesignTimeBuild>
+ </PropertyGroup>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
// Setup Qt installation path
// -->
<PropertyGroup Condition="'$(QtVsProjectSettings)' == 'true'">
@@ -112,21 +124,29 @@
>$([System.String]::Copy($([System.IO.File]::ReadAllText('$(QtVarsIndexPathDesignTime)'))).Replace('&#xD;&#xA;',''))</QtVarsDesignTime>
</PropertyGroup>
- <!--// Import Qt variables (full build) -->
- <Import
- Condition="'$(DesignTimeBuild)' != 'true' AND Exists('$(QtVarsFilePath)')"
- Project="$(QtVarsFilePath)"/>
+ <PropertyGroup>
+ <!--// Path to Qt variables .props: full build -->
+ <QtVarsImportPath
+ Condition="'$(QtDesignTimeBuild)' != 'true'
+ AND Exists('$(QtVarsFilePath)')"
+ >$(QtVarsFilePath)</QtVarsImportPath>
- <!--// Import Qt variables (design-time build) -->
- <Import
- Condition="'$(DesignTimeBuild)' == 'true' AND Exists('$(QtVarsDesignTime)')"
- Project="$(QtVarsDesignTime)"/>
+ <!--// Path to Qt variables .props: design-time build -->
+ <QtVarsImportPath
+ Condition="'$(QtDesignTimeBuild)' == 'true'
+ AND Exists('$(QtVarsDesignTime)')"
+ >$(QtVarsDesignTime)</QtVarsImportPath>
- <!--// Import Qt variables (fall-back) -->
- <Import
- Condition=
-"'$(DesignTimeBuild)' == 'true' AND !Exists('$(QtVarsDesignTime)') AND Exists('$(QtVarsFilePath)')"
- Project="$(QtVarsFilePath)"/>
+ <!--// Path to Qt variables .props: fall-back -->
+ <QtVarsImportPath
+ Condition="'$(QtDesignTimeBuild)' == 'true'
+ AND !Exists('$(QtVarsDesignTime)')
+ AND Exists('$(QtVarsFilePath)')"
+ >$(QtVarsFilePath)</QtVarsImportPath>
+ </PropertyGroup>
+
+ <!--// Import Qt vars property file -->
+ <Import Condition="Exists('$(QtVarsImportPath)')" Project="$(QtVarsImportPath)"/>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/QtMSBuild/QtMsBuild/qt_settings.xml b/QtMSBuild/QtMsBuild/qt_settings.xml
index 9c1b2549..53b2f526 100644
--- a/QtMSBuild/QtMsBuild/qt_settings.xml
+++ b/QtMSBuild/QtMsBuild/qt_settings.xml
@@ -100,6 +100,14 @@
Category="QtSettings_01_General"
DisplayName="Run Deployment Tool"
Description="Select whether Qt for Windows Deployment Tool (windeployqt) should be called after build."/>
+ <EnumProperty
+ Name="QtToolsDesignTime"
+ Category="QtSettings_01_General"
+ DisplayName="Design Time Build"
+ Description="Run Qt tools during IntelliSense builds.">
+ <EnumValue Name="true" DisplayName="Run Qt Tools"/>
+ <EnumValue Name="false" DisplayName="Skip Qt Tools"/>
+ </EnumProperty>
<StringProperty
Name="QtPathBinaries"
Category="QtSettings_02_Paths"
diff --git a/QtMSBuild/QtMsBuild/qt_vars.targets b/QtMSBuild/QtMsBuild/qt_vars.targets
index 174b9b56..5d6f08da 100644
--- a/QtMSBuild/QtMsBuild/qt_vars.targets
+++ b/QtMSBuild/QtMsBuild/qt_vars.targets
@@ -501,15 +501,15 @@
<!--// In design-time, copy generated .props to randomly named file -->
<PropertyGroup>
<QtVarsDesignTimeNew
- Condition="'$(ErrorLevel)' == '0' AND '$(QtVSToolsBuild)' == 'true'"
+ Condition="'$(ErrorLevel)' == '0' AND '$(QtDesignTimeBuild)' == 'true'"
>$([System.IO.Path]::Combine('$(TEMP)','$([System.IO.Path]::GetRandomFileName()).designtime.props'))
</QtVarsDesignTimeNew>
</PropertyGroup>
<Copy
- Condition="'$(ErrorLevel)' == '0' AND '$(QtVSToolsBuild)' == 'true'"
+ Condition="'$(ErrorLevel)' == '0' AND '$(QtDesignTimeBuild)' == 'true'"
SourceFiles="$(QtVarsFilePath)" DestinationFiles="$(QtVarsDesignTimeNew)"/>
<WriteLinesToFile
- Condition="'$(ErrorLevel)' == '0' AND '$(QtVSToolsBuild)' == 'true'"
+ Condition="'$(ErrorLevel)' == '0' AND '$(QtDesignTimeBuild)' == 'true'"
File="$(QtVarsIndexPathDesignTime)" Overwrite="true" Lines="$(QtVarsDesignTimeNew)"/>
<!--// Clean-up -->
diff --git a/QtVsTools.Package/Editors/Editor.QtDesigner.cs b/QtVsTools.Package/Editors/Editor.QtDesigner.cs
index cddc7fa5..b6cee8a6 100644
--- a/QtVsTools.Package/Editors/Editor.QtDesigner.cs
+++ b/QtVsTools.Package/Editors/Editor.QtDesigner.cs
@@ -81,13 +81,11 @@ namespace QtVsTools.Editors
var latestWriteTime = File.GetLastWriteTime(filePath);
if (lastWriteTime != latestWriteTime) {
lastWriteTime = latestWriteTime;
- await QtProjectIntellisense.RefreshAsync(
- project, projectPath, selectedFiles: itemId);
+ await QtProjectIntellisense.RefreshAsync(project, projectPath);
}
}
if (lastWriteTime != File.GetLastWriteTime(filePath)) {
- await QtProjectIntellisense.RefreshAsync(
- project, projectPath, selectedFiles: itemId);
+ await QtProjectIntellisense.RefreshAsync(project, projectPath);
}
});
}
diff --git a/QtVsTools.Package/Package/DteEventsHandler.cs b/QtVsTools.Package/Package/DteEventsHandler.cs
index 30ca31c0..b5cfdfc1 100644
--- a/QtVsTools.Package/Package/DteEventsHandler.cs
+++ b/QtVsTools.Package/Package/DteEventsHandler.cs
@@ -185,8 +185,10 @@ namespace QtVsTools
if (debugStartWithoutDebuggingEvents != null)
debugStartWithoutDebuggingEvents.BeforeExecute -= debugStartWithoutDebuggingEvents_BeforeExecute;
- if (vcProjectEngineEvents != null)
+ if (vcProjectEngineEvents != null) {
vcProjectEngineEvents.ItemPropertyChange -= OnVCProjectEngineItemPropertyChange;
+ vcProjectEngineEvents.ItemPropertyChange2 -= OnVCProjectEngineItemPropertyChange2;
+ }
if (windowEvents != null)
windowEvents.WindowActivated -= WindowEvents_WindowActivated;
@@ -520,6 +522,7 @@ namespace QtVsTools
if (vcProjectEngineEvents != null) {
try {
vcProjectEngineEvents.ItemPropertyChange += OnVCProjectEngineItemPropertyChange;
+ vcProjectEngineEvents.ItemPropertyChange2 += OnVCProjectEngineItemPropertyChange2;
} catch {
Messages.DisplayErrorMessage("VCProjectEngine events could not be registered.");
}
@@ -590,6 +593,23 @@ namespace QtVsTools
}
}
+ private void OnVCProjectEngineItemPropertyChange2(
+ object item,
+ string propertySheet,
+ string itemType,
+ string propertyName)
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+ if (!propertyName.StartsWith("Qt") || propertyName == "QtLastBackgroundBuild")
+ return;
+ if (item is VCConfiguration vcConfig
+ && vcConfig.project is VCProject vcProject
+ && vcProject.Object is Project project) {
+ QtProjectIntellisense.Refresh(
+ QtProjectTracker.Get(project, project.FullName).Project, vcConfig.Name);
+ }
+ }
+
private static VCFile GetVCFileFromProject(string absFileName, VCProject project)
{
foreach (VCFile f in (IVCCollection)project.Files) {
diff --git a/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs b/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs
index 59049a1a..d893fe64 100644
--- a/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs
+++ b/QtVsTools.Package/QtMsBuild/QtProjectBuild.cs
@@ -48,11 +48,18 @@ namespace QtVsTools.QtMsBuild
using Common;
using Core;
using VisualStudio;
+ using static Common.EnumExt;
class QtProjectBuild : Concurrent<QtProjectBuild>
{
static LazyFactory StaticLazy { get; } = new LazyFactory();
+ public enum Target
+ {
+ // Mark project as dirty, but do not request a build
+ [String("QtVsTools.QtMsBuild.QtProjectBuild.Target.SetOutdated")] SetOutdated
+ }
+
static PunisherQueue<QtProjectBuild> BuildQueue => StaticLazy.Get(() =>
BuildQueue, () => new PunisherQueue<QtProjectBuild>(
getItemKey: (QtProjectBuild build) =>
@@ -148,6 +155,35 @@ namespace QtVsTools.QtMsBuild
.Forget();
}
+ public static void SetOutdated(
+ EnvDTE.Project project,
+ string projectPath,
+ string configName,
+ LoggerVerbosity verbosity = LoggerVerbosity.Quiet)
+ {
+ if (project == null)
+ throw new ArgumentException("Project cannot be null.");
+ if (configName == null)
+ throw new ArgumentException("Configuration name cannot be null.");
+
+ _ = Task.Run(() => SetOutdatedAsync(project, projectPath, configName, verbosity));
+ }
+
+ public static async Task SetOutdatedAsync(
+ EnvDTE.Project project,
+ string projectPath,
+ string configName,
+ LoggerVerbosity verbosity = LoggerVerbosity.Quiet)
+ {
+ await StartBuildAsync(
+ project,
+ projectPath,
+ configName,
+ null,
+ new[] { Target.SetOutdated.Cast<string>() },
+ verbosity);
+ }
+
public static void Reset()
{
BuildQueue.Clear();
@@ -208,6 +244,12 @@ namespace QtVsTools.QtMsBuild
{
var msBuildProject = await writeAccess.GetProjectAsync(ConfiguredProject);
+ if (Targets.Any(t => t == Target.SetOutdated.Cast<string>())) {
+ msBuildProject.MarkDirty();
+ await writeAccess.ReleaseAsync();
+ return true;
+ }
+
var solutionPath = QtProjectTracker.SolutionPath;
var configProps = new Dictionary<string, string>(
ConfiguredProject.ProjectConfiguration.Dimensions.ToImmutableDictionary())
diff --git a/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs b/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs
index 101b51af..2597e22f 100644
--- a/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs
+++ b/QtVsTools.Package/QtMsBuild/QtProjectIntelliSense.cs
@@ -60,14 +60,15 @@ namespace QtVsTools.QtMsBuild
(configId != null) ? configId : "(all configs)", project.FullName));
}
string projectPath = project.FullName;
- _ = Task.Run(() => RefreshAsync(project, projectPath, configId, selectedFiles));
+ _ = Task.Run(() => RefreshAsync(project, projectPath, configId, selectedFiles, false));
}
public static async Task RefreshAsync(
EnvDTE.Project project,
string projectPath,
string configId = null,
- IEnumerable<string> selectedFiles = null)
+ IEnumerable<string> selectedFiles = null,
+ bool refreshQtVars = false)
{
if (project == null || !QtProjectTracker.IsTracked(projectPath))
return;
@@ -92,9 +93,14 @@ namespace QtVsTools.QtMsBuild
}
foreach (var config in configs) {
- await QtProjectBuild.StartBuildAsync(
- project, projectPath, config, properties, targets,
- LoggerVerbosity.Quiet);
+ if (refreshQtVars) {
+ await QtProjectBuild.StartBuildAsync(
+ project, projectPath, config, properties, targets,
+ LoggerVerbosity.Quiet);
+ } else {
+ await QtProjectBuild.SetOutdatedAsync(
+ project, projectPath, config, LoggerVerbosity.Quiet);
+ }
}
}
}
diff --git a/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs b/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs
index 01e3156f..464322e8 100644
--- a/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs
+++ b/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs
@@ -75,51 +75,11 @@ namespace QtVsTools.QtMsBuild
Initialized = new EventWaitHandle(false, EventResetMode.ManualReset);
}
- class Subscriber : IDisposable
- {
- public Subscriber(QtProjectTracker tracker, ConfiguredProject config)
- {
- Tracker = tracker;
- Config = config;
- Subscription = Config.Services.ProjectSubscription.JointRuleSource.SourceBlock
- .LinkTo(new SubscriberAction(ProjectUpdateAsync),
- ruleNames: new[]
- {
- "ClCompile",
- "QtRule10_Settings",
- "QtRule30_Moc",
- "QtRule40_Rcc",
- "QtRule60_Repc",
- "QtRule50_Uic",
- "QtRule_Translation",
- "QtRule70_Deploy",
- },
- initialDataAsNew: false
- );
- }
-
- QtProjectTracker Tracker { get; }
- ConfiguredProject Config { get; }
- IDisposable Subscription { get; set; }
-
- public void Dispose()
- {
- Subscription?.Dispose();
- Subscription = null;
- }
-
- async Task ProjectUpdateAsync(IProjectVersionedValue<IProjectSubscriptionUpdate> update)
- {
- await Tracker.OnProjectUpdateAsync(Config, update.Value);
- }
- }
-
public EnvDTE.Project Project { get; private set; }
public string ProjectPath { 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(string projectPath)
{
@@ -221,13 +181,11 @@ namespace QtVsTools.QtMsBuild
Initialized.Set();
- Subscribers = new List<Subscriber>();
int n = configs.Count;
int d = (100 - p) / (n * 2);
foreach (var config in configs) {
var configProject = await UnconfiguredProject.LoadConfiguredProjectAsync(config);
UpdateInitStatus(p += d);
- Subscribers.Add(new Subscriber(this, configProject));
configProject.ProjectUnloading += OnProjectUnloadingAsync;
if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) {
Messages.Print(string.Format(
@@ -239,37 +197,6 @@ namespace QtVsTools.QtMsBuild
}
}
-
- async Task OnProjectUpdateAsync(ConfiguredProject config, IProjectSubscriptionUpdate update)
- {
- var changes = update.ProjectChanges.Values
- .Where(x => x.Difference.AnyChanges)
- .Select(x => x.Difference);
- var changesCount = changes
- .Select(x => x.AddedItems.Count
- + x.ChangedItems.Count
- + x.ChangedProperties.Count
- + x.RemovedItems.Count
- + x.RenamedItems.Count)
- .Sum();
- var changedProps = changes.SelectMany(x => x.ChangedProperties);
- if (changesCount == 0
- || (changesCount == 1
- && changedProps.Count() == 1
- && changedProps.First() == "QtLastBackgroundBuild")) {
- return;
- }
-
- if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) {
- Messages.Print(string.Format(
- "{0:HH:mm:ss.FFF} QtProjectTracker({1}): Changed [{2}] {3}",
- DateTime.Now, Thread.CurrentThread.ManagedThreadId,
- config.ProjectConfiguration.Name,
- config.UnconfiguredProject.FullPath));
- }
- await QtProjectIntellisense.RefreshAsync(Project, config.ProjectConfiguration.Name);
- }
-
async Task OnProjectUnloadingAsync(object sender, EventArgs args)
{
var project = sender as ConfiguredProject;
@@ -283,11 +210,6 @@ namespace QtVsTools.QtMsBuild
project.UnconfiguredProject.FullPath));
}
lock (CriticalSection) {
- if (Subscribers != null) {
- Subscribers.ForEach(s => s.Dispose());
- Subscribers.Clear();
- Subscribers = null;
- }
project.ProjectUnloading -= OnProjectUnloadingAsync;
Instances.TryRemove(project.UnconfiguredProject.FullPath, out QtProjectTracker _);
}