Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Create targeting pack MSI installers #5114

Merged
merged 7 commits into from
Feb 14, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ jobs:
# Windows x86
- template: /eng/jobs/windows-build.yml
parameters:
buildFullPlatformManifest: true
displayName: Build_Windows_x86
targetArchitecture: x86

Expand Down
7 changes: 7 additions & 0 deletions dir.props
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,14 @@
<DotnetHostString>dotnet-host-</DotnetHostString>
<DotnetHostFxrString>dotnet-hostfxr-</DotnetHostFxrString>
<DotnetRuntimeString>dotnet-runtime-</DotnetRuntimeString>
<DotnetTargetingPackString>dotnet-netcoreapp-targeting-pack-</DotnetTargetingPackString>
<DotnetRuntimeDependenciesPackageString>dotnet-runtime-deps-</DotnetRuntimeDependenciesPackageString>

<CombinedInstallerStart>$(AssetOutputPath)$(DotnetRuntimeString)</CombinedInstallerStart>
<SharedHostInstallerStart>$(AssetOutputPath)$(DotnetHostString)</SharedHostInstallerStart>
<HostFxrInstallerStart>$(AssetOutputPath)$(DotnetHostFxrString)</HostFxrInstallerStart>
<SharedFrameworkInstallerStart>$(AssetOutputPath)$(DotnetRuntimeString)</SharedFrameworkInstallerStart>
<TargetingPackInstallerStart>$(AssetOutputPath)$(DotnetTargetingPackString)</TargetingPackInstallerStart>
<DotnetRuntimeDependenciesPackageInstallerStart>$(AssetOutputPath)$(DotnetRuntimeDependenciesPackageString)</DotnetRuntimeDependenciesPackageInstallerStart>

<!-- OSX specific intermediate package suffix . OSX specific intermediate packages are suffixed with -internal to avoid name collision for bundle package (dotnet-runtime-*)
Expand All @@ -298,6 +301,7 @@
<SharedHostInstallerStart Condition="'$(OSGroup)' == 'OSX'">$(SharedHostInstallerStart)$(InstallerStartSuffix)-</SharedHostInstallerStart>
<HostFxrInstallerStart Condition="'$(OSGroup)' == 'OSX'">$(HostFxrInstallerStart)$(InstallerStartSuffix)-</HostFxrInstallerStart>
<SharedFrameworkInstallerStart Condition="'$(OSGroup)' == 'OSX'">$(SharedFrameworkInstallerStart)$(InstallerStartSuffix)-</SharedFrameworkInstallerStart>
<TargetingPackInstallerStart Condition="'$(OSGroup)' == 'OSX'">$(TargetingPackInstallerStart)$(InstallerStartSuffix)-</TargetingPackInstallerStart>

</PropertyGroup>

Expand Down Expand Up @@ -428,9 +432,12 @@
<PropertyGroup>
<CombinedInstallerFile>$(CombinedInstallerStart)$(ProductMoniker)$(CombinedInstallerExtension)</CombinedInstallerFile>
<CombinedInstallerEngine>$(CombinedInstallerStart)$(ProductMoniker)-engine.exe</CombinedInstallerEngine>

<SharedHostInstallerFile>$(SharedHostInstallerStart)$(ProductMoniker)$(InstallerExtension)</SharedHostInstallerFile>
<HostFxrInstallerFile>$(HostFxrInstallerStart)$(HostResolverVersionMoniker)$(InstallerExtension)</HostFxrInstallerFile>
<SharedFrameworkInstallerFile>$(SharedFrameworkInstallerStart)$(ProductMoniker)$(InstallerExtension)</SharedFrameworkInstallerFile>
<TargetingPackInstallerFile>$(TargetingPackInstallerStart)$(ProductMoniker)$(InstallerExtension)</TargetingPackInstallerFile>

