CMake: Win XP (v141_xp) VS install script

Move the PowerShell code from .github/workflow/cmake-builds.yml into its
own script, cmake/github_v141_xp.ps1, to keep cmake-buils.yml readable.
The script also facilitates synchronizng with the Chocolatey installer's
Wait-VSIstallerProcesses function easier (from which this this code is
derived.)

cmake-builds.yml: Check the output from Get-VSSetupInstance and
Set-VSSetupInstance. Empty (or null) output indicates that the v141_xp
install did not complete successfully. Build process will bail when that
happens.

cmake/v141_xp_install.ps1: Unused and now unnecessary script.
This commit is contained in:
B. Scott Michel 2023-08-17 14:12:05 -07:00 committed by Paul Koning
parent eeebbed273
commit 06d41835fe
4 changed files with 166 additions and 182 deletions

View file

@ -127,101 +127,8 @@ jobs:
Where-Object { $_ -notlike "*\Strawberry\*" -and $_ -notlike "*/Strawberry/*" }) -join ';'
$env:Path = $fixPATH
#+
# Update the existing Github Visual Studio installation in-place. `vswhere` may find multiple
# VS installations, so iterate through them all.
#
# This is Grey Magic. `vs_installer` exits almost immediately if you run it from the command
# line. However, `vs_installer`'s subprocesses are well known and we look for them and wait
# for them to terminate.
#
# GH Actions does something strange with stdout and stderr, so you won't get any
# indication of failure or output that shows you that something is happening.
#
# The waiting code was adapted from the Chocolatey VS installer scripts.
#-
$vswhere = "${env:ProgramFiles} (x86)\Microsoft Visual Studio\Installer\vswhere"
$vsinstaller = "${env:ProgramFiles} (x86)\Microsoft Visual Studio\Installer\vs_installer.exe"
$vsInstallOut = "$env:TEMP\vsinstall-out.txt"
$vsInstallErr = "$env:TEMP\vsinstall-err.txt"
& ${vswhere} -property installationPath | `
Foreach-Object -process {
## --quiet: Don't open/show UI
## --force: Terminate any VS instances forcibly
## --norestart: Delay reboot after install, if needed
## --installWhileDownloading: Self-explanitory.
$Params = @(
"modify",
"--installPath", "$_",
"--add", "Microsoft.VisualStudio.Component.VC.v141.x86.x64",
"--add", "Microsoft.VisualStudio.Component.WinXP",
"--quiet", "--force", "--norestart", "--installWhileDownloading"
)
& $vsInstaller $Params 2> $vsInstallErr > $vsInstallOut
$vsinstallerProcesses = @('vs_installer', 'vs_installershell', 'vs_installerservice')
$vsInstallerStartup = $true
$vsInstallerStartCount = 10
do
{
Write-Debug ('Looking for running VS installer processes')
$vsInstallerRemaining = Get-Process -Name $vsinstallerProcesses -ErrorAction SilentlyContinue | Where-Object { $null -ne $_ -and -not $_.HasExited }
$vsInstallerProcessCount = ($vsInstallerRemaining | Measure-Object).Count
if ($vsInstallerProcessCount -gt 0)
{
## Installer processes are present, so obviously not starting up.
$vsInstallerStartup = $false
try
{
Write-Debug "Found $vsInstallerProcessCount running Visual Studio installer processes which are known to exit asynchronously:"
$vsInstallerRemaining | Sort-Object -Property Name, Id | ForEach-Object { '[{0}] {1}' -f $_.Id, $_.Name } | Write-Debug
Write-Debug ('Giving the processes some time to exit')
$vsInstallerRemaining | Wait-Process -Timeout 45 -ErrorAction SilentlyContinue
}
finally
{
$vsInstallerRemaining | ForEach-Object { $_.Dispose() }
$vsInstallerRemaining = $null
}
} else {
if ($vsInstallerStartup) {
if ($vsInstallerStartCount -gt 0) {
Write-Debug "No VS installer processes detected; sleeping with $vsInstallerStartCount tries remaining."
Start-Sleep -Seconds 10.0
$vsInstallerStartCount -= 1
} else {
$vsInstallerStartup = $false
Write-Debug "VS installer never started? Exiting."
Exit 99
}
}
}
}
while (($vsInstallerStartup -and $vsInstallerStartCount -gt 0) -or $vsInstallerProcessCount -gt 0)
}
if ((Test-Path $vsInstallOut -PathType Leaf) -and (Get-Item $vsInstallOut).length -gt 0kb)
{
Write-Output "-- vsinstaller output:"
Get-Content $vsInstallOut
}
else
{
Write-Debug "-- No vsinstaller output."
}
if ((Test-Path $vsInstallErr -PathType Leaf) -and (Get-Item $vsInstallErr).length -gt 0kb)
{
Write-Output "-- vsinstaller error output:"
Get-Content $vsInstallErr
}
else
{
Write-Debug "-- No vsinstaller error/diag output."
}
## Install the XP toolkit, aka v141_xp. This script is specific to the Github environment.
./cmake/github_v141_xp.ps1
#+
# The GH Windows runner image documentation says that the VSSetup module is installed, from
@ -229,7 +136,15 @@ jobs:
# paranoia, ensuring that we really, truly and honestly have WinXP support.
#-
Write-Debug "Get-VSSetupInstance/Select-VSSetupInstance"
Get-VSSetupInstance -All | Select-VSSetupInstance -Require 'Microsoft.VisualStudio.Component.WinXP' -Latest
$instances=$(Get-VSSetupInstance -All | Select-VSSetupInstance -Require 'Microsoft.VisualStudio.Component.WinXP' -Latest)
if ($null -eq $instances)
{
throw "v141_xp didn't install correctly or incomplete install."
}
else
{
$instances | Write-Output
}
## Don't use LTO for XP. XP compatibility comes from VS2017 -- MS is
## at VS2022. There are likely legacy bugs that have been fixed.

View file

@ -130,6 +130,8 @@ open-simh This is CMAKE_SOURCE_DIR
| | CMakeLists.txt from the makefile
| +-- git-commit-id.cmake CMake script to update .git-commit-id and
| | .git-commit-id.h
| +-- github_v141_xp.ps1 Visual Studio "XP toolkit" installer PowerShell
| | script
| +-- installer-customizations Installer-specific customization files
| +-- os-features.cmake Operating system feature probes, e.g., -lm
| +-- patches Patches applied to external dependency libs
@ -142,8 +144,6 @@ open-simh This is CMAKE_SOURCE_DIR
| | CPack components (simulator "families")
| +-- simh-simulators.cmake Simulator add_subdirectory includes, variable
| | definitions
| +-- v141_xp_install.ps1 Experimental Powershell script to install XP
| | compatibility support in Visual Studio (unused)
| +-- vcpkg-setup.cmake vcpkg package manager setup code
```

