From a9c358bbbdd3b82157135a6071bafd26242dee6d Mon Sep 17 00:00:00 2001
From: Nate McMaster <natemcmaster@users.noreply.github.com>
Date: Tue, 19 Feb 2019 16:28:08 -0800
Subject: [PATCH] Build MSI installers for targeting pack (#7726)

Part of #6501

This adds a new Windows installer for the targeting pack. It places *.dll and *.xml (docs) in `[DOTNETHOME]\packs\Microsoft.AspNetCore.App.Ref\$(version)\ref\netcoreapp3.0`.

Outputs:
* aspnetcore-targeting-pack-$(version).zip
* aspnetcore-targeting-pack-$(version)-win-x64.exe (defaults to C:\Program Files\dotnet)
* aspnetcore-targeting-pack-$(version)-win-x86.exe (defaults to C:\Program Files (x86)\dotnet)

These all include the same files. These are meant to be bundled in the .NET Core SDK installer, but can be launched directly too.
---
 Directory.Build.props                         |  2 +
 build/repo.props                              |  4 +
 .../ref/Microsoft.AspNetCore.App.Ref.csproj   | 27 +++++++
 .../Windows/AspNetCoreModule-Setup/.gitignore |  2 +
 .../SharedFramework/SharedFramework.wixproj   |  2 +-
 .../TargetingPack/DependencyProvider.wxs      | 14 ++++
 .../Windows/TargetingPack/Product.props       | 11 +++
 .../Windows/TargetingPack/Product.wxs         | 74 +++++++++++++++++++
 .../Windows/TargetingPack/Strings.wxl         |  5 ++
 .../TargetingPack/TargetingPack.wixproj       | 67 +++++++++++++++++
 10 files changed, 207 insertions(+), 1 deletion(-)
 create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/.gitignore
 create mode 100644 src/Installers/Windows/TargetingPack/DependencyProvider.wxs
 create mode 100644 src/Installers/Windows/TargetingPack/Product.props
 create mode 100644 src/Installers/Windows/TargetingPack/Product.wxs
 create mode 100644 src/Installers/Windows/TargetingPack/Strings.wxl
 create mode 100644 src/Installers/Windows/TargetingPack/TargetingPack.wixproj

diff --git a/Directory.Build.props b/Directory.Build.props
index 57ff94d85b7..23f27a8c72d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -172,6 +172,8 @@
     <MvcTestingTargets>$(MSBuildThisFileDirectory)src\Mvc\Mvc.Testing\src\Microsoft.AspNetCore.Mvc.Testing.targets</MvcTestingTargets>
     <!-- IIS native projects can only be built on Windows for x86 and x64. -->
     <BuildIisNativeProjects Condition="'$(BuildNative)' != 'false' AND '$(TargetOsName)' == 'win' AND ('$(TargetArchitecture)' == 'x86' OR '$(TargetArchitecture)' == 'x64')">true</BuildIisNativeProjects>
+    <!-- This property is shared by several projects to layout the AspNetCore.App targeting pack for installers -->
+    <TargetingPackLayoutRoot>$(ArtifactsObjDir)TargetingPack.Layout\$(Configuration)\</TargetingPackLayoutRoot>
   </PropertyGroup>
 
   <Import Project="eng\Dependencies.props" />
diff --git a/build/repo.props b/build/repo.props
index 6fe7f20689f..d1393406d24 100644
--- a/build/repo.props
+++ b/build/repo.props
@@ -94,6 +94,10 @@
         <ProjectToBuild Include="$(RepositoryRoot)src\Installers\Windows\AspNetCoreModule-Setup\ANCMV2\ANCMV2.wixproj" AdditionalProperties="Platform=x64" />
         <ProjectToBuild Include="$(RepositoryRoot)src\Installers\Windows\AspNetCoreModule-Setup\ANCMV2\ANCMV2.wixproj" AdditionalProperties="Platform=x86" />
 
+        <!-- Build the targeting pack installers -->
+        <ProjectToBuild Include="$(RepositoryRoot)src\Installers\Windows\TargetingPack\TargetingPack.wixproj" AdditionalProperties="Platform=x64" />
+        <ProjectToBuild Include="$(RepositoryRoot)src\Installers\Windows\TargetingPack\TargetingPack.wixproj" AdditionalProperties="Platform=x86" />
+
         <!-- Build the SharedFramework installers -->
         <ProjectToBuild Include="$(RepositoryRoot)src\Installers\Windows\SharedFrameworkBundle\SharedFrameworkBundle.wixproj" AdditionalProperties="Platform=x64" />
         <ProjectToBuild Include="$(RepositoryRoot)src\Installers\Windows\SharedFrameworkBundle\SharedFrameworkBundle.wixproj" AdditionalProperties="Platform=x86" />
diff --git a/src/Framework/ref/Microsoft.AspNetCore.App.Ref.csproj b/src/Framework/ref/Microsoft.AspNetCore.App.Ref.csproj
index 911bfead8a4..8fa309887fa 100644
--- a/src/Framework/ref/Microsoft.AspNetCore.App.Ref.csproj
+++ b/src/Framework/ref/Microsoft.AspNetCore.App.Ref.csproj
@@ -22,6 +22,10 @@ This package is an internal implementation of the .NET Core SDK and is not meant
     <PackageType>TargetingPack</PackageType>
     <RefAssemblyPackagePath>ref/$(TargetFramework)/</RefAssemblyPackagePath>
 
+    <LayoutTargetDir>$(TargetingPackLayoutRoot)packs/Microsoft.AspNetCore.App.Ref/$(PackageVersion)/$(RefAssemblyPackagePath)</LayoutTargetDir>
+    <ArchiveOutputFileName>aspnetcore-targeting-pack-$(PackageVersion).zip</ArchiveOutputFileName>
+    <ArchiveOutputPath>$(InstallersOutputPath)$(ArchiveOutputFileName)</ArchiveOutputPath>
+
     <!-- There are no symbols for reference assemblies. -->
     <IncludeSymbols>false</IncludeSymbols>
 
@@ -53,6 +57,8 @@ This package is an internal implementation of the .NET Core SDK and is not meant
       GeneratePackageConflictManifest;
       _ResolveTargetingPackContent;
       _BatchCopyToOutputDirectory;
+      _BatchCopyToLayoutTargetDir;
+      _CreateTargetingPackArchive;
     </BuildDependsOn>
   </PropertyGroup>
 
@@ -117,4 +123,25 @@ This package is an internal implementation of the .NET Core SDK and is not meant
           UseHardlinksIfPossible="true" />
   </Target>
 
+  <!-- Written to take advantage of target batching in MSBuild. -->
+  <Target Name="_BatchCopyToLayoutTargetDir"
+          DependsOnTargets="_ResolveTargetingPackContent"
+          Inputs="@(RefPackContent)"
+          Outputs="@(RefPackContent->'$(LayoutTargetDir)%(FileName)%(Extension)')">
+
+    <Copy SourceFiles="@(RefPackContent)"
+          DestinationFiles="@(RefPackContent->'$(LayoutTargetDir)%(FileName)%(Extension)')"
+          UseHardlinksIfPossible="true" />
+  </Target>
+
+  <Target Name="_CreateTargetingPackArchive"
+          Inputs="@(RefPackContent)"
+          Outputs="$(ArchiveOutputPath)"
+          Condition="'$(IsPackable)' != 'false'">
+    <ZipDirectory
+      SourceDirectory="$(TargetingPackLayoutRoot)"
+      DestinationFile="$(ArchiveOutputPath)"
+      Overwrite="true" />
+  </Target>
+
 </Project>
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/.gitignore b/src/Installers/Windows/AspNetCoreModule-Setup/.gitignore
new file mode 100644
index 00000000000..6db035b42a2
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/.gitignore
@@ -0,0 +1,2 @@
+Debug/
+Release/
diff --git a/src/Installers/Windows/SharedFramework/SharedFramework.wixproj b/src/Installers/Windows/SharedFramework/SharedFramework.wixproj
index 242de9fcad4..3e4484cdc7f 100644
--- a/src/Installers/Windows/SharedFramework/SharedFramework.wixproj
+++ b/src/Installers/Windows/SharedFramework/SharedFramework.wixproj
@@ -54,7 +54,7 @@
     </HarvestDirectory>
   </ItemGroup>
 
-  <!-- TODO: harvest shared frameworks from a project reference -->
+  <!-- TODO: https://github.com/aspnet/AspNetCore/issues/6304. Harvest shared frameworks from a project reference -->
   <Target Name="ExtractIntermediateSharedFx" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
       <SharedFrameworkX64HarvestRootPath Condition="'$(SharedFrameworkX64HarvestRootPath)' == ''">$(InstallersOutputPath)</SharedFrameworkX64HarvestRootPath>
diff --git a/src/Installers/Windows/TargetingPack/DependencyProvider.wxs b/src/Installers/Windows/TargetingPack/DependencyProvider.wxs
new file mode 100644
index 00000000000..d62c3dfe7dd
--- /dev/null
+++ b/src/Installers/Windows/TargetingPack/DependencyProvider.wxs
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:dep="http://schemas.microsoft.com/wix/DependencyExtension">
+    <Fragment>
+        <Feature Id="FT_DepProvider" Absent="disallow" AllowAdvertise="no" Description="Used for Ref Counting" Display="hidden" InstallDefault="local" Level="1" Title="RefCounting" TypicalDefault="install">
+            <ComponentRef Id="C_DepProvider" />
+        </Feature>
+
+        <DirectoryRef Id="TARGETDIR">
+            <Component Id="C_DepProvider" Win64="no">
+                <dep:Provides Key="$(var.DepProviderKey)" />
+            </Component>
+        </DirectoryRef>
+    </Fragment>
+</Wix>
\ No newline at end of file
diff --git a/src/Installers/Windows/TargetingPack/Product.props b/src/Installers/Windows/TargetingPack/Product.props
new file mode 100644
index 00000000000..777bf589a63
--- /dev/null
+++ b/src/Installers/Windows/TargetingPack/Product.props
@@ -0,0 +1,11 @@
+<Project>
+  <PropertyGroup>
+    <ProductNameFolder>Microsoft ASP.NET Core Targeting Pack</ProductNameFolder>
+    <ProductName>Microsoft ASP.NET Core $(PackageBrandingVersion) Targeting Pack ($(Platform))</ProductName>
+    <ProductNameShort>AspNetCore.TargetingPack</ProductNameShort>
+
+    <DefineConstants>$(DefineConstants);ProductName=$(ProductName)</DefineConstants>
+    <DefineConstants>$(DefineConstants);ProductNameShort=$(ProductNameShort)</DefineConstants>
+    <DefineConstants>$(DefineConstants);ProductNameFolder=$(ProductNameFolder)</DefineConstants>
+  </PropertyGroup>
+</Project>
diff --git a/src/Installers/Windows/TargetingPack/Product.wxs b/src/Installers/Windows/TargetingPack/Product.wxs
new file mode 100644
index 00000000000..ce7bda6695e
--- /dev/null
+++ b/src/Installers/Windows/TargetingPack/Product.wxs
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+    <Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1033" Version="$(var.Version)"
+             Manufacturer="Microsoft Corporation" UpgradeCode="$(var.UpgradeCode)">
+        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
+
+        <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." Schedule="afterInstallFinalize" />
+        <Media Id="1" Cabinet="$(var.Cabinet)" CompressionLevel="high" EmbedCab="$(var.EmbedCab)" />
+
+        <WixVariable Id="WixUILicenseRtf" Value="$(var.files)\eula.rtf" />
+        <UIRef Id="WixUI_Minimal" />
+
+        <FeatureRef Id="FT_DepProvider" />
+        <FeatureRef Id="FT_AspNetCoreTargetingPack" />
+        <FeatureRef Id="FT_ProductInfo" />
+    </Product>
+
+    <?ifdef PFilesFolder?>
+    <?undef PFilesFolder?>
+    <?endif?>
+
+    <?if $(var.Platform)=x86?>
+    <?define PFilesFolder=ProgramFilesFolder?>
+    <?elseif $(var.Platform)=x64?>
+    <?define PFilesFolder=ProgramFiles64Folder?>
+    <?else?>
+    <?error Invalid Platform ($(var.Platform))?>
+    <?endif?>
+
+    <Fragment>
+        <Directory Id="TARGETDIR" Name="SourceDir">
+            <Directory Id="$(var.PFilesFolder)">
+                <Directory Id="DOTNETHOME" Name="dotnet" />
+            </Directory>
+        </Directory>
+    </Fragment>
+
+    <Fragment>
+        <Feature Id="FT_AspNetCoreTargetingPack" Absent="allow" Description="!(loc.FT_AspNetCoreTargetingPackDescription)" Display="2" Level="1" Title="!(loc.FT_AspNetCoreTargetingPackTitle)">
+            <ComponentGroupRef Id="CG_AspNetCoreTargetingPack" />
+        </Feature>
+    </Fragment>
+
+    <Fragment>
+        <Feature Id="FT_ProductInfo">
+            <ComponentGroupRef Id="CG_ProductInfo" />
+        </Feature>
+
+        <ComponentGroup Id="CG_ProductInfo">
+            <ComponentRef Id="C_ProductVersion"/>
+            <ComponentRef Id="C_ProductInstallDir"/>
+        </ComponentGroup>
+
+        <DirectoryRef Id="DOTNETHOME">
+            <?ifdef ProductVersionKey?>
+            <?undef ProductVersionKey?>
+            <?endif?>
+
+            <?define ProductVersionKey=SOFTWARE\Microsoft\ASP.NET Core\Targeting Pack\v$(var.MajorVersion).$(var.MinorVersion)\$(var.PackageVersion)?>
+
+            <Component Id="C_ProductVersion">
+                <RegistryKey Key="$(var.ProductVersionKey)" Root="HKLM">
+                    <RegistryValue Name="Version" Type="string" Value="$(var.Version)" />
+                </RegistryKey>
+            </Component>
+
+            <Component Id="C_ProductInstallDir">
+                <RegistryKey Key="SOFTWARE\Microsoft\ASP.NET Core\Targeting Pack" Root="HKLM">
+                    <RegistryValue Name="InstallDir" Type="string" Value="[DOTNETHOME]" />
+                </RegistryKey>
+            </Component>
+        </DirectoryRef>
+    </Fragment>
+</Wix>
diff --git a/src/Installers/Windows/TargetingPack/Strings.wxl b/src/Installers/Windows/TargetingPack/Strings.wxl
new file mode 100644
index 00000000000..8b327078538
--- /dev/null
+++ b/src/Installers/Windows/TargetingPack/Strings.wxl
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization">
+    <String Id="FT_AspNetCoreTargetingPackTitle">ASP.NET Core Targeting Pack</String>
+    <String Id="FT_AspNetCoreTargetingPackDescription">ASP.NET Core Targeting Pack</String>
+</WixLocalization>
diff --git a/src/Installers/Windows/TargetingPack/TargetingPack.wixproj b/src/Installers/Windows/TargetingPack/TargetingPack.wixproj
new file mode 100644
index 00000000000..3d571020c68
--- /dev/null
+++ b/src/Installers/Windows/TargetingPack/TargetingPack.wixproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.props))\Directory.Build.props" />
+
+  <Import Project="Product.props" />
+
+  <PropertyGroup>
+    <Name>AspNetCoreTargetingPack</Name>
+    <OutputName>aspnetcore-targeting-pack-$(PackageVersion)-win-$(Platform)</OutputName>
+    <OutputType>Package</OutputType>
+    <IsProductInstaller>true</IsProductInstaller>
+    <ProjectGuid>0AC34F1B-8056-4FFB-A398-E6BB7D67B48D</ProjectGuid>
+    <HarvestDirectoryAutoGenerateGuids>true</HarvestDirectoryAutoGenerateGuids>
+    <HarvestDirectorySuppressSpecificWarnings>5150;5151</HarvestDirectorySuppressSpecificWarnings>
+    <HarvestDirectorySuppressRegistry>true</HarvestDirectorySuppressRegistry>
+    <HarvestSource>$(IntermediateOutputPath)dn\</HarvestSource>
+    <DefineConstants>$(DefineConstants);AspNetCoreTargetingPackSource=$(HarvestSource)</DefineConstants>
+    <NamespaceGuid>DDBB771F-963F-47D3-8510-9ABD04DBE1D1</NamespaceGuid>
+    <SchemaVersion>2.0</SchemaVersion>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <WixExtension Include="WixDependencyExtension">
+      <HintPath>$(WixExtDir)\WixDependencyExtension.dll</HintPath>
+      <Name>WixDependencyExtension</Name>
+    </WixExtension>
+    <WixExtension Include="WixNetFxExtension">
+      <HintPath>$(WixExtDir)\WixNetFxExtension.dll</HintPath>
+      <Name>WixNetFxExtension</Name>
+    </WixExtension>
+    <WixExtension Include="WixUtilExtension">
+      <HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
+      <Name>WixUtilExtension</Name>
+    </WixExtension>
+    <WixExtension Include="WixUIExtension">
+      <HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
+      <Name>WixUIExtension</Name>
+    </WixExtension>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Include="DependencyProvider.wxs" />
+    <Compile Include="Product.wxs" />
+    <EmbeddedResource Include="Strings.wxl" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <HarvestDirectory Include="$(HarvestSource)">
+      <SuppressRootDirectory>true</SuppressRootDirectory>
+      <ComponentGroupName>CG_AspNetCoreTargetingPack</ComponentGroupName>
+      <DirectoryRefId>DOTNETHOME</DirectoryRefId>
+      <PreprocessorVariable>var.AspNetCoreTargetingPackSource</PreprocessorVariable>
+    </HarvestDirectory>
+  </ItemGroup>
+
+  <!-- TODO: https://github.com/aspnet/AspNetCore/issues/6304. harvest from TargetingPackLayoutRoot directly. Unzipping is currently required because the zip has the signed versions of .dll files. -->
+  <Target Name="ExtractIntermediateTargetingPack" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <TargetingPackHarvestRoot Condition="'$(TargetingPackHarvestRoot)' == ''">$(InstallersOutputPath)</TargetingPackHarvestRoot>
+      <IntermediateTargetingPackZip>$(TargetingPackHarvestRoot)aspnetcore-targeting-pack-$(PackageVersion).zip</IntermediateTargetingPackZip>
+    </PropertyGroup>
+
+    <Unzip SourceFiles="$(IntermediateTargetingPackZip)" DestinationFolder="$(HarvestSource)" />
+  </Target>
+
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.targets))\Directory.Build.targets" />
+</Project>
-- 
GitLab