<!-- Runtime Deb and Rpm packages are distro version agnostic -->
<SharedHostInstallerFile Condition="'$(InstallerExtension)' == '.deb' or '$(InstallerExtension)' == '.rpm' ">$(SharedHostInstallerStart)$(SharedFrameworkNugetVersion)-$(TargetArchitecture)$(InstallerExtension)</SharedHostInstallerFile>
<HostFxrInstallerFile Condition="'$(InstallerExtension)' == '.deb' or '$(InstallerExtension)' == '.rpm'">$(HostFxrInstallerStart)$(HostResolverVersion)-$(TargetArchitecture)$(InstallerExtension)</HostFxrInstallerFile>
Expand Down
3 changes: 3 additions & 0 deletions src/pkg/packaging/dir.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
<!-- Package prebuilt binaries -->
<UsePrebuiltPortableBinariesForInstallers>false</UsePrebuiltPortableBinariesForInstallers>

<!-- Use trailing '/'. Heat.exe doesn't accept a trailing '\'.-->
<PackagesIntermediateDir>$(IntermediateOutputRootPath)packages/</PackagesIntermediateDir>
<SharedHostPublishRoot>$(IntermediateOutputRootPath)sharedHost/</SharedHostPublishRoot>
<HostFxrPublishRoot>$(IntermediateOutputRootPath)hostFxr/</HostFxrPublishRoot>
<SharedFrameworkPublishRoot>$(IntermediateOutputRootPath)sharedFx/</SharedFrameworkPublishRoot>
<TargetingPackPublishRoot>$(IntermediateOutputRootPath)Microsoft.NETCore.App.Ref/layout/</TargetingPackPublishRoot>
<CombinedPublishRoot>$(IntermediateOutputRootPath)combined-framework-host/</CombinedPublishRoot>
</PropertyGroup>

Expand All @@ -28,6 +30,7 @@
<ProductBrandSuffix Condition="'$(ReleaseBrandSuffix)'!=''">$(ProductionVersion) $(ReleaseBrandSuffix)</ProductBrandSuffix>
<SharedHostBrandName>$(ProductBrandPrefix) Host - $(ProductBrandSuffix)</SharedHostBrandName>
<HostFxrBrandName>$(ProductBrandPrefix) Host FX Resolver - $(ProductBrandSuffix)</HostFxrBrandName>
<TargetingPackBrandName>$(ProductBrandPrefix) App Targeting Pack - $(ProductBrandSuffix)</TargetingPackBrandName>
dagood marked this conversation as resolved.
Show resolved Hide resolved
<SharedFrameworkBrandName>$(ProductBrandPrefix) Runtime - $(ProductBrandSuffix)</SharedFrameworkBrandName>
</PropertyGroup>
</Project>
10 changes: 10 additions & 0 deletions src/pkg/packaging/windows/package.targets
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
<Output TaskParameter="GeneratedGui" PropertyName="HostFxrUpgradeCode" />
</GenerateGuidFromName>

<GenerateGuidFromName Name="$(TargetingPackInstallerFile)">
<Output TaskParameter="GeneratedGui" PropertyName="TargetingPackUpgradeCode" />
dagood marked this conversation as resolved.
Show resolved Hide resolved
</GenerateGuidFromName>

<ItemGroup>
<WixOutputs Include="$(WixObjRoot)host">
<InputDir>$(SharedHostPublishRoot)</InputDir>
Expand All @@ -60,6 +64,12 @@
<InstallerName>$(HostFxrInstallerFile)</InstallerName>
<UpgradeCode>$(HostFxrUpgradeCode)</UpgradeCode>
</WixOutputs>
<WixOutputs Include="$(WixObjRoot)targetingpack">
<InputDir>$(TargetingPackPublishRoot)</InputDir>
<BrandName>$(TargetingPackBrandName)</BrandName>
<InstallerName>$(TargetingPackInstallerFile)</InstallerName>
<UpgradeCode>$(TargetingPackUpgradeCode)</UpgradeCode>
</WixOutputs>
<!-- shared framework has extra arguments so it needs to be in a separate group -->
<WixOutputs2 Include="$(WixObjRoot)sharedframework">
<InputDir>$(SharedFrameworkPublishRoot)</InputDir>
Expand Down
162 changes: 162 additions & 0 deletions src/pkg/packaging/windows/targetingpack/generatemsi.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Copyright (c) .NET Foundation and contributors. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.

