<?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>QtVarsPrepare;QtVars;$(QtDependsOn)</QtDependsOn>
    <QtSkipBuildTargets>QtSkipBuild;$(QtSkipBuildTargets)</QtSkipBuildTargets>
    <CleanDependsOn>$(CleanDependsOn);QtVarsClean</CleanDependsOn>
  </PropertyGroup>

  <!--
  /////////////////////////////////////////////////////////////////////////////////////////////////
  /// TARGET QtVars
  /////////////////////////////////////////////////////////////////////////////////////////////////
  // Call qmake with generated .pro file to export Qt variables into MSBuild .props file
  // -->
  <Target
    Name="QtVars"
    Condition="'$(QtVsProjectSettings)' == 'true'"
    DependsOnTargets="QtMocInit;QtUicInit"
    Inputs="$(MSBuildProjectFile)" Outputs="$(QtVarsFilePath)">

    <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
      Condition="!$([System.IO.Path]::IsPathRooted('$(QtPathBinaries)'))"
      Value="$(QtInstallDir)\$(QtPathBinaries)">
      <Output TaskParameter="ValueSetByTask" PropertyName="QtToolsPath" />
    </CreateProperty>
    <CreateProperty
      Condition="$([System.IO.Path]::IsPathRooted('$(QtPathBinaries)'))"
      Value="$(QtPathBinaries)">
      <Output TaskParameter="ValueSetByTask" PropertyName="QtToolsPath" />
    </CreateProperty>

    <!--// Modules and additional .pro file lines -->
    <ItemGroup>
      <QtModuleList Include="$(QtModules)"/>
      <QMakeCodeLine Include="$(QMakeCodeLines)"/>
    </ItemGroup>

    <!--// Generate INCLUDEPATH value -->
    <ItemGroup>
      <QtIncludesList Include="$(QtHeaderSearchPath)"/>
      <QtIncludes Include=
"$([System.IO.Path]::Combine($(QtInstallDir),$([System.String]::Copy('%(QtIncludesList.Identity)'))))"/>
      <QtIncludesList Remove="@(QtIncludesList)"/>
    </ItemGroup>
    <PropertyGroup>
      <QtIncludes>@(QtIncludes->'&quot;%(Identity)&quot;', ' ')</QtIncludes>
    </PropertyGroup>

    <!--// Generate LIBS value -->
    <ItemGroup>
      <QtLibsList Include="$(QtLibrarySearchPath)"/>
      <QtLibs Include=
"$([System.IO.Path]::Combine($(QtInstallDir),$([System.String]::Copy('%(QtLibsList.Identity)'))))"/>
      <QtLibsList Include="@(QtLibsList)"/>
    </ItemGroup>
    <PropertyGroup>
      <QtLibs>@(QtLibs->'&quot;-L%(Identity)&quot;', ' ')</QtLibs>
    </PropertyGroup>

    <Message
      Importance="high"
      Text="Reading Qt configuration ($(QtToolsPath)\qmake.exe)"/>

    <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>
        <!--
# Selected Qt modules -->
        QT += @(QtModuleList->'%(Identity)', ' ')
        <!--
# Custom additional .pro file code (from property page) -->
        @(QMakeCodeLine->'%(Identity)','%0D%0A')
      </QtVarsProFileInput>
      <!--
# Custom additional header search paths (from property page) -->
      <QtVarsProFileInput Condition="'$(QtHeaderSearchPath)' != ''">
        $(QtVarsProFileInput)
        INCLUDEPATH += $(QtIncludes)
      </QtVarsProFileInput>
      <!--
# Custom additional library search paths (from property page) -->
      <QtVarsProFileInput Condition="'$(QtLibrarySearchPath)' != ''">
        $(QtVarsProFileInput)
        LIBS += $(QtLibs)
      </QtVarsProFileInput>
      <!--
# Undef UNICODE macro if project is configured with multi-byte char set -->
      <QtVarsProFileInput Condition="'$(CharacterSet)' == 'MultiByte'">
        $(QtVarsProFileInput)
        DEFINES -= UNICODE _UNICODE
      </QtVarsProFileInput>
    </PropertyGroup>

    <!--// Write .pro file to temp path -->
    <RemoveDir
      Directories="$(QtVarsWorkDir)"/>
    <MakeDir
      Directories="$(QtVarsWorkDir)"/>
    <WriteLinesToFile
      File="$(QtVarsWorkDir)\qtvars.pro"
      Lines="$(QtVarsProFileConfig)
            ;$(QtVarsProFileInput)"/>

    <!--// Write start of Qt vars data file:
        //  * Open property group tag -->
    <PropertyGroup>
      <!--
