| # Copyright 2019 The Bazel Authors. All rights reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| # Set path constants. These are relative to the Bazel source tree root. |
| $Icon = 'site\images\favicon.ico' |
| $ArtworkBig = 'scripts\packages\msi\dialog.bmp' |
| $ArtworkSmall = 'scripts\packages\msi\banner.bmp' |
| $Licence = 'scripts\packages\msi\license.rtf' |
| $Guids = 'scripts\packages\msi\guids.txt' |
| $Wxs = 'scripts\packages\msi\bazelmsi.wxs' |
| |
| # Logs a message to stdout. |
| function Log-Info { |
| param ( |
| [string]$msg |
| ) |
| $basename = $PSCommandPath.Substring($PSCommandPath.LastIndexOfAny('/\') + 1) |
| $time = (Get-Date).ToString('HH:mm:ss') |
| Write-Host "INFO[$basename $time] $msg" |
| } |
| |
| function Replace-Slashes { |
| param ( |
| [string]$s |
| ) |
| return $s.Replace('/', '\') |
| } |
| |
| # Computes the release name from the 'BazelExe'. |
| # 'BazelExe' must already have been validated to match this regex. |
| # 'ReleaseName' is like "0.28.0rc5" |
| # 'Version' is the SemVer part of 'ReleaseName', e.g. "0.28.0" |
| function Compute-RelaseNameAndVersion { |
| param ( |
| [Parameter(Mandatory=$true)][string]$BazelExe |
| ) |
| |
| $rel = [regex]::Match($BazelExe, "bazel-([^-]+)-windows.*\.exe$").captures.groups[1].value |
| $ver = [regex]::Match($rel, "^([0-9]+\.[0-9]+\.[0-9]+)(rc[0-9]+)?$").captures.groups[1].value |
| return $rel, $ver |
| } |
| |
| # Generates a new GUID, prints it as uppercase. |
| # The WiX Toolkit expects uppercase GUIDs in the .wxs file. |
| function Generate-Guid { |
| return [guid]::NewGuid().ToString().ToUpper() |
| } |
| |
| # Returns the UpgradeGuid for this release. |
| function Get-UpgradeGuid { |
| param ( |
| [Parameter(Mandatory=$true)][string]$release_name |
| ) |
| |
| $d = @{} |
| $result = $null |
| foreach ($line in Get-Content -Path $Guids) { |
| $line = $line.Split('#')[0] |
| if ($line) { |
| $k, $v = $line.Split(' ', 2) |
| # Ensure all version prefixes in the file are unique. |
| if ($d.ContainsKey($k)) { |
| throw "Duplicate relase prefix $k in $Guids" |
| } |
| else { |
| $d[$k] = $null |
| } |
| if (! $v) { |
| throw "Null key '$v' in line '$line'" |
| } |
| # Ensure all GUIDs in the file are unique. We can use the same |
| # hashtable because the value domains are distinct. |
| if ($d.ContainsKey($v)) { |
| throw "Duplicate GUID $v in $Guids" |
| } |
| else { |
| $d[$v] = $null |
| } |
| if (! $result -and $release_name.StartsWith($k)) { |
| $result = $v |
| # Do not return yet, so we check that all GUIDs are unique. |
| } |
| } |
| } |
| if ($result) { |
| return $result |
| } |
| else { |
| throw "UpgradeGuid for $release_name not found in $Guids" |
| } |
| } |
| |
| # Returns the Bazel version (as a SemVer string) from the release name. |
| function Get-BazelVersion { |
| if ($ReleaseName -match "rc[0-9]+$") { |
| return $ReleaseName.Substring(0, $ReleaseName.LastIndexOf('rc')) |
| } |
| else { |
| return $ReleaseName |
| } |
| } |
| |
| # Downloads and extracts the WiX Toolkit. |
| # Returns the path where the tools are (e.g. "candle.exe"). |
| function Download-Wix { |
| # Use TLS1.2 for HTTPS (fixes an issue where later steps can't connect to github.com). |
| # See https://github.com/bazelbuild/continuous-integration/blob/master/buildkite/setup-windows.ps1 |
| [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 |
| |
| $wix_dir = $(New-Item -Path "${WorkDir}\_wix" -ItemType Directory -Force).FullName |
| $zip_file = "$wix_dir\wix311.zip" |
| (New-Object Net.WebClient).DownloadFile( |
| 'https://github.com/wixtoolset/wix3/releases/download/wix3111rtm/wix311-binaries.zip', |
| $zip_file) |
| |
| $actual_sha = (Get-FileHash -Path $zip_file -Algorithm SHA256).Hash.ToString() |
| $expected_sha = '37F0A533B0978A454EFB5DC3BD3598BECF9660AAF4287E55BF68CA6B527D051D' |
| if ($actual_sha -ne $expected_sha) { |
| throw "Bad checksum: wix311-binaries.zip SHA256 is $actual_sha, expected $expected_sha" |
| } |
| |
| Expand-Archive -Path $zip_file -DestinationPath $wix_dir -Force |
| |
| return $wix_dir |
| } |
| |
| # Creates the .wixobj file using candle.exe (the "compiler"). |
| function Run-Candle { |
| param ( |
| [Parameter(Mandatory=$true)][string]$wix_root |
| ) |
| |
| $out = "${WorkDir}\bazelmsi.wixobj" |
| |
| $output = & "${wix_root}\candle.exe" ` |
| -nologo ` |
| -arch x64 ` |
| "-dBAZEL_EXE=$BazelExe" ` |
| "-dICON=$Icon" ` |
| "-dUPGRADE_GUID=$(Get-UpgradeGuid $ReleaseName)" ` |
| "-dRELEASE_NAME=$ReleaseName" ` |
| "-dVERSION=$(Get-BazelVersion)" ` |
| "-dRANDOM_GUID_1=$(Generate-Guid)" ` |
| "-dRANDOM_GUID_2=$(Generate-Guid)" ` |
| -o $out ` |
| $Wxs |
| if (! $?) { |
| throw $output |
| } |
| return $out |
| } |
| |
| # Creates the .msi file using light.exe (the "linker"). |
| function Run-Light { |
| param ( |
| [Parameter(Mandatory=$true)][string]$wix_root, |
| [Parameter(Mandatory=$true)][string]$wixobj |
| ) |
| |
| $output = & "${wix_root}\light.exe" ` |
| -nologo ` |
| -ext WixUIExtension ` |
| '-cultures:en-us' ` |
| "-dWixUILicenseRtf=$Licence" ` |
| "-dWixUIDialogBmp=$ArtworkBig" ` |
| "-dWixUIBannerBmp=$ArtworkSmall" ` |
| -o $OutMsi ` |
| $wixobj |
| if (! $?) { |
| throw $output |
| } |
| } |
| |
| function Make-Msi { |
| param ( |
| [Parameter(Mandatory=$true)] |
| [ValidatePattern("bazel-[0-9]+\.[0-9]+\.[0-9]+(rc[1-9]|rc[1-9][0-9]+)?-windows-x86_64.exe$")] |
| [string] |
| $BazelExe, |
| |
| [Parameter(Mandatory=$true)][string]$WorkDir, |
| [Parameter(Mandatory=$true)][string]$OutMsi |
| ) |
| |
| $ReleaseName, $Version = Compute-RelaseNameAndVersion $BazelExe |
| |
| Log-Info 'Downloading WiX Toolkit' |
| $wix_root = Download-Wix |
| |
| Log-Info 'Creating wixobj' |
| $wixobj = Run-Candle -wix_root $wix_root |
| |
| Log-Info 'Creating msi' |
| Run-Light -wix_root $wix_root -wixobj $wixobj |
| |
| Log-Info "Done: $OutMsi" |
| } |