param(
[Parameter(Mandatory=$true)][string]$TargetingPackPublishRoot,
[Parameter(Mandatory=$true)][string]$TargetingPackMSIOutput,
[Parameter(Mandatory=$true)][string]$WixRoot,
[Parameter(Mandatory=$true)][string]$ProductMoniker,
[Parameter(Mandatory=$true)][string]$TargetingPackMSIVersion,
[Parameter(Mandatory=$true)][string]$TargetingPackNugetVersion,
[Parameter(Mandatory=$true)][string]$Architecture,
[Parameter(Mandatory=$true)][string]$TargetArchitecture,
[Parameter(Mandatory=$true)][string]$WixObjRoot,
[Parameter(Mandatory=$true)][string]$TargetingPackUpgradeCode
)

$RepoRoot = Convert-Path "$PSScriptRoot\..\..\..\..\.."
$CommonScript = "$RepoRoot\tools-local\scripts\common\_common.ps1"

if(-Not (Test-Path "$CommonScript"))
{
Exit -1
}
. "$CommonScript"

$PackagingRoot = Join-Path $RepoRoot "src\pkg\packaging"

$InstallFileswsx = "$WixObjRoot\install-files.wxs"
$InstallFilesWixobj = "$WixObjRoot\install-files.wixobj"

function RunHeat
{
$result = $true
pushd "$WixRoot"

Write-Host Running heat.. to $InstallFileswsx
write-host "Root $TargetingPackPublishRoot"
dagood marked this conversation as resolved.
Show resolved Hide resolved

.\heat.exe dir `"$TargetingPackPublishRoot`" `
-nologo `
dagood marked this conversation as resolved.
Show resolved Hide resolved
-template fragment `
-sreg -gg `
-var var.TargetingPackSrc `
-cg InstallFiles `
-srd `
-dr DOTNETHOME `
-out $InstallFileswsx | Out-Host

if($LastExitCode -ne 0)
{
$result = $false
Write-Host "Heat failed with exit code $LastExitCode."
}

popd
return $result
}

function RunCandle
{
$result = $true
pushd "$WixRoot"

Write-Host Running candle..
$AuthWsxRoot = Join-Path $PackagingRoot "windows\targetingpack"
dagood marked this conversation as resolved.
Show resolved Hide resolved

$ComponentVersion = $TargetingPackNugetVersion.Replace('-', '_');

.\candle.exe -nologo `
-out "$WixObjRoot\" `
-dTargetingPackSrc="$TargetingPackPublishRoot" `
-dMicrosoftEula="$PackagingRoot\windows\eula.rtf" `
-dProductMoniker="$ProductMoniker" `
-dBuildVersion="$TargetingPackMSIVersion" `
-dNugetVersion="$TargetingPackNugetVersion" `
-dComponentVersion="$ComponentVersion" `
-dTargetArchitecture="$TargetArchitecture" `
-dUpgradeCode="$TargetingPackUpgradeCode" `
-arch $Architecture `
-ext WixDependencyExtension.dll `
"$AuthWsxRoot\targetingpack.wxs" `
"$AuthWsxRoot\provider.wxs" `
$InstallFileswsx | Out-Host

if($LastExitCode -ne 0)
{
$result = $false
Write-Host "Candle failed with exit code $LastExitCode."
}

popd
return $result
}

function RunLight
{
$result = $true
pushd "$WixRoot"

Write-Host Running light..

.\light.exe -nologo `
-ext WixUIExtension.dll `
-ext WixDependencyExtension.dll `
-ext WixUtilExtension.dll `
-cultures:en-us `
"$WixObjRoot\targetingpack.wixobj" `
"$WixObjRoot\provider.wixobj" `
"$InstallFilesWixobj" `
-out $TargetingPackMSIOutput | Out-Host

if($LastExitCode -ne 0)
{
$result = $false
Write-Host "Light failed with exit code $LastExitCode."
}

popd
return $result
}

