From 40de0f80d0b5fbd807231ff7ea2d1508e110d821 Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Wed, 21 Feb 2018 10:40:32 -0800 Subject: [PATCH 1/3] move new-msipackage to packaging.psm1 --- build.psm1 | 151 --------------------------------- tools/packaging/packaging.psm1 | 151 +++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 151 deletions(-) diff --git a/build.psm1 b/build.psm1 index 3cf30f5836b..760df04f07f 100644 --- a/build.psm1 +++ b/build.psm1 @@ -2075,157 +2075,6 @@ function Get-PackageVersionAsMajorMinorBuildRevision $packageVersion } -<# - .Synopsis - Creates a Windows installer MSI package and assumes that the binaries are already built using 'Start-PSBuild'. - This only works on a Windows machine due to the usage of WiX. - .EXAMPLE - # This example shows how to produce a Debug-x64 installer for development purposes. - cd $RootPathOfPowerShellRepo - Import-Module .\build.psm1; Import-Module .\tools\packaging\packaging.psm1 - New-MSIPackage -Verbose -ProductCode (New-Guid) -ProductSourcePath '.\src\powershell-win-core\bin\Debug\netcoreapp2.0\win7-x64\publish' -ProductTargetArchitecture x64 -ProductVersion '1.2.3' -#> -function New-MSIPackage -{ - [CmdletBinding()] - param ( - - # Name of the Product - [ValidateNotNullOrEmpty()] - [string] $ProductName = 'PowerShell', - - # Suffix of the Name - [string] $ProductNameSuffix, - - # Version of the Product - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [string] $ProductVersion, - - # The ProductCode property is a unique identifier for the particular product release - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [string] $ProductCode, - - # Source Path to the Product Files - required to package the contents into an MSI - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [string] $ProductSourcePath, - - # File describing the MSI Package creation semantics - [ValidateNotNullOrEmpty()] - [ValidateScript( {Test-Path $_})] - [string] $ProductWxsPath = "$PSScriptRoot\assets\Product.wxs", - - # Path to Assets folder containing artifacts such as icons, images - [ValidateNotNullOrEmpty()] - [ValidateScript( {Test-Path $_})] - [string] $AssetsPath = "$PSScriptRoot\assets", - - # Path to license.rtf file - for the EULA - [ValidateNotNullOrEmpty()] - [ValidateScript( {Test-Path $_})] - [string] $LicenseFilePath = "$PSScriptRoot\assets\license.rtf", - - # Architecture to use when creating the MSI - [Parameter(Mandatory = $true)] - [ValidateSet("x86", "x64")] - [ValidateNotNullOrEmpty()] - [string] $ProductTargetArchitecture, - - # Force overwrite of package - [Switch] $Force - ) - - ## AppVeyor base image might update the version for Wix. Hence, we should - ## not hard code version numbers. - $wixToolsetBinPath = "${env:ProgramFiles(x86)}\WiX Toolset *\bin" - - Write-Verbose "Ensure Wix Toolset is present on the machine @ $wixToolsetBinPath" - if (-not (Test-Path $wixToolsetBinPath)) - { - throw "The latest version of Wix Toolset 3.11 is required to create MSI package. Please install it from https://github.com/wixtoolset/wix3/releases" - } - - ## Get the latest if multiple versions exist. - $wixToolsetBinPath = (Get-ChildItem $wixToolsetBinPath).FullName | Sort-Object -Descending | Select-Object -First 1 - - Write-Verbose "Initialize Wix executables - Heat.exe, Candle.exe, Light.exe" - $wixHeatExePath = Join-Path $wixToolsetBinPath "Heat.exe" - $wixCandleExePath = Join-Path $wixToolsetBinPath "Candle.exe" - $wixLightExePath = Join-Path $wixToolsetBinPath "Light.exe" - - $ProductSemanticVersion = Get-PackageSemanticVersion -Version $ProductVersion - $ProductVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $ProductVersion - - $assetsInSourcePath = Join-Path $ProductSourcePath 'assets' - New-Item $assetsInSourcePath -type directory -Force | Write-Verbose - - Write-Verbose "Place dependencies such as icons to $assetsInSourcePath" - Copy-Item "$AssetsPath\*.ico" $assetsInSourcePath -Force - - $productVersionWithName = $ProductName + '_' + $ProductVersion - $productSemanticVersionWithName = $ProductName + '-' + $ProductSemanticVersion - - Write-Verbose "Create MSI for Product $productSemanticVersionWithName" - - [Environment]::SetEnvironmentVariable("ProductSourcePath", $ProductSourcePath, "Process") - # These variables are used by Product.wxs in assets directory - [Environment]::SetEnvironmentVariable("ProductName", $ProductName, "Process") - [Environment]::SetEnvironmentVariable("ProductCode", $ProductCode, "Process") - [Environment]::SetEnvironmentVariable("ProductVersion", $ProductVersion, "Process") - [Environment]::SetEnvironmentVariable("ProductSemanticVersion", $ProductSemanticVersion, "Process") - [Environment]::SetEnvironmentVariable("ProductVersionWithName", $productVersionWithName, "Process") - $ProductProgFilesDir = "ProgramFiles64Folder" - if ($ProductTargetArchitecture -eq "x86") - { - $ProductProgFilesDir = "ProgramFilesFolder" - } - [Environment]::SetEnvironmentVariable("ProductProgFilesDir", $ProductProgFilesDir, "Process") - - $wixFragmentPath = Join-Path $env:Temp "Fragment.wxs" - $wixObjProductPath = Join-Path $env:Temp "Product.wixobj" - $wixObjFragmentPath = Join-Path $env:Temp "Fragment.wixobj" - - $packageName = $productSemanticVersionWithName - if ($ProductNameSuffix) { - $packageName += "-$ProductNameSuffix" - } - $msiLocationPath = Join-Path $pwd "$packageName.msi" - - if(!$Force.IsPresent -and (Test-Path -Path $msiLocationPath)) - { - Write-Error -Message "Package already exists, use -Force to overwrite, path: $msiLocationPath" -ErrorAction Stop - } - - $WiXHeatLog = & $wixHeatExePath dir $ProductSourcePath -dr $productVersionWithName -cg $productVersionWithName -gg -sfrag -srd -scom -sreg -out $wixFragmentPath -var env.ProductSourcePath -v - $WiXCandleLog = & $wixCandleExePath "$ProductWxsPath" "$wixFragmentPath" -out (Join-Path "$env:Temp" "\\") -ext WixUIExtension -ext WixUtilExtension -arch $ProductTargetArchitecture -v - $WiXLightLog = & $wixLightExePath -out $msiLocationPath $wixObjProductPath $wixObjFragmentPath -ext WixUIExtension -ext WixUtilExtension -dWixUILicenseRtf="$LicenseFilePath" -v - - Remove-Item -ErrorAction SilentlyContinue *.wixpdb -Force - Remove-Item -ErrorAction SilentlyContinue $wixFragmentPath -Force - Remove-Item -ErrorAction SilentlyContinue $wixObjProductPath -Force - Remove-Item -ErrorAction SilentlyContinue $wixObjFragmentPath -Force - - if (Test-Path $msiLocationPath) - { - Write-Verbose "You can find the MSI @ $msiLocationPath" -Verbose - $msiLocationPath - } - else - { - $WiXHeatLog | Out-String | Write-Verbose -Verbose - $WiXCandleLog | Out-String | Write-Verbose -Verbose - $WiXLightLog | Out-String | Write-Verbose -Verbose - $errorMessage = "Failed to create $msiLocationPath" - if ($null -ne $env:CI) - { - Add-AppveyorCompilationMessage $errorMessage -Category Error -FileName $MyInvocation.ScriptName -Line $MyInvocation.ScriptLineNumber - } - throw $errorMessage - } -} - function Start-CrossGen { [CmdletBinding()] param( diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index dc96def14f2..49fb6e4e46c 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -1429,3 +1429,154 @@ function Get-NugetSemanticVersion $packageSemanticVersion } + +<# + .Synopsis + Creates a Windows installer MSI package and assumes that the binaries are already built using 'Start-PSBuild'. + This only works on a Windows machine due to the usage of WiX. + .EXAMPLE + # This example shows how to produce a Debug-x64 installer for development purposes. + cd $RootPathOfPowerShellRepo + Import-Module .\build.psm1; Import-Module .\tools\packaging\packaging.psm1 + New-MSIPackage -Verbose -ProductCode (New-Guid) -ProductSourcePath '.\src\powershell-win-core\bin\Debug\netcoreapp2.0\win7-x64\publish' -ProductTargetArchitecture x64 -ProductVersion '1.2.3' +#> +function New-MSIPackage +{ + [CmdletBinding()] + param ( + + # Name of the Product + [ValidateNotNullOrEmpty()] + [string] $ProductName = 'PowerShell', + + # Suffix of the Name + [string] $ProductNameSuffix, + + # Version of the Product + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $ProductVersion, + + # The ProductCode property is a unique identifier for the particular product release + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $ProductCode, + + # Source Path to the Product Files - required to package the contents into an MSI + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $ProductSourcePath, + + # File describing the MSI Package creation semantics + [ValidateNotNullOrEmpty()] + [ValidateScript( {Test-Path $_})] + [string] $ProductWxsPath = "$PSScriptRoot\assets\Product.wxs", + + # Path to Assets folder containing artifacts such as icons, images + [ValidateNotNullOrEmpty()] + [ValidateScript( {Test-Path $_})] + [string] $AssetsPath = "$PSScriptRoot\assets", + + # Path to license.rtf file - for the EULA + [ValidateNotNullOrEmpty()] + [ValidateScript( {Test-Path $_})] + [string] $LicenseFilePath = "$PSScriptRoot\assets\license.rtf", + + # Architecture to use when creating the MSI + [Parameter(Mandatory = $true)] + [ValidateSet("x86", "x64")] + [ValidateNotNullOrEmpty()] + [string] $ProductTargetArchitecture, + + # Force overwrite of package + [Switch] $Force + ) + + ## AppVeyor base image might update the version for Wix. Hence, we should + ## not hard code version numbers. + $wixToolsetBinPath = "${env:ProgramFiles(x86)}\WiX Toolset *\bin" + + Write-Verbose "Ensure Wix Toolset is present on the machine @ $wixToolsetBinPath" + if (-not (Test-Path $wixToolsetBinPath)) + { + throw "The latest version of Wix Toolset 3.11 is required to create MSI package. Please install it from https://github.com/wixtoolset/wix3/releases" + } + + ## Get the latest if multiple versions exist. + $wixToolsetBinPath = (Get-ChildItem $wixToolsetBinPath).FullName | Sort-Object -Descending | Select-Object -First 1 + + Write-Verbose "Initialize Wix executables - Heat.exe, Candle.exe, Light.exe" + $wixHeatExePath = Join-Path $wixToolsetBinPath "Heat.exe" + $wixCandleExePath = Join-Path $wixToolsetBinPath "Candle.exe" + $wixLightExePath = Join-Path $wixToolsetBinPath "Light.exe" + + $ProductSemanticVersion = Get-PackageSemanticVersion -Version $ProductVersion + $ProductVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $ProductVersion + + $assetsInSourcePath = Join-Path $ProductSourcePath 'assets' + New-Item $assetsInSourcePath -type directory -Force | Write-Verbose + + Write-Verbose "Place dependencies such as icons to $assetsInSourcePath" + Copy-Item "$AssetsPath\*.ico" $assetsInSourcePath -Force + + $productVersionWithName = $ProductName + '_' + $ProductVersion + $productSemanticVersionWithName = $ProductName + '-' + $ProductSemanticVersion + + Write-Verbose "Create MSI for Product $productSemanticVersionWithName" + + [Environment]::SetEnvironmentVariable("ProductSourcePath", $ProductSourcePath, "Process") + # These variables are used by Product.wxs in assets directory + [Environment]::SetEnvironmentVariable("ProductName", $ProductName, "Process") + [Environment]::SetEnvironmentVariable("ProductCode", $ProductCode, "Process") + [Environment]::SetEnvironmentVariable("ProductVersion", $ProductVersion, "Process") + [Environment]::SetEnvironmentVariable("ProductSemanticVersion", $ProductSemanticVersion, "Process") + [Environment]::SetEnvironmentVariable("ProductVersionWithName", $productVersionWithName, "Process") + $ProductProgFilesDir = "ProgramFiles64Folder" + if ($ProductTargetArchitecture -eq "x86") + { + $ProductProgFilesDir = "ProgramFilesFolder" + } + [Environment]::SetEnvironmentVariable("ProductProgFilesDir", $ProductProgFilesDir, "Process") + + $wixFragmentPath = Join-Path $env:Temp "Fragment.wxs" + $wixObjProductPath = Join-Path $env:Temp "Product.wixobj" + $wixObjFragmentPath = Join-Path $env:Temp "Fragment.wixobj" + + $packageName = $productSemanticVersionWithName + if ($ProductNameSuffix) { + $packageName += "-$ProductNameSuffix" + } + $msiLocationPath = Join-Path $pwd "$packageName.msi" + + if(!$Force.IsPresent -and (Test-Path -Path $msiLocationPath)) + { + Write-Error -Message "Package already exists, use -Force to overwrite, path: $msiLocationPath" -ErrorAction Stop + } + + $WiXHeatLog = & $wixHeatExePath dir $ProductSourcePath -dr $productVersionWithName -cg $productVersionWithName -gg -sfrag -srd -scom -sreg -out $wixFragmentPath -var env.ProductSourcePath -v + $WiXCandleLog = & $wixCandleExePath "$ProductWxsPath" "$wixFragmentPath" -out (Join-Path "$env:Temp" "\\") -ext WixUIExtension -ext WixUtilExtension -arch $ProductTargetArchitecture -v + $WiXLightLog = & $wixLightExePath -out $msiLocationPath $wixObjProductPath $wixObjFragmentPath -ext WixUIExtension -ext WixUtilExtension -dWixUILicenseRtf="$LicenseFilePath" -v + + Remove-Item -ErrorAction SilentlyContinue *.wixpdb -Force + Remove-Item -ErrorAction SilentlyContinue $wixFragmentPath -Force + Remove-Item -ErrorAction SilentlyContinue $wixObjProductPath -Force + Remove-Item -ErrorAction SilentlyContinue $wixObjFragmentPath -Force + + if (Test-Path $msiLocationPath) + { + Write-Verbose "You can find the MSI @ $msiLocationPath" -Verbose + $msiLocationPath + } + else + { + $WiXHeatLog | Out-String | Write-Verbose -Verbose + $WiXCandleLog | Out-String | Write-Verbose -Verbose + $WiXLightLog | Out-String | Write-Verbose -Verbose + $errorMessage = "Failed to create $msiLocationPath" + if ($null -ne $env:CI) + { + Add-AppveyorCompilationMessage $errorMessage -Category Error -FileName $MyInvocation.ScriptName -Line $MyInvocation.ScriptLineNumber + } + throw $errorMessage + } +} From 6e06987dd9cd8dfbbeb731136f342e601e71c939 Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Wed, 21 Feb 2018 11:15:25 -0800 Subject: [PATCH 2/3] fix paths --- tools/packaging/packaging.psm1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index 49fb6e4e46c..120ce9ddb67 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -1470,17 +1470,17 @@ function New-MSIPackage # File describing the MSI Package creation semantics [ValidateNotNullOrEmpty()] [ValidateScript( {Test-Path $_})] - [string] $ProductWxsPath = "$PSScriptRoot\assets\Product.wxs", + [string] $ProductWxsPath = "$PSScriptRoot\..\..\assets\Product.wxs", # Path to Assets folder containing artifacts such as icons, images [ValidateNotNullOrEmpty()] [ValidateScript( {Test-Path $_})] - [string] $AssetsPath = "$PSScriptRoot\assets", + [string] $AssetsPath = "$PSScriptRoot\..\..\assets", # Path to license.rtf file - for the EULA [ValidateNotNullOrEmpty()] [ValidateScript( {Test-Path $_})] - [string] $LicenseFilePath = "$PSScriptRoot\assets\license.rtf", + [string] $LicenseFilePath = "$PSScriptRoot\..\..\assets\license.rtf", # Architecture to use when creating the MSI [Parameter(Mandatory = $true)] From 59e0ae6242910fae4cc2fb3529e6f8cd2f641e40 Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Thu, 22 Feb 2018 12:36:22 -0800 Subject: [PATCH 3/3] move Get-PackageVersionAsMajorMinorBuildRevision to packaging.psm1 --- build.psm1 | 36 ---------------------------------- tools/packaging/packaging.psm1 | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/build.psm1 b/build.psm1 index 760df04f07f..af8cecb77d9 100644 --- a/build.psm1 +++ b/build.psm1 @@ -2039,42 +2039,6 @@ function script:Start-NativeExecution([scriptblock]$sb, [switch]$IgnoreExitcode) } } -# Builds coming out of this project can have version number as 'a.b.c' OR 'a.b.c-d-f' -# This function converts the above version into major.minor[.build[.revision]] format -function Get-PackageVersionAsMajorMinorBuildRevision -{ - [CmdletBinding()] - param ( - # Version of the Package - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [string] $Version - ) - - Write-Verbose "Extract the version in the form of major.minor[.build[.revision]] for $Version" - $packageVersionTokens = $Version.Split('-') - $packageVersion = ([regex]::matches($Version, "\d+(\.\d+)+"))[0].value - - if (1 -eq $packageVersionTokens.Count) { - # In case the input is of the form a.b.c, add a '0' at the end for revision field - $packageVersion = $packageVersion + '.0' - } elseif (1 -lt $packageVersionTokens.Count) { - # We have all the four fields - $packageBuildTokens = ([regex]::Matches($packageVersionTokens[1], "\d+"))[0].value - - if ($packageBuildTokens) - { - $packageVersion = $packageVersion + '.' + $packageBuildTokens - } - else - { - $packageVersion = $packageVersion - } - } - - $packageVersion -} - function Start-CrossGen { [CmdletBinding()] param( diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index 120ce9ddb67..885c62e1cba 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -1580,3 +1580,39 @@ function New-MSIPackage throw $errorMessage } } + +# Builds coming out of this project can have version number as 'a.b.c' OR 'a.b.c-d-f' +# This function converts the above version into major.minor[.build[.revision]] format +function Get-PackageVersionAsMajorMinorBuildRevision +{ + [CmdletBinding()] + param ( + # Version of the Package + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $Version + ) + + Write-Verbose "Extract the version in the form of major.minor[.build[.revision]] for $Version" + $packageVersionTokens = $Version.Split('-') + $packageVersion = ([regex]::matches($Version, "\d+(\.\d+)+"))[0].value + + if (1 -eq $packageVersionTokens.Count) { + # In case the input is of the form a.b.c, add a '0' at the end for revision field + $packageVersion = $packageVersion + '.0' + } elseif (1 -lt $packageVersionTokens.Count) { + # We have all the four fields + $packageBuildTokens = ([regex]::Matches($packageVersionTokens[1], "\d+"))[0].value + + if ($packageBuildTokens) + { + $packageVersion = $packageVersion + '.' + $packageBuildTokens + } + else + { + $packageVersion = $packageVersion + } + } + + $packageVersion +}