Skip to content

Commit

Permalink
CMake: Win XP (v141_xp) VS install script
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bscottm authored and pkoning2 committed Oct 24, 2023
1 parent eeebbed commit 06d4183
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 182 deletions.
107 changes: 11 additions & 96 deletions .github/workflows/cmake-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,109 +127,24 @@ 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
# whence Get-VSSetupInstance and Select-VSSetupInstance are imported. This step is pure
# 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.
Expand Down
4 changes: 2 additions & 2 deletions cmake/CMake-Maintainers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
```

Expand Down
153 changes: 153 additions & 0 deletions cmake/github_v141_xp.ps1
Original file line number Diff line number Diff line change
@@ -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"
}
84 changes: 0 additions & 84 deletions cmake/v141_xp_install.ps1

This file was deleted.

0 comments on commit 06d4183

Please sign in to comment.