if(!(Test-Path $TargetingPackPublishRoot))
{
throw "$TargetingPackPublishRoot not found"
}

if(!(Test-Path $WixObjRoot))
{
throw "$WixObjRoot not found"
}

Write-Host "Creating Targeting Pack MSI at $TargetingPackMSIOutput"

if([string]::IsNullOrEmpty($WixRoot))
{
Exit -1
}

if(-Not (RunHeat))
{
Exit -1
}

if(-Not (RunCandle))
{
Exit -1
}

if(-Not (RunLight))
{
Exit -1
}

if(!(Test-Path $TargetingPackMSIOutput))
{
throw "Unable to create the Targeting Pack MSI."
Exit -1
dagood marked this conversation as resolved.
Show resolved Hide resolved
}

Write-Host -ForegroundColor Green "Successfully created Targeting Pack MSI - $TargetingPackMSIOutput"

exit $LastExitCode
9 changes: 9 additions & 0 deletions src/pkg/packaging/windows/targetingpack/provider.wxs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:dep="http://schemas.microsoft.com/wix/DependencyExtension">
<?include "Variables.wxi" ?>
<Fragment>
<Component Id="$(var.DependencyKeyId)" Directory="TARGETDIR" Win64="no" Guid="117B1755-5027-4257-A1A9-7C37D81C3D5F">
<dep:Provides Key="$(var.DependencyKey)" />
</Component>
</Fragment>
</Wix>
36 changes: 36 additions & 0 deletions src/pkg/packaging/windows/targetingpack/targetingpack.wxs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this appears to be boilerplate yet it is still copy/pasted in every installer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah... I'm definitely planning to look into using some common WiX files as part of refactoring.

<?include "Variables.wxi" ?>
<Product Id="*" Name="$(var.ProductName)" Language="$(var.ProductLanguage)" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<Package Compressed="yes" InstallScope="perMachine" InstallerVersion="200" />

<MajorUpgrade DowngradeErrorMessage="$(var.DowngradeErrorMessage)" Schedule="afterInstallInitialize"/>

<MediaTemplate CompressionLevel="high" EmbedCab="yes" />

<Feature Id="MainFeature" Title="Main Feature" Level="1">
<ComponentGroupRef Id="InstallFiles" />
</Feature>
<Feature Id="Provider" Absent="disallow" AllowAdvertise="no" Description="Used for Ref Counting" Display="hidden" Level="1" InstallDefault="local" Title="RefCounting" TypicalDefault="install">
<ComponentRef Id="$(var.DependencyKeyId)" />
</Feature>
<Property Id="ProductCPU" Value="$(var.Platform)" />
<Property Id="RTM_ProductVersion" Value="$(var.Dotnet_ProductVersion)" />

<Property Id="MSIFASTINSTALL" Value="7" />

<WixVariable Id="WixUILicenseRtf" Value="$(var.MicrosoftEula)" />

<Property Id="WIXUI_INSTALLDIR" Value="DOTNETHOME"/>
<UIRef Id="WixUI_InstallDir" />

<CustomActionRef Id="WixBroadcastEnvironmentChange" />
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.Program_Files)">
<Directory Id="DOTNETHOME" Name="dotnet"/>
</Directory>
</Directory>
</Fragment>
</Wix>
26 changes: 26 additions & 0 deletions src/pkg/packaging/windows/targetingpack/variables.wxi
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">