######## BEGIN generated XML (.props) ##############################################################
##    -->
      <QtVarsDataFileText>
        <![CDATA[
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
        ]]>
      </QtVarsDataFileText>
      <!--
##
######## END generated XML (.props) ################################################################
      -->
    </PropertyGroup>
    <WriteLinesToFile File="$(QtVarsWorkPath)" Lines="$(QtVarsDataFileText)" Overwrite="true"/>

    <!--// Ensure C++ compiler in PATH -->
    <Exec Command="WHERE /Q cl.exe"
      WorkingDirectory="$(QtVarsWorkDir)" IgnoreExitCode="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorLevel"/>
    </Exec>
    <SetEnv Condition="'$(ErrorLevel)' != '0'"
      Name="PATH" Prefix="true" Value="$(ExecutablePath)"/>

    <!--// Run qmake: convert Makefile vars to .props (XML) file -->
    <PropertyGroup>
      <Cmd><![CDATA[("$(QtToolsPath)\qmake.exe") 1> qtvars.log 2>&1]]></Cmd>
    </PropertyGroup>
    <Exec WorkingDirectory="$(QtVarsWorkDir)" IgnoreExitCode="true" Command="$(Cmd)">
      <Output TaskParameter="ExitCode" PropertyName="ErrorLevel"/>
    </Exec>

    <!--// Check qmake result -->
    <PropertyGroup Condition="'$(ErrorLevel)' != '0' OR !Exists('$(QtVarsWorkDir)\Makefile')">
      <QMakeError>true</QMakeError>
    </PropertyGroup>

    <!--// Get qmake console output -->
    <ItemGroup>
      <QMakeError Include="($(QtToolsPath)\qmake.exe)"/>
      <QMakeError Include="%24PWD=$(QtVarsWorkDir)"/>
    </ItemGroup>
    <ReadLinesFromFile
        File="$(QtVarsWorkDir)\qtvars.log">
      <Output TaskParameter="Lines" ItemName="QMakeError"/>
    </ReadLinesFromFile>
    <ItemGroup>
      <QMakeError
        Condition="$([System.String]::Copy('%(Identity)').StartsWith('Info: creating stash file'))"
        Remove="@(QMakeError)"/>
      <QMakeError
        Condition="!Exists('$(QtVarsWorkDir)\Makefile')"
        Include="Error creating Makefile"/>
    </ItemGroup>

    <!--// If error, show qmake console output and stop build -->
    <Error
      Condition="'$(QMakeError)' == 'true'"
      File="$(MSBuildProjectFile)"
      Text="ERROR running qmake%0D%0Aqmake: @(QMakeError->'%(Identity)','%0D%0Aqmake: ')%0D%0A"/>
    <Message
      Importance="high"
      Condition="'$(QMakeError)' != 'true' AND '$(QtVarsDebug)' == 'true'"
      Text="qmake: @(QMakeError->'%(Identity)','%0D%0Aqmake: ')"/>

    <!--// Parse variable definition expressions -->
    <ParseVarDefs
      Condition="'$(QtVars)' != ''" QtVars="$(QtVars)">
      <Output TaskParameter="OutVarDefs" ItemName="QtVarDef"/>
    </ParseVarDefs>

    <!--// Read variables from Makefile -->
    <GetVarsFromMakefile
      Makefile="$(QtVarsWorkDir)\Makefile" VarDefs="@(QtVarDef)">
      <Output TaskParameter="OutVars" ItemName="QtVar"/>
    </GetVarsFromMakefile>

    <!--// Write variables as MSBuild properties to .props file -->
    <PropertyGroup>
      <QtMakefileVars Condition="'@(QtVar)' != ''">
        <![CDATA[@(QtVar->'<Qt_%(Identity)_>%(Value)</Qt_%(Identity)_>','%0D%0A')]]>
      </QtMakefileVars>
    </PropertyGroup>
    <WriteLinesToFile Condition="'$(QtMakefileVars)' != ''"
      File="$(QtVarsWorkPath)" Lines="$([System.String]::Copy($(QtMakefileVars)))"/>

    <!--// Qt settings list for backup -->
    <ItemGroup>
      <QtInstall Include="$(QtInstall)"/>
      <QtModules Include="$(QtModules)"/>
      <QtPathBinaries Include="$(QtPathBinaries)"/>
      <QtPathLibraryExecutables Include="$(QtPathLibraryExecutables)"/>
      <QtHeaderSearchPath Include="$(QtHeaderSearchPath)"/>
      <QtLibrarySearchPath Include="$(QtLibrarySearchPath)"/>
      <QtVariables Include="$(QtVars)"/>
      <QMakeCodeLines Include="$(QMakeCodeLines)"/>
    </ItemGroup>

    <!--// Write end of .props (XML) file
        //  * Add Qt tools output directories to include path
        //  * Save settings backup
        //  * 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[
    <Qt_INCLUDEPATH_
      >%24(Qt_INCLUDEPATH_)%3B@(QtIncludePath->Distinct(),'%3B')</Qt_INCLUDEPATH_>
    <QtBkup_QtInstall
      >@(QtInstall,'%3B')</QtBkup_QtInstall>
    <QtBkup_QtModules
      >@(QtModules,'%3B')</QtBkup_QtModules>
    <QtBkup_QtPathBinaries
      >@(QtPathBinaries,'%3B')</QtBkup_QtPathBinaries>
    <QtBkup_QtPathLibraryExecutables
      >@(QtPathLibraryExecutables,'%3B')</QtBkup_QtPathLibraryExecutables>
    <QtBkup_QtHeaderSearchPath
      >@(QtHeaderSearchPath,'%3B')</QtBkup_QtHeaderSearchPath>
    <QtBkup_QtLibrarySearchPath
      >@(QtLibrarySearchPath,'%3B')</QtBkup_QtLibrarySearchPath>
    <QtBkup_QtVars
      >@(QtVariables,'%3B')</QtBkup_QtVars>
    <QtBkup_QMakeCodeLines
      >@(QMakeCodeLines,'%3B')</QtBkup_QMakeCodeLines>
  </PropertyGroup>
