﻿<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
*************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
This code is licensed under the Visual Studio SDK license terms.
THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
*************************************************************************
-->
  <PropertyGroup>
    <VsSDKCommonAssemblyFile Condition="'$(VsSDKCommonAssemblyFile)'==''">Microsoft.VisualStudio.Sdk.BuildTasks.dll</VsSDKCommonAssemblyFile>
    <VsSDKAssemblyFile Condition="'$(VsSDKAssemblyFile)'==''">Microsoft.VisualStudio.Sdk.BuildTasks.17.0.dll</VsSDKAssemblyFile>
  </PropertyGroup>

  <PropertyGroup>
    <BuildToolsArchitecture>*</BuildToolsArchitecture>
    <RuntimeBuildToolsArchitecture>$(BuildToolsArchitecture)</RuntimeBuildToolsArchitecture>
    <Is64BitBuild>false</Is64BitBuild>
    <Is64BitBuild Condition="'$(Platform)' != 'x86' AND '$(PlatformTarget)' != 'x86' AND '$(BuildArchitecture)' != 'x86' AND '$(BuildArchitecture)' != 'i386' ">true</Is64BitBuild>
    <RuntimeBuildToolsArchitecture Condition="'$(Is64BitBuild)' != 'true'">x86</RuntimeBuildToolsArchitecture>

    <RequiredArchitecture>x86</RequiredArchitecture>
    <RequiredArchitecture Condition="'$(Platform)' != 'x86' AND '$(PlatformTarget)' != 'x86' AND '$(BuildArchitecture)' != 'x86' AND '$(BuildArchitecture)' != 'i386' ">amd64</RequiredArchitecture>
    <RequiredArchitecture Condition="'$(PlatformTarget)' == 'arm64' OR '$(Platform)' == 'arm64'">arm64</RequiredArchitecture>
  </PropertyGroup>
  
  <UsingTask TaskName="FindVsSDKInstallation" AssemblyFile="$(VsSDKAssemblyFile)" Architecture="$(BuildToolsArchitecture)" />
  <UsingTask TaskName="VSCTCompiler" AssemblyFile="$(VsSDKAssemblyFile)" Architecture="$(BuildToolsArchitecture)" />
  <UsingTask TaskName="CreateMenuPkgDef" AssemblyFile="$(VsSDKCommonAssemblyFile)" Architecture="$(BuildToolsArchitecture)" />

  <!--
    Set the general properties for this installation of the SDK
  -->
  <PropertyGroup>
    <VsSDKVersion>17.0</VsSDKVersion>
    <VSSDKTargetPlatformVersion>17.0</VSSDKTargetPlatformVersion>
    <VSSDKTargetsPath>$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VsSDKVersion)\VSSDK</VSSDKTargetsPath>
    <VSSDKTargetPlatformRegRoot>Software\Microsoft\VisualStudio\$(VSSDKTargetPlatformVersion)</VSSDKTargetPlatformRegRoot>
    <VSSDKTargetPlatformRegRootSuffix Condition="'$(VSSDKTargetPlatformRegRootSuffix)' == ''">Exp</VSSDKTargetPlatformRegRootSuffix>
  </PropertyGroup>

  <Target Name="FindSDKInstallation">
    <FindVsSDKInstallation InstallationPath="$(VsSDKInstall)"
                           IncludesPath="$(VsSDKIncludes)"
                           ToolsPath="$(VsSDKToolsPath)"
                           ToolsPathX86="$(VsSDKX86ToolsPath)">
      <Output TaskParameter="InstallationPath" PropertyName="VsSDKInstall" />
      <Output TaskParameter="IncludesPath" PropertyName="VsSDKIncludes" />
      <Output TaskParameter="ToolsPath" PropertyName="VsSDKToolsPath" />
      <Output TaskParameter="ToolsPathX86" PropertyName="VsSDKX86ToolsPath" />
    </FindVsSDKInstallation>
  </Target>

  <!--
    =======================================================================================================
                                                VSCT Compilation
    =======================================================================================================
  -->
  <PropertyGroup>
    <VSCTCompileDependsOn>$(VSCTCompileDependsOn);FindSDKInstallation</VSCTCompileDependsOn>
    <!--Make sure that the __CTC__ macro is defined. This macro is used in common headers
        like vsshids.h, so we need it for every VSCT compilation.-->
    <__internal_VSCTDefinitions>__CTC__;_CTC_GUIDS_;$(VSCTDefinitions)</__internal_VSCTDefinitions>
    <VsctVerboseOutput Condition="'$(VsctVerboseOutput)' == ''">false</VsctVerboseOutput>
  </PropertyGroup>

  <ItemGroup>
    <ProjectCapability Include="CompileVsct" />
  </ItemGroup>
  <Target Name="VSCTCompile"
      DependsOnTargets="$(VSCTCompileDependsOn)"
      Condition="'$(BuildingProject)' != 'false' And '@(VSCTCompile)' != ''">

    <!--Create the list of include path to use for the VSCT compilation-->
    <ItemGroup>
      <!--First add the user provided folders-->
      <_InternalVSCTIncludePath Include="@(VSCTIncludePath)" Condition="'@(VSCTIncludePath)' != ''"/>
      <!--Now add the internal folders-->
      <_InternalVSCTIncludePath Include="$(VsSDKIncludes)" Condition="'$(VsSDKIncludes)' != ''"/>
      <_InternalVSCTIncludePath Include="$(VsSDKIncludes)\office10" Condition="'$(VsSDKIncludes)' != ''"/>
    </ItemGroup>

    <VSCTCompiler AdditionalIncludeDirectories="@(_InternalVSCTIncludePath)"
                  IntermediateDirectory="$(IntermediateOutputPath)"
                  Definitions="$(__internal_VSCTDefinitions)"
                  NoLogo="true"
                  OutputFile="%(VSCTCompile.FileName).cto"
                  Source="%(VSCTCompile.Identity)"
                  Verbose="$(VsctVerboseOutput)">
      <Output TaskParameter="TemporaryFiles" ItemName="_TemporaryVsctCompilerFiles"/>
    </VSCTCompiler>

    <!--Record the VSCT compile CTO outputs for the Clean task.-->
    <ItemGroup>
      <FileWrites Include="$(IntermediateOutputPath)%(VSCTCompile.FileName).cto" Condition="Exists('$(IntermediateOutputPath)%(VSCTCompile.FileName).cto')"/>
      <FileWrites Include="@(_TemporaryVsctCompilerFiles)" />
    </ItemGroup>
  </Target>

  <!--
    =======================================================================================================
                                            Force AppId to refresh menu cache
    =======================================================================================================
  -->
  <!-- The goal of this target is to force a change in a Menu entry of a pkgdef file when a .vsct file is updated to force VS to pick up the new .cto -->
  <Target Name="CreateMenuPkgDef"
          Inputs="@(VSCTCompile)"
          Outputs="$(PkgdefFileWithMenuEntry)"
          DependsOnTargets="$(CreateMenuPkgDefDependsOn)"
          AfterTargets="VSCTCompile"
          BeforeTargets="PrepareForRun">
    <CreateMenuPkgDef PkgdefFile="$(PkgdefFileWithMenuEntry)" VsctFile="%(VSCTCompile.FullPath)" Condition="'$(PkgdefFileWithMenuEntry)'!=''"/>
  </Target>


  <!--
    ============================================================
                                        _VsixCleanRecordFileWrites

    Save the list of all files written to disk by the VSIX targets so that it can be used for "Clean" later.

    Files written in prior builds are not removed from Clean cache.
    ============================================================
    -->
  <Target Name="_VsixCleanRecordFileWrites"
          AfterTargets="IncrementalClean">

    <!-- Read the list of files deployed by prior builds from disk. -->
    <ReadLinesFromFile File="$(IntermediateOutputPath)$(VsixCleanFile)">
      <Output TaskParameter="Lines" ItemName="_VsixCleanPriorFileWrites"/>
    </ReadLinesFromFile>

    <!--
        Merge list of files from prior builds with the current build and then
        remove duplicates.
        -->
    <RemoveDuplicates Inputs="@(_VsixCleanPriorFileWrites);@(_VsixDeployCurrentFileWrites)">
      <Output TaskParameter="Filtered" ItemName="_VsixCleanUniqueFileWrites"/>
    </RemoveDuplicates>

    <!-- Make sure the directory exists. -->
    <MakeDir Directories="$(IntermediateOutputPath)"/>

    <!-- Write merged file list back to disk, replacing existing contents. -->
    <WriteLinesToFile File="$(IntermediateOutputPath)$(VsixCleanFile)"
                      Lines="@(_VsixCleanUniqueFileWrites)"
                      Overwrite="true"
                      WriteOnlyWhenDifferent="true"/>
  </Target>

  <!--
    =======================================================================================================
                                         Clean Deployed Vsix Extension Files
    =======================================================================================================
  -->
  <PropertyGroup>
    <VsixCleanFile Condition="'$(VsixCleanFile)'==''">$(MSBuildProjectFile).VsixDeployedFileListAbsolute.txt</VsixCleanFile>
    <ShouldCleanDeployedVsixExtensionFiles Condition="'$(ShouldCleanDeployedVsixExtensionFiles)'==''">true</ShouldCleanDeployedVsixExtensionFiles>
  </PropertyGroup>
  <Target Name="CleanDeployedVsixExtensionFiles"
          BeforeTargets="AfterClean"
          Condition="$(ShouldCleanDeployedVsixExtensionFiles)">

    <!-- Read the list of files deployed by prior builds from disk. -->
    <ReadLinesFromFile File="$(IntermediateOutputPath)$(VsixCleanFile)">
      <Output TaskParameter="Lines" ItemName="_VsixCleanPriorFileWrites"/>
    </ReadLinesFromFile>

    <!-- Remove duplicates. -->
    <RemoveDuplicates Inputs="@(_VsixCleanPriorFileWrites)">
      <Output TaskParameter="Filtered" ItemName="_VsixUniqueCleanPriorFileWrites"/>
    </RemoveDuplicates>

    <Delete Files="@(_VsixUniqueCleanPriorFileWrites)" TreatErrorsAsWarnings="true">
      <Output TaskParameter="DeletedFiles" ItemName="_VsixCleanFilesDeleted"/>
    </Delete>

    <!-- Create a list of everything that wasn't deleted for some reason. -->
    <ItemGroup>
      <_VsixCleanRemainingFileWritesAfterIncrementalClean Include="@(_VsixUniqueCleanPriorFileWrites)" Exclude="@(_VsixCleanFilesDeleted)"/>
    </ItemGroup>

    <!-- Write new list of current files back to disk, replacing the existing list.-->
    <WriteLinesToFile File="$(IntermediateOutputPath)$(VsixCleanFile)"
                      Lines="@(_VsixCleanRemainingFileWritesAfterIncrementalClean)"
                      Condition="'@(_VsixCleanPriorFileWrites)'!='@(_VsixCleanRemainingFileWritesAfterIncrementalClean)'"
                      Overwrite="true"/>
  </Target>
</Project>