153
cmake/github_v141_xp.ps1 Normal file
View file

@ -0,0 +1,153 @@
<#
.SYNOPSIS
Install Visual Studio's 'v141_xp' XP toolkit on Github.
.DESCRIPTION
Update the existing Github Visual Studio installation in-place. This script
will iterate through all VS installations identified by the `vswhere` utility.
This script is Grey Magic. The `vs_installer` installer utility exits almost
immediately if you run it from the command line. `vs_installer`'s subprocesses
are reasonably well known, which allows this script to query the processes and
wait for them to terminate.
GitHub Actions does something strange with stdout and stderr, so you won't get any
indication of failure or output that shows you that something is happening.
The waiting code was adapted from the Chocolatey VS installer scripts (Wait-VSIstallerProcesses).
Ref: https://github.com/jberezanski/ChocolateyPackages/blob/master/chocolatey-visualstudio.extension/extensions/Wait-VSInstallerProcesses.ps1
#>
$exitcode = $null
$vswhere = "${env:ProgramFiles} (x86)\Microsoft Visual Studio\Installer\vswhere"
$vsinstaller = "${env:ProgramFiles} (x86)\Microsoft Visual Studio\Installer\vs_installer.exe"
$vsInstallOut = "$env:TEMP\vsinstall-out.txt"
$vsInstallErr = "$env:TEMP\vsinstall-err.txt"
& ${vswhere} -property installationPath | Foreach-Object -process {
# Save the installlation path for the current iteration
$installPath = $_
# Make sure that previously running installers have all exited.
Write-Debug ('Looking for previously running VS installer processes')
$lazyQuitterProcessNames = @('vs_installershell', 'vs_installerservice')
do
{
$lazyQuitterProcesses = Get-Process -Name $lazyQuitterProcessNames -ErrorAction SilentlyContinue | `
Where-Object { $null -ne $_ -and -not $_.HasExited }
$lazyQuitterProcessCount = ($lazyQuitterProcesses | Measure-Object).Count
if ($lazyQuitterProcessCount -gt 0)
{
try
{
$lazyQuitterProcesses | Sort-Object -Property Name, Id | ForEach-Object { '[{0}] {1}' -f $_.Id, $_.Name } | Write-Debug
$lazyQuitterProcesses | Wait-Process -Timeout 10 -ErrorAction SilentlyContinue
}
finally
{
$lazyQuitterProcesses | ForEach-Object { $_.Dispose() }
$lazyQuitterProcesses = $null
}
}
}
while ($lazyQuitterProcessCount -gt 0)
## Now kick off our install:
##
## --quiet: Don't open/show UI
## --force: Terminate any VS instances forcibly
## --norestart: Delay reboot after install, if needed
## --installWhileDownloading: Self-explanitory.
##
## Note: "--wait" doesn't.
$vsinstallParams = @(
"modify",
"--installPath", "$installPath",
"--add", "Microsoft.VisualStudio.Component.VC.v141.x86.x64",
"--add", "Microsoft.VisualStudio.Component.WinXP",
"--quiet", "--force", "--norestart", "--installWhileDownloading"
)
& $vsInstaller $vsinstallParams 2> $vsInstallErr > $vsInstallOut
## VS installer processes for which we want to wait because installation isn't complete. Yet.
$vsinstallerProcesses = @( 'vs_bootstrapper', 'vs_setup_bootstrapper', 'vs_installer', 'vs_installershell', `
'vs_installerservice', 'setup')
$vsInstallerProcessFilter = { $_.Name -ne 'setup' -or $_.Path -like '*\Microsoft Visual Studio\Installer*\setup.exe' }
do
{
Write-Debug ('Looking for running VS installer processes')
$vsInstallerRemaining = Get-Process -Name $vsinstallerProcesses -ErrorAction SilentlyContinue | `
Where-Object { $null -ne $_ -and -not $_.HasExited } | `
Where-Object $vsInstallerProcessFilter
$vsInstallerProcessCount = ($vsInstallerRemaining | Measure-Object).Count
if ($vsInstallerProcessCount -gt 0)
{
try
{
Write-Debug "Found $vsInstallerProcessCount running Visual Studio installer processes:"
$vsInstallerRemaining | Sort-Object -Property Name, Id | ForEach-Object { '[{0}] {1}' -f $_.Id, $_.Name } | Write-Debug
foreach ($p in $vsInstallerProcesses)
{
[void] $p.Handle # make sure we get the exit code http://stackoverflow.com/a/23797762/266876
}
Write-Debug ('Waiting 60 seconds for process(es) to exit...')
$vsInstallerRemaining | Wait-Process -Timeout 60 -ErrorAction SilentlyContinue
foreach ($proc in $vsInstallerProcesses)
{
if (-not $proc.HasExited)
{
continue
}
if ($null -eq $exitCode)
{
$exitCode = $proc.ExitCode
}
if ($proc.ExitCode -ne 0 -and $null -ne $proc.ExitCode)
{
Write-Debug "$($proc.Name) process $($proc.Id) exited with code $($proc.ExitCode)"
if ($exitCode -eq 0)
{
$exitCode = $proc.ExitCode
}
}
}
}
finally
{
$vsInstallerRemaining | ForEach-Object { $_.Dispose() }
$vsInstallerRemaining = $null
}
}
}
while (($vsInstallerStartup -and $vsInstallerStartCount -gt 0) -or $vsInstallerProcessCount -gt 0)
}
if ((Test-Path $vsInstallOut -PathType Leaf) -and (Get-Item $vsInstallOut).length -gt 0kb)
{
Write-Output "-- vsinstaller output:"
Get-Content $vsInstallOut
}
else
{
Write-Debug "-- No vsinstaller output."
}
if ((Test-Path $vsInstallErr -PathType Leaf) -and (Get-Item $vsInstallErr).length -gt 0kb)
{
Write-Output "-- vsinstaller error output:"
Get-Content $vsInstallErr
}
else
{
Write-Debug "-- No vsinstaller error/diag output."
}
if ($null -ne $exitcode -and $exitcode -ne 0)
{
throw "VS installer exited with non-zero exit status: $exitcode"
}