<?define Dotnet_ProductVersion = "$(var.BuildVersion)" ?>
<?define Dotnet_BuildVersion = "$(var.BuildVersion)" ?>
<?define Manufacturer = "Microsoft Corporation" ?>
<?define ProductName = "$(var.ProductMoniker) ($(var.TargetArchitecture))" ?>
<?define ProductLanguage = "1033" ?>
<?define ProductVersion = "$(var.Dotnet_ProductVersion)" ?>
<?define LCID = "$(var.ProductLanguage)"?>
<?define DowngradeErrorMessage = "A newer version is already installed; please uninstall it and re-run setup."?>

<?define Platform = "$(sys.BUILDARCH)" ?>
<?if $(var.Platform)=x86?>
<?define Program_Files="ProgramFilesFolder"?>
<?define Win64AttributeValue=no?>
<?elseif $(var.Platform)=x64?>
<?define Program_Files="ProgramFiles64Folder"?>
<?define Win64AttributeValue=yes?>
<?else?>
<?error Invalid Platform ($(var.Platform))?>
<?endif?>

<?define DependencyKey = "Dotnet_CLI_TargetingPack_$(var.BuildVersion)_$(var.Platform)"?>
dagood marked this conversation as resolved.
Show resolved Hide resolved
<?define DependencyKeyId = "$(var.DependencyKey)" ?>
</Include>
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
<!-- Remove package dependencies. -->
<ExcludeLineupReference>true</ExcludeLineupReference>
<PackProjectDependencies>false</PackProjectDependencies>

<!-- Location to lay out data/ dir. Used later to create installers. -->
<DataLayoutDir>$(IntermediateOutputPath)layout/</DataLayoutDir>
</PropertyGroup>

<!-- Redistribute package content from other nuget packages. -->
Expand All @@ -39,4 +42,35 @@
</ItemGroup>
</Target>

<!--
Copy the files in the package's data/ dir to a layout directory. This is what the targeting pack
installer will place in the dotnet install dir.

This extracts from the nupkg (zip) directly. An alternative would be using the PackageFile
items, but there's some risk of handling TargetPath metadata differently than NuGet does. Using
the nupkg directly ensures results are identical.
-->
<Target Name="CreateTargetingPackLayout"
AfterTargets="CreatePackage">
<PropertyGroup>
<TargetingPackNupkgFile>$(PackageOutputPath)$(Id).$(PackageVersion).nupkg</TargetingPackNupkgFile>
</PropertyGroup>

<ZipFileGetEntries TargetArchive="$(TargetingPackNupkgFile)">
<Output TaskParameter="Entries" ItemName="TargetingPackNupkgEntries" />
</ZipFileGetEntries>

<ItemGroup>
<TargetingPackDataEntries
Include="@(TargetingPackNupkgEntries)"
Condition="$([System.String]::new('%(TargetingPackNupkgEntries.Identity)').StartsWith('data/'))" />
</ItemGroup>

<ZipFileExtractToDirectory
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you pull them from the package? Just a couple targets before this you have the entire contents in items (@(File) if I remember correctly).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a bit of reasoning in the target comment:

This extracts from the nupkg (zip) directly. An alternative would be using the PackageFile items, but there's some risk of handling TargetPath metadata differently than NuGet does. Using the nupkg directly ensures results are identical.

It is slower to decompress it, I'm just coding a little defensively here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't find that defensive, it's just adding complexity. We define TargetPath and consume it, you can rely on it, of if you can't that's a bug that we fix.

Another thing to consider is inserting a layout phase between collecting assets and pack. That way the content of the pack can be defined by the layout instead of vice-versa.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true. I did add a file in #5168 that has a non-folder TargetPath, which is the kind of thing I wanted to avoid handling--but it looks like that's actually the only one, and I don't need to do it that way. I'll get rid of this.

A layout-first approach sounds much better. I'll shoot for that.

SourceArchive="$(TargetingPackNupkgFile)"
DestinationDirectory="$(DataLayoutDir)ref/$(Id)/$(Version)/"
nguerrera marked this conversation as resolved.
Show resolved Hide resolved
OverwriteDestination="true"
Include="@(TargetingPackDataEntries)" />
</Target>

</Project>