</Project>
        ]]>
      </QtVarsDataFileText>
      <!--
##
######## END generated XML (.props) ################################################################
      -->
    </PropertyGroup>
    <WriteLinesToFile File="$(QtVarsWorkPath)" Lines="$(QtVarsDataFileText)"/>

    <!--// Create $(QtVarsOutputDir) -->
    <MakeDir Directories="$(QtVarsOutputDir)"/>

    <!--// Copy generated .props to $(QtVarsOutputDir) -->
    <Delete
      Condition="'$(ErrorLevel)' == '0'"
      Files="$(QtVarsFilePath)"/>
    <Copy
      Condition="'$(ErrorLevel)' == '0'"
      SourceFiles="$(QtVarsWorkPath)" DestinationFiles="$(QtVarsFilePath)"/>

    <!--// Copy generated qtvars_plugin_import.cpp to $(QtVarsOutputDir) -->
    <Delete
      Condition="'$(ErrorLevel)' == '0'"
      Files="$(QtVarsOutputDir)\qtvars_plugin_import.cpp"/>
    <Copy
      Condition="'$(ErrorLevel)' == '0' AND Exists('$(QtVarsWorkDir)\qtvars_plugin_import.cpp')"
      SourceFiles="$(QtVarsWorkDir)\qtvars_plugin_import.cpp"
      DestinationFiles="$(QtVarsOutputDir)\qtvars_plugin_import.cpp"/>

    <!--// Remove work dir -->
    <RemoveDir
      Condition="'$(QtVarsDebug)' != 'true'"
      Directories="$(QtVarsWorkDir)"/>

    <!--// In design-time, copy generated .props to randomly named file -->
    <PropertyGroup>
      <QtVarsDesignTimeNew
        Condition="'$(ErrorLevel)' == '0'"
        >$([System.IO.Path]::Combine('$(QtVarsOutputDir)',
          'qtvars_$([System.IO.Path]::GetRandomFileName()).designtime.props'))</QtVarsDesignTimeNew>
    </PropertyGroup>
    <Delete
      Condition="'$(ErrorLevel)' == '0'"
      Files="$([System.IO.Directory]::GetFiles('$(QtVarsOutputDir)', '*.designtime.props'))"/>
    <Copy
      Condition="'$(ErrorLevel)' == '0'"
      SourceFiles="$(QtVarsFilePath)" DestinationFiles="$(QtVarsDesignTimeNew)"/>
    <WriteLinesToFile
      Condition="'$(ErrorLevel)' == '0'"
      File="$(QtVarsIndexPathDesignTime)" Overwrite="true" Lines="$(QtVarsDesignTimeNew)"/>

    <!--// Restart build in second MSBuild instance with updated Qt variables -->
    <MSBuild
      Condition="'$(DesignTimeBuild)' != 'true'"
      Projects="$(MSBuildProjectFullPath)"
      Targets="Build"
      Properties="RandomFileName=$([System.IO.Path]::GetRandomFileName())">
    </MSBuild>

    <!--// Skip remaining build -->
    <CreateProperty Value="true">
      <Output TaskParameter="ValueSetByTask" PropertyName="QtSkipWork" />
    </CreateProperty>
    <CallTarget
      Condition="'$(QtSkipBuildTargets)' != ''"
      Targets="$(QtSkipBuildTargets)"/>

    <!--// Clean-up -->
    <ItemGroup>
      <QtModuleList Remove="@(QtModuleList)"/>
      <QMakeCodeLine Remove="@(QMakeCodeLine)"/>
      <QtIncludes Remove="@(QtIncludes)"/>
      <QtLibs Remove="@(QtLibs)"/>
      <QMakeError Remove="@(QMakeError)"/>
      <QtInstall Remove="@(QtInstall)"/>
      <QtModules Remove="@(QtModules)"/>
      <QtPathBinaries Remove="@(QtPathBinaries)"/>
      <QtPathLibraryExecutables Remove="@(QtPathLibraryExecutables)"/>
      <QtHeaderSearchPath Remove="@(QtHeaderSearchPath)"/>
      <QtLibrarySearchPath Remove="@(QtLibrarySearchPath)"/>
      <QtVariables Remove="@(QtVariables)"/>
      <QMakeCodeLines Remove="@(QMakeCodeLines)"/>
      <QtVarDef Remove="@(QtVarDef)"/>
      <QtVar Remove="@(QtVar)"/>
    </ItemGroup>
    <PropertyGroup>
      <QtIncludes/>
      <QtLibs/>
      <QtVarsProFileConfig/>
      <QtVarsProFileInput/>
      <QtVarsDataFileText/>
      <Cmd/>
      <QtMakefileVars/>
    </PropertyGroup>
  </Target>

  <!--
  /////////////////////////////////////////////////////////////////////////////////////////////////
  /// TARGET QtVarsPrepare
  /////////////////////////////////////////////////////////////////////////////////////////////////
  // Force QtVars target to run when Qt settings have changed
  // -->
  <Target Name="QtVarsPrepare" BeforeTargets="QtVars" Condition="Exists('$(QtVarsFilePath)')">
    <Delete Files="$(QtVarsFilePath)" Condition="Exists('$(QtVarsFilePath)')
        AND '$(QtBkup_QtInstall)' != '$(QtInstall)'" />
    <Delete Files="$(QtVarsFilePath)" Condition="Exists('$(QtVarsFilePath)')
        AND '$(QtBkup_QtModules)' != '$(QtModules)'" />
    <Delete Files="$(QtVarsFilePath)" Condition="Exists('$(QtVarsFilePath)')
        AND '$(QtBkup_QtPathBinaries)' != '$(QtPathBinaries)'" />
    <Delete Files="$(QtVarsFilePath)" Condition="Exists('$(QtVarsFilePath)')
        AND '$(QtBkup_QtPathLibraryExecutables)' != '$(QtPathLibraryExecutables)'" />
    <Delete Files="$(QtVarsFilePath)" Condition="Exists('$(QtVarsFilePath)')
        AND '$(QtBkup_QtHeaderSearchPath)' != '$(QtHeaderSearchPath)'" />
    <Delete Files="$(QtVarsFilePath)" Condition="Exists('$(QtVarsFilePath)')
        AND '$(QtBkup_QtLibrarySearchPath)' != '$(QtLibrarySearchPath)'" />
    <Delete Files="$(QtVarsFilePath)" Condition="Exists('$(QtVarsFilePath)')
        AND '$(QtBkup_QtVars)' != '$(QtVars)'" />
    <Delete Files="$(QtVarsFilePath)" Condition="Exists('$(QtVarsFilePath)')
        AND '$(QtBkup_QMakeCodeLines)' != '$(QMakeCodeLines)'" />
  </Target>

  <!--
  /////////////////////////////////////////////////////////////////////////////////////////////////
  /// TARGET QtVarsClean
  /////////////////////////////////////////////////////////////////////////////////////////////////
  // Delete all files generated by the QtVars target
  // -->
  <Target Name="QtVarsClean">
    <RemoveDir Directories="$(QtVarsOutputDir)"/>
  </Target>

  <!--
  /////////////////////////////////////////////////////////////////////////////////////////////////
  /// TARGET QtVarsDesignTime
  /////////////////////////////////////////////////////////////////////////////////////////////////
  // Force QtVars target to run (called when project properties change)
  // -->
  <Target Name="QtVarsDesignTime">
    <CallTarget Targets="QtVarsClean"/>
    <CallTarget Targets="QtVars"/>
  </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)"/>
      <ProjectReference Remove="@(ProjectReference)"/>
    </ItemGroup>
  </Target>

</Project>