View file

@ -1,84 +0,0 @@
$vsFlavor=$args[0]
$vsSetupDir="C:\Program Files (x86)\Microsoft Visual Studio\installer"
$vswhere="${vsSetupDir}\vswhere.exe"
$vsinstaller="${vsSetupDir}\vs_installer.exe"
$vstudios = @{
"vs2017" = @{
names = @{
"Visual Studio Enterprise 2019" = "Microsoft.VisualStudio.Product.Enterprise"
"Visual Studio Professional 2019" = "Microsoft.VisualStudio.Product.Professional"
"Visual Studio Community 2019" = "Microsoft.VisualStudio.Product.Community"
}
channelId = "VisualStudio.15.Release"
v141toolkit = @( "Microsoft.VisualStudio.Component.WinXP" )
}
"vs2019" = @{
names = @{
"Visual Studio Enterprise 2019" = "Microsoft.VisualStudio.Product.Enterprise"
"Visual Studio Professional 2019" = "Microsoft.VisualStudio.Product.Professional"
"Visual Studio Community 2019" = "Microsoft.VisualStudio.Product.Community"
}
displayName = "Visual Studio Community 2019"
channelId = "VisualStudio.16.Release"
v141toolkit = @( "Microsoft.VisualStudio.Component.VC.v141.x86.x64", "Microsoft.VisualStudio.Component.WinXP" )
}
"vs2022" = @{
names = @{
"Visual Studio Enterprise 2022" = "Microsoft.VisualStudio.Product.Enterprise"
"Visual Studio Professional 2022" = "Microsoft.VisualStudio.Product.Professional"
"Visual Studio Community 2022" = "Microsoft.VisualStudio.Product.Community"
}
installedChannelId = "VisualStudio.17.Release"
v141toolkit = @( "Microsoft.VisualStudio.Component.VC.v141.x86.x64", "Microsoft.VisualStudio.Component.WinXP" )
}
}
if ($args.length -eq 0) {
"Womabt!!"
exit 1
}
$wantedVS = $vstudios[$args[0]]
if ($wantedVS -eq $null) {
"Wibbles."
exit 1
}
Set-PSDebug -Trace 1
if (Test-Path -Path $vsinstaller) {
if (Test-Path -Path $vswhere) {
$vsinfo=$(& $vswhere -format json | ConvertFrom-JSON)
foreach ($vs in $vsinfo) {
$productId = $wantedVS.names[$vs.displayName]
if ($productId -ne $null) {
Write-Output $("Found: " + $vs.displayName)
$args = @( "modify", "--quiet")
$args += @( "--channelId", $wantedVS.installedChannelId )
$args += @( "--productId", $productId )
foreach ($c in $wantedVS.v141toolkit) {
$args += @( "--add", $c )
}
Write-Output $( ( @("Executing: ", $vsinstaller) + $args ) -join " " )
$proc = Start-Process -Verbose -NoNewWindow -PassThru $vsinstaller -ArgumentList $args
$proc.WaitForExit()
$proc = Start-Process -NoNewWindow -PassThru $vsinstaller -ArgumentList @("export", "--channelId", $wantedVS.installedChannelId, "--productId", $productId, "--config", "vsinstall.after", "--quiet")
$proc.WaitForExit()
if (Test-Path -Path .\vsinstall.after) {
Get-Content .\vsinstall.after
}
}
}
} else {
Write-Ouput @("vswhere not found or available. ", $vswhere) -join " "
}
} else {
Write-Ouput @("VS installer not found or available. ", $vsinstaller) -join " "
}