aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel Costa <miguel.costa@qt.io>2019-07-08 14:50:29 +0200
committerMiguel Costa <miguel.costa@qt.io>2019-08-05 09:24:32 +0000
commit6a77aa5ee036621b1f79827edce481eafe20d29f (patch)
tree988d0c88b76e50675534032cb0e0da63fb5bf972
parentcff73364c3b632a84ab3c7ca2f2ea32b563910ce (diff)
Use Qt (qmake) variables in VS projects
Values in project property pages can now reference Qt/qmake variables, using the syntax $(Qt_<var>_), where <var> is the name of a Qt variable (e.g. $(Qt_INCLUDEPATH_) ). To extract the variable values, a qmake project (.pro file) is generated and processed ahead of the VS project build. The qmake processing will generate a MSBuild properties file containing the Qt variables definitions to import in the VS project. Change-Id: I51572bd3798533d305ee6464044a8fe3504aa115 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
-rw-r--r--src/qtmsbuild/qt.props42
-rw-r--r--src/qtmsbuild/qt.targets1
-rw-r--r--src/qtmsbuild/qt_vars.targets337
-rw-r--r--src/qtvstools/QtVsTools.csproj6
4 files changed, 386 insertions, 0 deletions
diff --git a/src/qtmsbuild/qt.props b/src/qtmsbuild/qt.props
index 4f7fa0d5..08f42d6c 100644
--- a/src/qtmsbuild/qt.props
+++ b/src/qtmsbuild/qt.props
@@ -85,6 +85,48 @@
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
+ // Qt Variables Expansion
+ // -->
+ <PropertyGroup Condition="'$(QtVsProjectSettings)' == 'true'">
+ <!--// List of Qt variables to import -->
+ <QtVariables Condition="'$(QtVariables)' == ''">DEFINES;INCLUDEPATH;LIBS</QtVariables>
+
+ <!--// Path to Qt variables property file -->
+ <QtVarsWorkDir
+ >$([System.IO.Path]::Combine(
+ '$(TEMP)', '$([System.IO.Path]::GetRandomFileName())'))\</QtVarsWorkDir>
+ <QtVarsOutputDir
+ >$([System.IO.Path]::Combine('$(ProjectDir)', '$(IntDir)'))</QtVarsOutputDir>
+ <QtVarsFileNameWithoutExt
+ >qtvars_$(Platform)_$(Configuration)</QtVarsFileNameWithoutExt>
+ <QtVarsFileName
+ >$(QtVarsFileNameWithoutExt).props</QtVarsFileName>
+ <QtVarsWorkPath
+ >$(QtVarsWorkDir)$(QtVarsFileName)</QtVarsWorkPath>
+ <QtVarsFilePath
+ >$(QtVarsOutputDir)$(QtVarsFileName)</QtVarsFilePath>
+ </PropertyGroup>
+
+ <!--// Import Qt variables (full build) -->
+ <Import
+ Project="$(QtVarsFilePath)"/>
+
+ <!--// Add Qt variables to compiler and linker options -->
+ <ItemDefinitionGroup Condition="'$(QtVsProjectSettings)' == 'true'">
+ <ClCompile>
+ <PreprocessorDefinitions
+ >$(Qt_DEFINES_);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories
+ >$(Qt_INCLUDEPATH_);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies
+ >$(Qt_LIBS_);%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
// Add Qt DLL path to debugger definitions
// -->
<PropertyGroup>
diff --git a/src/qtmsbuild/qt.targets b/src/qtmsbuild/qt.targets
index df0ec430..ac6b4e16 100644
--- a/src/qtmsbuild/qt.targets
+++ b/src/qtmsbuild/qt.targets
@@ -68,6 +68,7 @@
<Import Project="qt_globals.targets"/>
<Import Project="qt_settings.targets"/>
<Import Project="qt_tasks.targets"/>
+ <Import Project="qt_vars.targets"/>
<!--
/////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/qtmsbuild/qt_vars.targets b/src/qtmsbuild/qt_vars.targets
new file mode 100644
index 00000000..0d4cf834
--- /dev/null
+++ b/src/qtmsbuild/qt_vars.targets
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+-->
+<!--
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Read Qt Build Variables
+// -->
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+ <PropertyGroup>
+ <QtDependsOn>QtVars;$(QtDependsOn)</QtDependsOn>
+ </PropertyGroup>
+ <ItemGroup>
+ <QtModuleList Include="$(QtModules)"/>
+ <QtVariableList Include="$(QtVariables)"/>
+ <QMakeCodeLine Include="$(QMakeCodeLines)"/>
+ <QtVarProp Include="@(QtVariableList->'Qt_%(Identity)_')"/>
+ </ItemGroup>
+
+ <PropertyGroup>
+ <QtSkipBuildTargets>QtSkipBuild;$(QtSkipBuildTargets)</QtSkipBuildTargets>
+ <QtModuleNames>@(QtModuleList->'%(Identity)', ' ')</QtModuleNames>
+ <QtVarNames>@(QtVariableList->'%(Identity)', ' ')</QtVarNames>
+ </PropertyGroup>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// TARGET QtVars
+ Condition="'$(QtToolsPath)' != ''
+ AND '$(QtConfigStamp)' != '$(QtInstall)|$(QtModuleNames)'">
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ // Call qmake with generated .pro file to export Qt variables into MSBuild .props file
+ // -->
+ <Target Name="QtVars"
+ Condition="'$(QtVsProjectSettings)' == 'true'
+ AND '$(QtConfigStamp)' != '$(QtInstall)|$(QtModuleNames)'">
+
+ <CreateProperty
+ Condition="Exists('$(QtInstall)')"
+ Value="$(QtInstall)">
+ <Output TaskParameter="ValueSetByTask" PropertyName="QtInstallDir" />
+ </CreateProperty>
+ <CreateProperty
+ Condition="!Exists('$(QtInstall)') AND '$(QtInstall)' != ''"
+ Value="HKEY_CURRENT_USER\Software\Digia\Versions\$(QtInstall)">
+ <Output TaskParameter="ValueSetByTask" PropertyName="QtInstallRegKey" />
+ </CreateProperty>
+ <CreateProperty
+ Condition="!Exists('$(QtInstall)') AND '$(QtInstall)' != ''"
+ Value="$([MSBuild]::GetRegistryValue('$(QtInstallRegKey)','InstallDir'))">
+ <Output TaskParameter="ValueSetByTask" PropertyName="QtInstallRegDir" />
+ </CreateProperty>
+ <CreateProperty
+ Condition="!Exists('$(QtInstall)') AND '$(QtInstall)' != ''"
+ Value="$(QtInstallRegDir)">
+ <Output TaskParameter="ValueSetByTask" PropertyName="QtInstallDir" />
+ </CreateProperty>
+ <CreateProperty
+ Value="$(QtInstallDir)\bin">
+ <Output TaskParameter="ValueSetByTask" PropertyName="QtToolsPath" />
+ </CreateProperty>
+
+ <Message
+ Importance="high"
+ Text="Reading Qt configuration ($(QtInstallDir))"/>
+
+ <PropertyGroup>
+
+ <!--// .pro file configuration -->
+ <QtVarsProFileConfig
+ Condition="'$(Configuration)' == 'Debug'">
+ CONFIG -= debug release debug_and_release
+ CONFIG += debug
+ </QtVarsProFileConfig>
+ <QtVarsProFileConfig
+ Condition="'$(Configuration)' != 'Debug'">
+ CONFIG -= debug release debug_and_release
+ CONFIG += release
+ </QtVarsProFileConfig>
+
+ <!--// .pro file input parameters -->
+ <QtVarsProFileInput>
+ <!--
+# Qt vars data file name -->
+ fileName = "qtvars_$(Platform)_$(Configuration).props"
+ <!--
+# Selected Qt modules -->
+ modules = $(QtModuleNames)
+ <!--
+# Selected Qt variables -->
+ varNames = $(QtVarNames)
+ <!--
+# Custom additional .pro file code (from property page) -->
+ @(QMakeCodeLine->'%(Identity)','%0D%0A')
+ </QtVarsProFileInput>
+
+ <!--// Generate .pro file -->
+ <!--
+######## BEGIN generated qmake project #############################################################
+## -->
+ <QtVarsProFileText>
+ <![CDATA[
+## Escape string for use by MSBuild
+#
+defineReplace(formatMsBuildString) {
+ exprValue = $$1
+ exprText = ""
+ sep = ""
+ for (value, exprValue) {
+ value = $$replace(value, "%", "%2525")
+ value = $$replace(value, "%3B", "%253B")
+ value = $$replace(value, "\x24", "%2524")
+ value = $$replace(value, "@", "%2540")
+ exprText = "$$exprText$$sep$$value"
+ sep = "%3B"
+ }
+ return($$exprText)
+}
+
+## Fetch information from required modules through dependency relation
+#
+defined(modules, var) {
+ INCLUDEPATH = $$[INCLUDEPATH]
+ QT = $$resolve_depends(modules, "QT.")
+ for (module, $$list($${QT})) {
+ INCLUDEPATH *= $$eval($$"QT.$${module}.includes")
+ DEFINES *= $$eval($$"QT.$${module}.DEFINES")
+ }
+}
+
+## Add "qtvars" make target: append "late-bound" variables (e.g. LIBS) to .props (XML) file.
+#
+contains(varNames, LIBS) {
+ varNames -= LIBS
+ nop = "(ECHO>NUL)"
+ qtvars.target = qtvars
+ qtvars.commands = CMD /V:ON /C \
+ \"@ECHO OFF &\
+ SET VALUE= &\
+ (FOR %%x IN (%24(LIBS)) DO (\
+ SET y=%%x&\
+ IF NOT \"!y:~0,9!\"==\"/LIBPATH:\"\
+ SET VALUE=!y!%3B!VALUE!& $$nop \
+ ))&\
+ SET PROP=^<Qt_LIBS_^>!VALUE:~0,-2!^</Qt_LIBS_^>&\
+ ECHO !PROP!>>$$fileName&\"
+ QMAKE_EXTRA_TARGETS += qtvars
+}
+
+## Append Qt variables to .props (XML) file
+#
+for (varName, $$list($$sorted(varNames))) {
+ propName = "Qt_$${varName}_"
+ text = "<$${propName}>"$$formatMsBuildString($$eval($$varName))"</$${propName}>"
+ write_file($$fileName, text, append)
+}
+ ]]>
+ </QtVarsProFileText>
+ <!--
+##
+######## END generated qmake project ###############################################################
+ -->
+ </PropertyGroup>
+
+ <!--// Write .pro file to temp path -->
+ <RemoveDir
+ Directories="$(QtVarsWorkDir)"/>
+ <MakeDir
+ Directories="$(QtVarsWorkDir)"/>
+ <WriteLinesToFile
+ File="$(QtVarsWorkDir)\qtvars.pro"
+ Lines="$(QtVarsProFileConfig)
+ ;$(QtVarsProFileInput)
+ ;$(QtVarsProFileText)"/>
+
+ <!--// Write start of Qt vars data file:
+ // * Add QtConfigStamp property ::= Qt version + selected modules
+ // - used to determine if .props is up-to-date -->
+ <PropertyGroup>
+ <!--
+######## BEGIN generated XML (.props) ##############################################################
+## -->
+ <QtVarsDataFileText>
+ <![CDATA[
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <QtConfigStamp>$(QtInstall)|$(QtModuleNames)</QtConfigStamp>
+ ]]>
+ </QtVarsDataFileText>
+ <!--
+##
+######## END generated XML (.props) ################################################################
+ -->
+ </PropertyGroup>
+ <WriteLinesToFile File="$(QtVarsWorkPath)" Lines="$(QtVarsDataFileText)" Overwrite="true"/>
+
+ <!--// Run qmake && nmake: append output to .props (XML) file -->
+ <SetEnv Name="PATH" Prefix="true" Value="$(ExecutablePath)"/>
+ <PropertyGroup>
+ <Cmd><![CDATA[("$(QtToolsPath)\qmake.exe" && nmake qtvars) 1> qtvars.log 2>&1]]></Cmd>
+ </PropertyGroup>
+ <Exec WorkingDirectory="$(QtVarsWorkDir)" IgnoreExitCode="true" Command="$(Cmd)">
+ <Output TaskParameter="ExitCode" PropertyName="ErrorLevel"/>
+ </Exec>
+
+ <!--// If error, show qmake/nmake console output and stop build -->
+ <ReadLinesFromFile
+ File="$(QtVarsWorkDir)\qtvars.log">
+ <Output TaskParameter="Lines" ItemName="QMakeError"/>
+ </ReadLinesFromFile>
+ <ItemGroup Condition="'$(ErrorLevel)' != '0'">
+ <QMakeError
+ Condition="$([System.String]::Copy('%(Identity)').StartsWith('Info: creating stash file'))"
+ Remove="@(QMakeError)"/>
+ </ItemGroup>
+ <Message
+ Importance="high"
+ Condition="'$(QtVarsDebug)' == 'true'"
+ Text="@(QMakeError->'%(Identity)','%0D%0A')"/>
+ <Error
+ Condition="'$(ErrorLevel)' != '0'"
+ File="$(MSBuildProjectFile)"
+ Text="@(QMakeError->'%(Identity)','%0D%0A')"/>
+
+ <!--// Write end of .props (XML) file
+ // * Close property group tag
+ // * Create QtVar items to export Qt variables to the calling instance of MSBuild
+ // * Close project tag -->
+ <PropertyGroup>
+ <!--
+######## BEGIN generated XML (.props) ##############################################################
+## -->
+ <QtVarsDataFileText>
+ <![CDATA[
+ </PropertyGroup>
+ <ItemGroup>
+ @(QtVarProp->'<QtVar Include="%(Identity)"><Value>%24(%(Identity))</Value></QtVar>', '%0D%0A')
+ </ItemGroup>
+</Project>
+ ]]>
+ </QtVarsDataFileText>
+ <!--
+##
+######## END generated XML (.props) ################################################################
+ -->
+ </PropertyGroup>
+ <WriteLinesToFile File="$(QtVarsWorkPath)" Lines="$(QtVarsDataFileText)"/>
+
+ <!--// Copy generated .props to $(IntDir) -->
+ <Delete
+ Condition="'$(ErrorLevel)' == '0'"
+ Files="$(IntDir)qtvars_$(Platform)_$(Configuration).props"/>
+ <Copy
+ Condition="'$(ErrorLevel)' == '0'"
+ SourceFiles="$(QtVarsWorkPath)" DestinationFiles="$(QtVarsFilePath)"/>
+ <RemoveDir
+ Condition="'$(QtVarsDebug)' != 'true'"
+ Directories="$(QtVarsWorkDir)"/>
+
+ <!--// Skip remaining build -->
+ <CreateProperty Value="true">
+ <Output TaskParameter="ValueSetByTask" PropertyName="QtSkipWork" />
+ </CreateProperty>
+ <CallTarget
+ Condition="'$(QtSkipBuildTargets)' != ''"
+ Targets="$(QtSkipBuildTargets)"/>
+
+ <!--// Restart build in second MSBuild instance with updated Qt variables -->
+ <MSBuild
+ Projects="$(MSBuildProjectFullPath)"
+ Targets="Build"
+ Properties="RandomFileName=$([System.IO.Path]::GetRandomFileName())">
+ </MSBuild>
+
+ <!--// Clean-up -->
+ <ItemGroup>
+ <ProjectItem Remove="@(ProjectItem)"/>
+ <QtModuleList Remove="@(QtModuleList)"/>
+ <QtVariableList Remove="@(QtVariableList)"/>
+ <QMakeCodeLine Remove="@(QMakeCodeLine)"/>
+ </ItemGroup>
+ <PropertyGroup>
+ <QMakeProjTempDir/>
+ <QtVarsTempPath/>
+ <QtModuleNames/>
+ <QMakeVarNames/>
+ <QMakeAdditionalCode/>
+ <QtVarsProFileText/>
+ <Cmd/>
+ </PropertyGroup>
+ </Target>
+
+ <!--
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ /// TARGET QtSkipBuild
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ // Remove source file items in order to skip remaining build process
+ // -->
+ <Target Name="QtSkipBuild">
+ <ItemGroup>
+ <QtMoc Remove="@(QtMoc)"/>
+ <QtRcc Remove="@(QtRcc)"/>
+ <QtRepc Remove="@(QtRepc)"/>
+ <QtUic Remove="@(QtUic)"/>
+ <ClCompile Remove="@(ClCompile)"/>
+ <Link Remove="@(Link)"/>
+ </ItemGroup>
+ </Target>
+
+</Project>
diff --git a/src/qtvstools/QtVsTools.csproj b/src/qtvstools/QtVsTools.csproj
index d75c8d43..2134d88a 100644
--- a/src/qtvstools/QtVsTools.csproj
+++ b/src/qtvstools/QtVsTools.csproj
@@ -564,6 +564,12 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
+ <Content Include="..\qtmsbuild\qt_vars.targets">
+ <Link>QtMsBuild\qt_vars.targets</Link>
+ <SubType>Designer</SubType>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ <IncludeInVSIX>true</IncludeInVSIX>
+ </Content>
<!--
///////////////////////////////////////////////////////////////////////////////////////////////
// Qt/MSBuild moc property pages and targets