diff --git a/images/windows/scripts/build/Configure-BaseImage.ps1 b/images/windows/scripts/build/Configure-BaseImage.ps1 index b1b963eb5a..78be1b5885 100644 --- a/images/windows/scripts/build/Configure-BaseImage.ps1 +++ b/images/windows/scripts/build/Configure-BaseImage.ps1 @@ -44,7 +44,7 @@ function Disable-WindowsUpdate { Add-Content -Path $profile.AllUsersAllHosts -Value '$ErrorActionPreference="Stop"' Write-Host "Disable Server Manager on Logon" -Get-ScheduledTask -TaskName ServerManager | Disable-ScheduledTask +Get-ScheduledTask -TaskName ServerManager -ErrorAction SilentlyContinue | Disable-ScheduledTask Write-Host "Disable 'Allow your PC to be discoverable by other PCs' popup" New-Item -Path HKLM:\System\CurrentControlSet\Control\Network -Name NewNetworkWindowOff -Force diff --git a/images/windows/scripts/build/Configure-ImageDataFile.ps1 b/images/windows/scripts/build/Configure-ImageDataFile.ps1 index d0b73effa6..6a7af26f8a 100644 --- a/images/windows/scripts/build/Configure-ImageDataFile.ps1 +++ b/images/windows/scripts/build/Configure-ImageDataFile.ps1 @@ -15,20 +15,28 @@ $imageMinorVersion = $imageVersionComponents[1] $imageDataFile = $env:IMAGEDATA_FILE $githubUrl = "https://github.com/actions/runner-images/blob" -if ((Test-IsWin25) -and $env:INSTALL_VS_2026) { +if ((Test-IsWin25-X64) -and $env:INSTALL_VS_2026) { $imageLabel = "windows-2025-vs2026" $softwareUrl = "${githubUrl}/win25-vs2026/$imageMajorVersion.$imageMinorVersion/images/windows/Windows2025-VS2026-Readme.md" $releaseUrl = "https://github.com/actions/runner-images/releases/tag/win25-vs2026%2F$imageMajorVersion.$imageMinorVersion" -} elseif (Test-IsWin25) { +} elseif (Test-IsWin25-X64) { $imageLabel = "windows-2025" $softwareUrl = "${githubUrl}/win25/$imageMajorVersion.$imageMinorVersion/images/windows/Windows2025-Readme.md" $releaseUrl = "https://github.com/actions/runner-images/releases/tag/win25%2F$imageMajorVersion.$imageMinorVersion" -} elseif (Test-IsWin22) { +} elseif (Test-IsWin22-X64) { $imageLabel = "windows-2022" $softwareUrl = "${githubUrl}/win22/$imageMajorVersion.$imageMinorVersion/images/windows/Windows2022-Readme.md" $releaseUrl = "https://github.com/actions/runner-images/releases/tag/win22%2F$imageMajorVersion.$imageMinorVersion" +} elseif ((Test-IsWin11-Arm64) -and $env:INSTALL_VS_2026) { + $imageLabel = "windows-11-vs2026-arm64" + $softwareUrl = "${githubUrl}/win11-vs2026-arm64/$imageMajorVersion.$imageMinorVersion/images/windows/Windows11-VS2026-Arm64-Readme.md" + $releaseUrl = "https://github.com/actions/runner-images/releases/tag/win11-vs2026-arm64%2F$imageMajorVersion.$imageMinorVersion" +} elseif (Test-IsWin11-Arm64) { + $imageLabel = "windows-11-arm64" + $softwareUrl = "${githubUrl}/win11-arm64/$imageMajorVersion.$imageMinorVersion/images/windows/Windows11-Arm64-Readme.md" + $releaseUrl = "https://github.com/actions/runner-images/releases/tag/win11-arm64%2F$imageMajorVersion.$imageMinorVersion" } else { - throw "Invalid platform version is found. Either Windows Server 2022 or 2025 are required" + throw "Invalid platform version is found. Either Windows Server 2022, 2025 or Windows 11 are required" } $json = @" diff --git a/images/windows/scripts/build/Configure-Shell.ps1 b/images/windows/scripts/build/Configure-Shell.ps1 index f9ac961557..3f4d6f0733 100644 --- a/images/windows/scripts/build/Configure-Shell.ps1 +++ b/images/windows/scripts/build/Configure-Shell.ps1 @@ -2,7 +2,8 @@ $shellPath = "C:\shells" New-Item -Path $shellPath -ItemType Directory | Out-Null -# add a wrapper for C:\msys64\usr\bin\bash.exe +if (Test-IsX64) { + # add a wrapper for C:\msys64\usr\bin\bash.exe @' @echo off setlocal @@ -11,6 +12,7 @@ IF NOT DEFINED MSYSTEM set MSYSTEM=mingw64 set CHERE_INVOKING=1 C:\msys64\usr\bin\bash.exe -leo pipefail %* '@ | Out-File -FilePath "$shellPath\msys2bash.cmd" -Encoding ascii +} # gitbash <--> C:\Program Files\Git\bin\bash.exe New-Item -ItemType SymbolicLink -Path "$shellPath\gitbash.exe" -Target "$env:ProgramFiles\Git\bin\bash.exe" | Out-Null diff --git a/images/windows/scripts/build/Configure-System.ps1 b/images/windows/scripts/build/Configure-System.ps1 index dee40ab611..2f10b8a3b3 100644 --- a/images/windows/scripts/build/Configure-System.ps1 +++ b/images/windows/scripts/build/Configure-System.ps1 @@ -6,7 +6,7 @@ # Set default version to 1 for WSL (aka LXSS - Linux Subsystem) # The value should be set in the default user registry hive # https://github.com/actions/runner-images/issues/5760 -if (Test-IsWin22) { +if (Test-IsWin22-X64) { Write-Host "Setting WSL default version to 1" Mount-RegistryHive ` @@ -37,7 +37,7 @@ if ($LASTEXITCODE -ne 0) { } # Enable inheritance for the entire C:\ drive -if (Test-IsWin25) { +if (Test-IsWin25-X64) { cmd /c "icacls C:\ /inheritance:e /c /q 2>&1" | Out-Null if ($LASTEXITCODE -ne 0) { throw "Failed to enable inheritance for C:\ drive" @@ -101,11 +101,11 @@ $servicesToDisable = @( 'wuauserv' 'DiagTrack' 'dmwappushservice' - $(if(-not (Test-IsWin25)){'PcaSvc'}) + $(if(-not (Test-IsWin25-X64)){'PcaSvc'}) 'SysMain' 'gupdate' 'gupdatem' - $(if(-not (Test-IsWin25)){'StorSvc'}) + $(if(-not (Test-IsWin25-X64)){'StorSvc'}) ) | Get-Service -ErrorAction SilentlyContinue Stop-Service $servicesToDisable $servicesToDisable.WaitForStatus('Stopped', "00:01:00") diff --git a/images/windows/scripts/build/Configure-Toolset.ps1 b/images/windows/scripts/build/Configure-Toolset.ps1 index de8da36f0a..880f177e27 100644 --- a/images/windows/scripts/build/Configure-Toolset.ps1 +++ b/images/windows/scripts/build/Configure-Toolset.ps1 @@ -4,6 +4,12 @@ ## Desc: Configure Toolset ################################################################################ +if ( Test-IsArm64 ) { + $envVarTemplate = "GOROOT_{0}_{1}_AARCH64" +} else { + $envVarTemplate = "GOROOT_{0}_{1}_X64" +} + $toolEnvConfigs = @{ Python = @{ pathTemplates = @( @@ -15,7 +21,7 @@ $toolEnvConfigs = @{ pathTemplates = @( "{0}\bin" ) - envVarTemplate = "GOROOT_{0}_{1}_X64" + envVarTemplate = $envVarTemplate } } diff --git a/images/windows/scripts/build/Configure-User.ps1 b/images/windows/scripts/build/Configure-User.ps1 index 6ede0d8cc6..9965e7e075 100644 --- a/images/windows/scripts/build/Configure-User.ps1 +++ b/images/windows/scripts/build/Configure-User.ps1 @@ -27,8 +27,8 @@ if ($LASTEXITCODE -ne 0) { throw "Failed to copy HKCU\Software\Microsoft\VisualStudio to HKLM\DEFAULT\Software\Microsoft\VisualStudio" } -# TortoiseSVN not installed on Windows 2025 image due to Sysprep issues -if (-not (Test-IsWin25)) { +# TortoiseSVN not installed on Windows 2025 and Windows 11 due to Sysprep issues +if (Test-IsWin22-X64) { # disable TSVNCache.exe $registryKeyPath = 'HKCU:\Software\TortoiseSVN' if (-not(Test-Path -Path $registryKeyPath)) { @@ -42,7 +42,7 @@ if (-not (Test-IsWin25)) { } } # Accept by default "Send Diagnostic data to Microsoft" consent. -if (Test-IsWin25) { +if (Test-IsWin25-X64) { $registryKeyPath = 'HKLM:\DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Privacy' New-ItemProperty -Path $registryKeyPath -Name PrivacyConsentPresentationVersion -PropertyType DWORD -Value 3 | Out-Null New-ItemProperty -Path $registryKeyPath -Name PrivacyConsentSettingsValidMask -PropertyType DWORD -Value 4 | Out-Null @@ -52,7 +52,7 @@ if (Test-IsWin25) { Dismount-RegistryHive "HKLM\DEFAULT" # Remove the "installer" (var.install_user) user profile for Windows 2025 image -if (Test-IsWin25) { +if (Test-IsWin25-X64) { Get-CimInstance -ClassName Win32_UserProfile | where-object {$_.LocalPath -match $env:INSTALL_USER} | Remove-CimInstance -Confirm:$false & net user $env:INSTALL_USER /DELETE } diff --git a/images/windows/scripts/build/Install-Apache.ps1 b/images/windows/scripts/build/Install-Apache.ps1 index d5e85a6bc2..f36caeaf20 100644 --- a/images/windows/scripts/build/Install-Apache.ps1 +++ b/images/windows/scripts/build/Install-Apache.ps1 @@ -4,7 +4,10 @@ ################################################################################ # Stop w3svc service -Stop-Service -Name w3svc +$w3svcService = Get-Service -Name "w3svc" -ErrorAction SilentlyContinue +if ($w3svcService) { + Stop-Service $w3svcService +} # Install latest apache in chocolatey $installDir = "C:\tools" @@ -15,7 +18,10 @@ Stop-Service -Name Apache Set-Service -Name Apache -StartupType Disabled # Start w3svc service -Start-Service -Name w3svc +$w3svcService = Get-Service -Name "w3svc" -ErrorAction SilentlyContinue +if ($w3svcService) { + Start-Service $w3svcService +} # Invoke Pester Tests Invoke-PesterTests -TestFile "Apache" diff --git a/images/windows/scripts/build/Install-CMake.ps1 b/images/windows/scripts/build/Install-CMake.ps1 new file mode 100644 index 0000000000..3c3b63f4fe --- /dev/null +++ b/images/windows/scripts/build/Install-CMake.ps1 @@ -0,0 +1,31 @@ +################################################################################ +## File: Install-CMake.ps1 +## Desc: Install CMake (ARM64 only; x64 is installed via Choco) +## Supply chain security: CMake - checksum validation +################################################################################ + +# Install CMake +$downloadUrl = Resolve-GithubReleaseAssetUrl ` + -Repo "Kitware/CMake" ` + -Version "latest" ` + -UrlMatchPattern "cmake-*-windows-arm64.msi" + +#region Supply chain security - CMake +$packageName = Split-Path $downloadUrl -Leaf +$checksumsUrl = Resolve-GithubReleaseAssetUrl ` + -Repo "Kitware/CMake" ` + -Version "latest" ` + -UrlMatchPattern "cmake-*-SHA-256.txt" +$externalHash = Get-ChecksumFromUrl -Type "SHA256" ` + -Url $checksumsUrl ` + -FileName $packageName +#endregion + +Install-Binary ` + -Url $downloadUrl ` + -ExtraInstallArgs @("ADD_CMAKE_TO_PATH=System") ` + -ExpectedSHA256Sum $externalHash + +Update-Environment + +Invoke-PesterTests -TestFile "Tools" -TestName "CMake" diff --git a/images/windows/scripts/build/Install-Chrome.ps1 b/images/windows/scripts/build/Install-Chrome.ps1 index f8c98c3fa1..54f5cdb265 100644 --- a/images/windows/scripts/build/Install-Chrome.ps1 +++ b/images/windows/scripts/build/Install-Chrome.ps1 @@ -3,9 +3,15 @@ ## Desc: Install Google Chrome browser and Chrome WebDriver ################################################################################ +if (Test-IsArm64) { + $browserDownloadUrl = "https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise_arm64.msi" +} else { + $browserDownloadUrl = "https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi" +} + # Download and install latest Chrome browser Install-Binary ` - -Url 'https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi' ` + -Url $browserDownloadUrl ` -ExpectedSubject 'CN=Google LLC, O=Google LLC, L=Mountain View, S=California, C=US, SERIALNUMBER=3582691, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, OID.1.3.6.1.4.1.311.60.2.1.3=US' # Prepare firewall rules diff --git a/images/windows/scripts/build/Install-Docker.ps1 b/images/windows/scripts/build/Install-Docker.ps1 index f87e6069de..29aa39e27a 100644 --- a/images/windows/scripts/build/Install-Docker.ps1 +++ b/images/windows/scripts/build/Install-Docker.ps1 @@ -41,7 +41,7 @@ if ($LastExitCode -ne 0) { # https://github.com/Azure/azure-cli/issues/18766 New-Item -ItemType SymbolicLink -Path "C:\Windows\SysWOW64\docker.exe" -Target "C:\Windows\System32\docker.exe" -if (-not (Test-IsWin25)) { +if (-not (Test-IsWin25-X64)) { Write-Host "Download docker images" $dockerImages = (Get-ToolsetContent).docker.images foreach ($dockerImage in $dockerImages) { diff --git a/images/windows/scripts/build/Install-DotnetSDK.ps1 b/images/windows/scripts/build/Install-DotnetSDK.ps1 index 793c6a01c5..8a09887a97 100644 --- a/images/windows/scripts/build/Install-DotnetSDK.ps1 +++ b/images/windows/scripts/build/Install-DotnetSDK.ps1 @@ -82,9 +82,14 @@ function Install-DotnetSDK { # If installation failed, tests will fail anyway #region Supply chain security + if (Test-IsArm64) { + $dotnetArch = "arm64" + } else { + $dotnetArch = "x64" + } $releasesJsonUri = "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/${DotnetVersion}/releases.json" $releasesData = (Invoke-DownloadWithRetry $releasesJsonUri) | Get-Item | Get-Content | ConvertFrom-Json - $distributorFileHash = $releasesData.releases.sdks.Where({ $_.version -eq $SDKVersion }).files.Where({ $_.name -eq 'dotnet-sdk-win-x64.zip' }).hash + $distributorFileHash = $releasesData.releases.sdks.Where({ $_.version -eq $SDKVersion }).files.Where({ $_.name -eq "dotnet-sdk-win-$dotnetArch.zip" }).hash Test-FileChecksum $zipPath -ExpectedSHA512Sum $distributorFileHash #endregion } @@ -97,11 +102,9 @@ $installScriptPath = Invoke-DownloadWithRetry -Url "https://dot.net/v1/dotnet-in # Visual Studio 2022 pre-creates sdk-manifests/8.0.100 folder, causing dotnet-install to skip manifests creation # https://github.com/actions/runner-images/issues/11402 -if ((Test-IsWin22) -or (Test-IsWin25)) { - $sdkManifestPath = "C:\Program Files\dotnet\sdk-manifests\8.0.100" - if (Test-Path $sdkManifestPath) { - Move-Item -Path $sdkManifestPath -Destination $env:TEMP_DIR -ErrorAction Stop - } +$sdkManifestPath = "C:\Program Files\dotnet\sdk-manifests\8.0.100" +if (Test-Path $sdkManifestPath) { + Move-Item -Path $sdkManifestPath -Destination $env:TEMP_DIR -ErrorAction Stop } # Install and warm up dotnet @@ -122,12 +125,10 @@ foreach ($dotnetVersion in $dotnetToolset.versions) { # Replace manifests inside sdk-manifests/8.0.100 folder with ones from Visual Studio # https://github.com/actions/runner-images/issues/11402 -if ((Test-IsWin22) -or (Test-IsWin25)) { - if (Test-Path "${env:TEMP_DIR}\8.0.100") { - Get-ChildItem -Path "${env:TEMP_DIR}\8.0.100" | ForEach-Object { - Remove-Item -Path "$sdkManifestPath\$($_.BaseName)" -Recurse -Force | Out-Null - Move-Item -Path $_.FullName -Destination $sdkManifestPath -Force -ErrorAction Stop - } +if (Test-Path "${env:TEMP_DIR}\8.0.100") { + Get-ChildItem -Path "${env:TEMP_DIR}\8.0.100" | ForEach-Object { + Remove-Item -Path "$sdkManifestPath\$($_.BaseName)" -Recurse -Force | Out-Null + Move-Item -Path $_.FullName -Destination $sdkManifestPath -Force -ErrorAction Stop } } diff --git a/images/windows/scripts/build/Install-EdgeDriver.ps1 b/images/windows/scripts/build/Install-EdgeDriver.ps1 index f410ea688a..31ae98a517 100644 --- a/images/windows/scripts/build/Install-EdgeDriver.ps1 +++ b/images/windows/scripts/build/Install-EdgeDriver.ps1 @@ -3,6 +3,12 @@ ## Desc: Install Edge WebDriver and configure Microsoft Edge ################################################################################ +if (Test-IsArm64) { + $driverArch = "arm64" +} else { + $driverArch = "win64" +} + # Disable Edge auto-updates Rename-Item -Path "C:\Program Files (x86)\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe" -NewName "Disabled_MicrosoftEdgeUpdate.exe" -ErrorAction Stop @@ -20,7 +26,7 @@ $versionInfoFile = Invoke-DownloadWithRetry -Url $versionInfoUrl -Path "$edgeDri $latestVersion = Get-Content -Path $versionInfoFile Write-Host "Download Microsoft Edge WebDriver..." -$downloadUrl = "https://msedgedriver.microsoft.com/$latestVersion/edgedriver_win64.zip" +$downloadUrl = "https://msedgedriver.microsoft.com/$latestVersion/edgedriver_$driverArch.zip" $archivePath = Invoke-DownloadWithRetry $downloadUrl Write-Host "Expand Microsoft Edge WebDriver archive..." diff --git a/images/windows/scripts/build/Install-Firefox.ps1 b/images/windows/scripts/build/Install-Firefox.ps1 index 984588a3b9..ad235da0d0 100644 --- a/images/windows/scripts/build/Install-Firefox.ps1 +++ b/images/windows/scripts/build/Install-Firefox.ps1 @@ -4,17 +4,25 @@ ## Supply chain security: Firefox browser - checksum validation ################################################################################ +if (Test-IsArm64) { + $browserArch = "win64-aarch64" + $driverArch = "win-aarch64" +} else { + $browserArch = "win64" + $driverArch = "win64" +} + # Install and configure Firefox browser Write-Host "Get the latest Firefox version..." $versionsManifest = Invoke-RestMethod "https://product-details.mozilla.org/1.0/firefox_versions.json" Write-Host "Install Firefox browser..." -$installerUrl = "https://download.mozilla.org/?product=firefox-$($versionsManifest.LATEST_FIREFOX_VERSION)&os=win64&lang=en-US" +$installerUrl = "https://download.mozilla.org/?product=firefox-$($versionsManifest.LATEST_FIREFOX_VERSION)&os=$browserArch&lang=en-US" $hashUrl = "https://archive.mozilla.org/pub/firefox/releases/$($versionsManifest.LATEST_FIREFOX_VERSION)/SHA256SUMS" $externalHash = Get-ChecksumFromUrl -Type "SHA256" ` -Url $hashUrl ` - -FileName "win64/en-US/Firefox Setup*exe" + -FileName "$browserArch/en-US/Firefox Setup*exe" Install-Binary -Type EXE ` -Url $installerUrl ` @@ -46,7 +54,7 @@ Write-Host "Download Gecko WebDriver WebDriver..." $geckoDriverDownloadUrl = Resolve-GithubReleaseAssetUrl ` -Repo "mozilla/geckodriver" ` -Version $geckoDriverVersion ` - -UrlMatchPattern "geckodriver-*-win64.zip" + -UrlMatchPattern "geckodriver-*-$driverArch.zip" $geckoDriverArchPath = Invoke-DownloadWithRetry $geckoDriverDownloadUrl Write-Host "Expand Gecko WebDriver archive..." diff --git a/images/windows/scripts/build/Install-Git.ps1 b/images/windows/scripts/build/Install-Git.ps1 index 0e6843d79b..29c63d596a 100644 --- a/images/windows/scripts/build/Install-Git.ps1 +++ b/images/windows/scripts/build/Install-Git.ps1 @@ -4,12 +4,17 @@ ## Supply chain security: Git - checksum validation, Hub CLI - managed by package manager ################################################################################ -# Install the latest version of Git for Windows +if (Test-IsArm64) { + $gitArch = "arm64" +} else { + $gitArch = "64-bit" +} +# Install the latest version of Git for Windows $downloadUrl = Resolve-GithubReleaseAssetUrl ` -Repo "git-for-windows/git" ` -Version "latest" ` - -UrlMatchPattern "Git-*-64-bit.exe" + -UrlMatchPattern "Git-*-$gitArch.exe" $externalHash = Get-ChecksumFromGithubRelease ` -Repo "git-for-windows/git" ` diff --git a/images/windows/scripts/build/Install-GitHub-CLI.ps1 b/images/windows/scripts/build/Install-GitHub-CLI.ps1 index 0d1d80fd58..c5c0dc244e 100644 --- a/images/windows/scripts/build/Install-GitHub-CLI.ps1 +++ b/images/windows/scripts/build/Install-GitHub-CLI.ps1 @@ -4,12 +4,17 @@ ## Supply chain security: GitHub CLI - checksum validation ################################################################################ -Write-Host "Get the latest gh version..." +if (Test-IsArm64) { + $ghArch = "arm64" +} else { + $ghArch = "amd64" +} +Write-Host "Get the latest gh version..." $downloadUrl = Resolve-GithubReleaseAssetUrl ` -Repo "cli/cli" ` -Version "latest" ` - -UrlMatchPattern "gh_*_windows_amd64.msi" + -UrlMatchPattern "gh_*_windows_$ghArch.msi" $checksumsUrl = Resolve-GithubReleaseAssetUrl ` -Repo "cli/cli" ` diff --git a/images/windows/scripts/build/Install-Haskell.ps1 b/images/windows/scripts/build/Install-Haskell.ps1 index 33a958d7b9..9fdd14c3dd 100644 --- a/images/windows/scripts/build/Install-Haskell.ps1 +++ b/images/windows/scripts/build/Install-Haskell.ps1 @@ -30,7 +30,7 @@ Add-MachinePathItem "$cabalDir\bin" Update-Environment # Get 1 or 3 latest versions of GHC depending on the OS version -If (Test-IsWin25) { +If (Test-IsWin25-X64) { $numberOfVersions = 1 } else { $numberOfVersions = 3 diff --git a/images/windows/scripts/build/Install-JavaTools.ps1 b/images/windows/scripts/build/Install-JavaTools.ps1 index 5a29a9a15f..881d813493 100644 --- a/images/windows/scripts/build/Install-JavaTools.ps1 +++ b/images/windows/scripts/build/Install-JavaTools.ps1 @@ -19,8 +19,8 @@ function Set-JavaPath { exit 1 } - Write-Host "Set 'JAVA_HOME_${Version}_X64' environmental variable as $javaPath" - [Environment]::SetEnvironmentVariable("JAVA_HOME_${Version}_X64", $javaPath, "Machine") + Write-Host "Set 'JAVA_HOME_${Version}_$($Architecture.ToUpper())' environmental variable as $javaPath" + [Environment]::SetEnvironmentVariable("JAVA_HOME_${Version}_$($Architecture.ToUpper())", $javaPath, "Machine") if ($Default) { # Clean up any other Java folders from PATH to make sure that they won't conflict with each other @@ -91,6 +91,12 @@ function Install-JavaJDK { New-Item -ItemType File -Path $javaVersionPath -Name "$Architecture.complete" | Out-Null } +if (Test-IsArm64) { + $javaArch = "aarch64" +} else { + $javaArch = "x64" +} + $toolsetJava = (Get-ToolsetContent).java $defaultVersion = $toolsetJava.default $jdkVersionsToInstall = $toolsetJava.versions @@ -98,12 +104,12 @@ $jdkVersionsToInstall = $toolsetJava.versions foreach ($jdkVersionToInstall in $jdkVersionsToInstall) { $isDefaultVersion = $jdkVersionToInstall -eq $defaultVersion - Install-JavaJDK -JDKVersion $jdkVersionToInstall + Install-JavaJDK -JDKVersion $jdkVersionToInstall -Architecture $javaArch if ($isDefaultVersion) { - Set-JavaPath -Version $jdkVersionToInstall -Default + Set-JavaPath -Version $jdkVersionToInstall -Architecture $javaArch -Default } else { - Set-JavaPath -Version $jdkVersionToInstall + Set-JavaPath -Version $jdkVersionToInstall -Architecture $javaArch } } diff --git a/images/windows/scripts/build/Install-LLVM.ps1 b/images/windows/scripts/build/Install-LLVM.ps1 index 41b8aef951..08883dc7c2 100644 --- a/images/windows/scripts/build/Install-LLVM.ps1 +++ b/images/windows/scripts/build/Install-LLVM.ps1 @@ -1,10 +1,36 @@ ################################################################################ ## File: Install-LLVM.ps1 -## Desc: Install the latest stable version of llvm and clang compilers +## Desc: Install the stable version of llvm and clang compilers ################################################################################ $llvmVersion = (Get-ToolsetContent).llvm.version -$latestChocoVersion = Resolve-ChocoPackageVersion -PackageName "llvm" -TargetVersion $llvmVersion -Install-ChocoPackage llvm -ArgumentList '--version', $latestChocoVersion + +if (Test-IsArm64) { + $installDir = "C:\Program Files\LLVM" + + Write-Host "Resolve LLVM $llvmVersion ARM64 download URL" + $downloadUrl = Resolve-GithubReleaseAssetUrl ` + -Repository "llvm/llvm-project" ` + -Version $llvmVersion ` + -UrlMatchPattern "clang*llvm-*-aarch64-pc-windows-msvc.tar.xz" + + Write-Host "Download LLVM $llvmVersion ARM64 archive" + $archivePath = Invoke-DownloadWithRetry $downloadUrl + + Write-Host "Extract LLVM archive" + $tarPath = $archivePath -replace '\.xz$' + Expand-7ZipArchive -Path $archivePath -DestinationPath (Split-Path $archivePath) + Expand-7ZipArchive -Path $tarPath -DestinationPath $env:TEMP_DIR + + Write-Host "Install LLVM to $installDir" + $extractedDir = Get-ChildItem -Path $env:TEMP_DIR -Directory -Filter "clang+llvm-*" | Select-Object -First 1 + Move-Item -Path $extractedDir.FullName -Destination $installDir -Force + + Add-MachinePathItem (Join-Path $installDir "bin") + Update-Environment +} else { + $latestChocoVersion = Resolve-ChocoPackageVersion -PackageName "llvm" -TargetVersion $llvmVersion + Install-ChocoPackage llvm -ArgumentList '--version', $latestChocoVersion +} Invoke-PesterTests -TestFile "LLVM" diff --git a/images/windows/scripts/build/Install-NativeImages.ps1 b/images/windows/scripts/build/Install-NativeImages.ps1 index 214a9577a6..1b2b84ad66 100644 --- a/images/windows/scripts/build/Install-NativeImages.ps1 +++ b/images/windows/scripts/build/Install-NativeImages.ps1 @@ -9,14 +9,16 @@ if ($LASTEXITCODE -ne 0) { throw "Installation of Microsoft.PowerShell.Utility.Activities failed with exit code $LASTEXITCODE" } -Write-Host "NGen: update x64 native images..." -& $env:SystemRoot\Microsoft.NET\Framework64\v4.0.30319\ngen.exe update | Out-Null -if ($LASTEXITCODE -ne 0) { - throw "Update of x64 native images failed with exit code $LASTEXITCODE" -} +if (Test-IsX64) { + Write-Host "NGen: update x64 native images..." + & $env:SystemRoot\Microsoft.NET\Framework64\v4.0.30319\ngen.exe update | Out-Null + if ($LASTEXITCODE -ne 0) { + throw "Update of x64 native images failed with exit code $LASTEXITCODE" + } -Write-Host "NGen: update x86 native images..." -& $env:SystemRoot\Microsoft.NET\Framework\v4.0.30319\ngen.exe update | Out-Null -if ($LASTEXITCODE -ne 0) { - throw "Update of x86 native images failed with exit code $LASTEXITCODE" + Write-Host "NGen: update x86 native images..." + & $env:SystemRoot\Microsoft.NET\Framework\v4.0.30319\ngen.exe update | Out-Null + if ($LASTEXITCODE -ne 0) { + throw "Update of x86 native images failed with exit code $LASTEXITCODE" + } } diff --git a/images/windows/scripts/build/Install-Nginx.ps1 b/images/windows/scripts/build/Install-Nginx.ps1 index 4b6f1bd503..4b790f8a86 100644 --- a/images/windows/scripts/build/Install-Nginx.ps1 +++ b/images/windows/scripts/build/Install-Nginx.ps1 @@ -4,7 +4,10 @@ ################################################################################ # Stop w3svc service -Stop-Service -Name w3svc +$w3svcService = Get-Service -Name "w3svc" -ErrorAction SilentlyContinue +if ($w3svcService) { + Stop-Service $w3svcService +} # Install latest nginx in chocolatey $installDir = "C:\tools" @@ -15,7 +18,10 @@ Stop-Service -Name nginx Set-Service -Name nginx -StartupType Disabled # Start w3svc service -Start-Service -Name w3svc +$w3svcService = Get-Service -Name "w3svc" -ErrorAction SilentlyContinue +if ($w3svcService) { + Start-Service $w3svcService +} # Invoke Pester Tests Invoke-PesterTests -TestFile "Nginx" diff --git a/images/windows/scripts/build/Install-Ninja.ps1 b/images/windows/scripts/build/Install-Ninja.ps1 new file mode 100644 index 0000000000..b8c04e6939 --- /dev/null +++ b/images/windows/scripts/build/Install-Ninja.ps1 @@ -0,0 +1,24 @@ +################################################################################ +## File: Install-Ninja.ps1 +## Desc: Install Ninja build system (ARM64 only; x64 is installed via Choco) +################################################################################ + +$installDir = "C:\Tools\Ninja" + +Write-Host "Resolve Ninja latest ARM64 download URL" +$downloadUrl = Resolve-GithubReleaseAssetUrl ` + -Repository "ninja-build/ninja" ` + -Version "latest" ` + -UrlMatchPattern "ninja-winarm64.zip" + +Write-Host "Download Ninja ARM64 archive" +$zipPath = Invoke-DownloadWithRetry $downloadUrl + +Write-Host "Install Ninja to $installDir" +New-Item -ItemType Directory -Path $installDir -Force | Out-Null +Expand-7ZipArchive -Path $zipPath -DestinationPath $installDir + +Add-MachinePathItem $installDir +Update-Environment + +Invoke-PesterTests -TestFile "Tools" -TestName "Ninja" diff --git a/images/windows/scripts/build/Install-NodeJS.ps1 b/images/windows/scripts/build/Install-NodeJS.ps1 index 1063ba8e9d..d288ba18bd 100644 --- a/images/windows/scripts/build/Install-NodeJS.ps1 +++ b/images/windows/scripts/build/Install-NodeJS.ps1 @@ -7,12 +7,18 @@ $prefixPath = 'C:\npm\prefix' $cachePath = 'C:\npm\cache' +if (Test-IsArm64) { + $nodeArch = "arm64" +} else { + $nodeArch = "x64" +} + New-Item -Path $prefixPath -Force -ItemType Directory New-Item -Path $cachePath -Force -ItemType Directory $defaultVersion = (Get-ToolsetContent).node.default $nodeVersion = (Get-GithubReleasesByVersion -Repo "nodejs/node" -Version "${defaultVersion}").version | Select-Object -First 1 -$downloadUrl = "https://nodejs.org/dist/v${nodeVersion}/node-v${nodeVersion}-x64.msi" +$downloadUrl = "https://nodejs.org/dist/v${nodeVersion}/node-v${nodeVersion}-${nodeArch}.msi" $packageName = Split-Path $downloadUrl -Leaf $externalHash = Get-ChecksumFromUrl -Type "SHA256" ` diff --git a/images/windows/scripts/build/Install-OpenSSL.ps1 b/images/windows/scripts/build/Install-OpenSSL.ps1 index 3717ddc545..21518b01b3 100644 --- a/images/windows/scripts/build/Install-OpenSSL.ps1 +++ b/images/windows/scripts/build/Install-OpenSSL.ps1 @@ -4,7 +4,12 @@ ## Supply chain security: checksum validation ################################################################################ -$arch = 'INTEL' +if (Test-IsArm64) { + $openSSLArch = "ARM" +} else { + $openSSLArch = "INTEL" +} + $bits = '64' $light = $false $installerType = "exe" @@ -22,7 +27,7 @@ $installerHash = $null foreach ($key in $installerNames) { $installer = $installersAvailable.$key - if (($installer.light -eq $light) -and ($installer.arch -eq $arch) -and ($installer.bits -eq $bits) -and ($installer.installer -eq $installerType) -and ($installer.basever -like $version)) { + if (($installer.light -eq $light) -and ($installer.arch -eq $openSSLArch) -and ($installer.bits -eq $bits) -and ($installer.installer -eq $installerType) -and ($installer.basever -like $version)) { $installerUrl = $installer.url $installerHash = $installer.sha512 } diff --git a/images/windows/scripts/build/Install-PowershellCore.ps1 b/images/windows/scripts/build/Install-PowershellCore.ps1 index 68a3bc80ab..921543b05a 100644 --- a/images/windows/scripts/build/Install-PowershellCore.ps1 +++ b/images/windows/scripts/build/Install-PowershellCore.ps1 @@ -6,6 +6,12 @@ $ErrorActionPreference = "Stop" +if (Test-IsArm64) { + $pwshArch = "arm64" +} else { + $pwshArch = "x64" +} + $tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName()) New-Item -ItemType Directory -Path $tempDir -Force -ErrorAction SilentlyContinue | Out-Null try { @@ -18,7 +24,7 @@ try { $releases = $metadata.LTSReleaseTag -replace '^v' foreach ($release in $releases) { if ($release -like "${pwshMajorMinor}*") { - $downloadUrl = "https://github.com/PowerShell/PowerShell/releases/download/v${release}/PowerShell-${release}-win-x64.msi" + $downloadUrl = "https://github.com/PowerShell/PowerShell/releases/download/v${release}/PowerShell-${release}-win-${pwshArch}.msi" break } } diff --git a/images/windows/scripts/build/Install-R.ps1 b/images/windows/scripts/build/Install-R.ps1 index 96743d7256..0abd6e96c6 100644 --- a/images/windows/scripts/build/Install-R.ps1 +++ b/images/windows/scripts/build/Install-R.ps1 @@ -6,6 +6,13 @@ Install-ChocoPackage R.Project Install-ChocoPackage rtools -$rscriptPath = Resolve-Path "C:\Program Files\R\*\bin\x64" +if (Test-IsArm64) { + $rscriptPathPattern = "C:\Program Files (x86)\R\*\bin\x64" +} else { + $rscriptPathPattern = "C:\Program Files\R\*\bin\x64" +} + +$rscriptPath = Resolve-Path $rscriptPathPattern Add-MachinePathItem $rscriptPath + Invoke-PesterTests -TestFile "Tools" -TestName "R" diff --git a/images/windows/scripts/build/Install-Ruby.ps1 b/images/windows/scripts/build/Install-Ruby.ps1 index 01bd525bb1..f867f0bf62 100644 --- a/images/windows/scripts/build/Install-Ruby.ps1 +++ b/images/windows/scripts/build/Install-Ruby.ps1 @@ -63,6 +63,14 @@ function Set-DefaultRubyVersion { Add-MachinePathItem -PathItem $rubyDir | Out-Null } +if (Test-IsArm64) { + $downloadArch = "arm" + $toolcacheArch = "aarch64" +} else { + $downloadArch = "x64" + $toolcacheArch = "x64" +} + # Install Ruby $rubyTools = (Get-ToolsetContent).toolcache | Where-Object { $_.name -eq "Ruby" } $rubyToolVersions = $rubyTools.versions @@ -73,9 +81,14 @@ foreach ($rubyVersion in $rubyToolVersions) { $downloadUrl = Resolve-GithubReleaseAssetUrl ` -Repo "oneclick/rubyinstaller2" ` -Version "$rubyVersion*" ` - -UrlMatchPattern "*-x64.7z" + -UrlMatchPattern "*-${downloadArch}.7z" $packagePath = Invoke-DownloadWithRetry $downloadUrl - Install-Ruby -PackagePath $packagePath + + if (Test-IsArm64) { + Install-Ruby -PackagePath $packagePath -Architecture $toolcacheArch + } else { + Install-Ruby -PackagePath $packagePath -Architecture $toolcacheArch + } } Set-DefaultRubyVersion -Version $rubyTools.default -Arch $rubyTools.arch diff --git a/images/windows/scripts/build/Install-Rust.ps1 b/images/windows/scripts/build/Install-Rust.ps1 index cf35a74102..890b4103af 100644 --- a/images/windows/scripts/build/Install-Rust.ps1 +++ b/images/windows/scripts/build/Install-Rust.ps1 @@ -4,16 +4,22 @@ ## Supply chain security: checksum validation for bootstrap, managed by rustup for workloads ################################################################################ +if (Test-IsArm64) { + $rustArch = "aarch64" +} else { + $rustArch = "x86_64" +} + # Rust Env $env:RUSTUP_HOME = "C:\Users\Default\.rustup" $env:CARGO_HOME = "C:\Users\Default\.cargo" -# Download the latest rustup-init.exe for Windows x64 +# Download the latest rustup-init.exe for Windows # See https://rustup.rs/# -$rustupPath = Invoke-DownloadWithRetry "https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe" +$rustupPath = Invoke-DownloadWithRetry "https://static.rust-lang.org/rustup/dist/${rustArch}-pc-windows-msvc/rustup-init.exe" #region Supply chain security -$distributorFileHash = (Invoke-RestMethod -Uri 'https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe.sha256').Trim() +$distributorFileHash = (Invoke-RestMethod -Uri "https://static.rust-lang.org/rustup/dist/${rustArch}-pc-windows-msvc/rustup-init.exe.sha256").Trim() Test-FileChecksum $rustupPath -ExpectedSHA256Sum $distributorFileHash #endregion @@ -28,18 +34,23 @@ Add-DefaultPathItem "%USERPROFILE%\.cargo\bin" # Add Rust binaries to the path $env:Path += ";$env:CARGO_HOME\bin" -# Add i686 target for building 32-bit binaries -rustup target add i686-pc-windows-msvc +if (Test-IsArm64) { + rustup target add aarch64-pc-windows-msvc +} else { + # Add i686 target for building 32-bit binaries + rustup target add i686-pc-windows-msvc -# Add target for building mingw-w64 binaries -rustup target add x86_64-pc-windows-gnu + # Add target for building mingw-w64 binaries + rustup target add x86_64-pc-windows-gnu +} # Install common tools rustup component add rustfmt clippy if ($LASTEXITCODE -ne 0) { throw "Rust component installation failed with exit code $LASTEXITCODE" } -if (-not (Test-IsWin25)) { + +if ((Test-IsWin22-X64) -or (Test-IsWin11-Arm64)) { cargo install --locked bindgen-cli cbindgen cargo-audit cargo-outdated if ($LASTEXITCODE -ne 0) { throw "Rust tools installation failed with exit code $LASTEXITCODE" diff --git a/images/windows/scripts/build/Install-VisualStudio.ps1 b/images/windows/scripts/build/Install-VisualStudio.ps1 index e866ffeb65..5e28bffdd7 100644 --- a/images/windows/scripts/build/Install-VisualStudio.ps1 +++ b/images/windows/scripts/build/Install-VisualStudio.ps1 @@ -4,6 +4,12 @@ ################################################################################ $vsToolset = (Get-ToolsetContent).visualStudio +if (Test-IsArm64) { + $vsArch = "arm64" +} else { + $vsArch = "x64" +} + # Install Visual Studio for Windows 22 and 25 with InstallChannel Install-VisualStudio ` -Version $vsToolset.subversion ` @@ -11,7 +17,8 @@ Install-VisualStudio ` -Channel $vsToolset.channel ` -InstallChannelUri $vsToolset.installChannelUri ` -RequiredComponents $vsToolset.workloads ` - -ExtraArgs "--allWorkloads --includeRecommended --remove Component.CPython3.x64" + -ExtraArgs "--allWorkloads --includeRecommended --remove Component.CPython3.x64" ` + -Architecture $vsArch # Find the version of VS installed for this instance # Only supports a single instance @@ -27,7 +34,7 @@ $vsInstallRoot = (Get-VisualStudioInstance).InstallationPath $newContent = '{"Extensions":[{"Key":"1e906ff5-9da8-4091-a299-5c253c55fdc9","Value":{"ShouldAutoUpdate":false}},{"Key":"Microsoft.VisualStudio.Web.AzureFunctions","Value":{"ShouldAutoUpdate":false}}],"ShouldAutoUpdate":false,"ShouldCheckForUpdates":false}' Set-Content -Path "$vsInstallRoot\Common7\IDE\Extensions\MachineState.json" -Value $newContent -if (Test-IsWin22) { +if (Test-IsWin22-X64) { # Install Windows 10 SDK version 10.0.17763 Install-Binary -Type EXE ` -Url 'https://go.microsoft.com/fwlink/p/?LinkID=2033908' ` @@ -42,7 +49,7 @@ Install-Binary -Type EXE ` -ExpectedSubject $(Get-MicrosoftPublisher) # Enable Windows Desktop Debuggers (cdb.exe) on Windows Server 2025 -if (Test-IsWin25) { +if (Test-IsWin25-X64) { $installerEntry = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* ` | Where-Object { $_.DisplayName -match "Windows Software Development Kit" } ` | Sort-Object DisplayVersion -Descending | Select-Object -First 1 diff --git a/images/windows/scripts/build/Install-WDK.ps1 b/images/windows/scripts/build/Install-WDK.ps1 index 1cac470cf7..6560cb3465 100644 --- a/images/windows/scripts/build/Install-WDK.ps1 +++ b/images/windows/scripts/build/Install-WDK.ps1 @@ -4,9 +4,12 @@ ################################################################################ # Requires Windows SDK with the same version number as the WDK -if (Test-IsWin22) { +if (Test-IsWin22-X64) { # SDK is available through Visual Studio $wdkUrl = "https://go.microsoft.com/fwlink/?linkid=2324617" +} elseif (Test-IsWin11-Arm64) { + # SDK is available through Visual Studio + $wdkUrl = "https://go.microsoft.com/fwlink/?linkid=2335869" } else { throw "Invalid version of Visual Studio is found. Windows Server 2022 is required" } diff --git a/images/windows/scripts/build/Invoke-Cleanup.ps1 b/images/windows/scripts/build/Invoke-Cleanup.ps1 index 7616c218e2..2cc6151163 100644 --- a/images/windows/scripts/build/Invoke-Cleanup.ps1 +++ b/images/windows/scripts/build/Invoke-Cleanup.ps1 @@ -49,7 +49,7 @@ if ($LASTEXITCODE -ne 0) { throw "Failed to clean npm cache" } -if (Test-IsWin25) { +if (Test-IsWin25-X64) { $directoriesToCompact = @( "C:\Program Files (x86)\Android", "C:\Program Files\dotnet", diff --git a/images/windows/scripts/docs-gen/Generate-SoftwareReport.ps1 b/images/windows/scripts/docs-gen/Generate-SoftwareReport.ps1 index 40fe4b1ca0..0a84fc3d51 100644 --- a/images/windows/scripts/docs-gen/Generate-SoftwareReport.ps1 +++ b/images/windows/scripts/docs-gen/Generate-SoftwareReport.ps1 @@ -21,7 +21,7 @@ Import-Module (Join-Path $PSScriptRoot "SoftwareReport.VisualStudio.psm1") -Disa $softwareReport = [SoftwareReport]::new($(Build-OSInfoSection)) $optionalFeatures = $softwareReport.Root.AddHeader("Windows features") $optionalFeatures.AddToolVersion("Windows Subsystem for Linux (WSLv1):", "Enabled") -if (Test-IsWin25) { +if (Test-IsWin25-X64) { $optionalFeatures.AddToolVersion("Windows Subsystem for Linux (Default, WSLv2):", $(Get-WSL2Version)) } $installedSoftware = $softwareReport.Root.AddHeader("Installed Software") @@ -44,7 +44,9 @@ $packageManagement = $installedSoftware.AddHeader("Package Management") $packageManagement.AddToolVersion("Chocolatey", $(Get-ChocoVersion)) $packageManagement.AddToolVersion("Composer", $(Get-ComposerVersion)) $packageManagement.AddToolVersion("Helm", $(Get-HelmVersion)) -$packageManagement.AddToolVersion("Miniconda", $(Get-CondaVersion)) +if (Test-IsX64) { + $packageManagement.AddToolVersion("Miniconda", $(Get-CondaVersion)) +} $packageManagement.AddToolVersion("NPM", $(Get-NPMVersion)) $packageManagement.AddToolVersion("NuGet", $(Get-NugetVersion)) $packageManagement.AddToolVersion("pip", $(Get-PipVersion)) @@ -70,13 +72,17 @@ $tools.AddToolVersion("azcopy", $(Get-AzCopyVersion)) $tools.AddToolVersion("Bazel", $(Get-BazelVersion)) $tools.AddToolVersion("Bazelisk", $(Get-BazeliskVersion)) $tools.AddToolVersion("Bicep", $(Get-BicepVersion)) -$tools.AddToolVersion("Cabal", $(Get-CabalVersion)) +if (Test-IsX64) { + $tools.AddToolVersion("Cabal", $(Get-CabalVersion)) +} $tools.AddToolVersion("CMake", $(Get-CMakeVersion)) $tools.AddToolVersion("CodeQL Action Bundle", $(Get-CodeQLBundleVersion)) -$tools.AddToolVersion("Docker", $(Get-DockerVersion)) -$tools.AddToolVersion("Docker Compose v2", $(Get-DockerComposeVersionV2)) -$tools.AddToolVersion("Docker-wincred", $(Get-DockerWincredVersion)) -$tools.AddToolVersion("ghc", $(Get-GHCVersion)) +if (Test-IsX64) { + $tools.AddToolVersion("Docker", $(Get-DockerVersion)) + $tools.AddToolVersion("Docker Compose v2", $(Get-DockerComposeVersionV2)) + $tools.AddToolVersion("Docker-wincred", $(Get-DockerWincredVersion)) + $tools.AddToolVersion("ghc", $(Get-GHCVersion)) +} $tools.AddToolVersion("Git", $(Get-GitVersion)) $tools.AddToolVersion("Git LFS", $(Get-GitLFSVersion)) $tools.AddToolVersion("ImageMagick", $(Get-ImageMagickVersion)) @@ -84,36 +90,42 @@ $tools.AddToolVersion("InnoSetup", $(Get-InnoSetupVersion)) $tools.AddToolVersion("jq", $(Get-JQVersion)) $tools.AddToolVersion("Kind", $(Get-KindVersion)) $tools.AddToolVersion("Kubectl", $(Get-KubectlVersion)) -if (-not (Test-IsWin25)) { +if (-not (Test-IsWin25-X64)) { $tools.AddToolVersion("Mercurial", $(Get-MercurialVersion)) } $tools.AddToolVersion("gcc", $(Get-GCCVersion)) $tools.AddToolVersion("gdb", $(Get-GDBVersion)) $tools.AddToolVersion("GNU Binutils", $(Get-GNUBinutilsVersion)) $tools.AddToolVersion("Newman", $(Get-NewmanVersion)) -if (-not (Test-IsWin25)) { +if (-not (Test-IsWin25-X64)) { $tools.AddToolVersion("NSIS", $(Get-NSISVersion)) } $tools.AddToolVersion("OpenSSL", $(Get-OpenSSLVersion)) $tools.AddToolVersion("Packer", $(Get-PackerVersion)) $tools.AddToolVersion("Pulumi", $(Get-PulumiVersion)) $tools.AddToolVersion("R", $(Get-RVersion)) -$tools.AddToolVersion("Service Fabric SDK", $(Get-ServiceFabricSDKVersion)) +if (Test-IsX64) { + $tools.AddToolVersion("Service Fabric SDK", $(Get-ServiceFabricSDKVersion)) +} $tools.AddToolVersion("Stack", $(Get-StackVersion)) -if (-not (Test-IsWin25)) { +if (Test-IsWin22-X64) { $tools.AddToolVersion("Subversion (SVN)", $(Get-SVNVersion)) } $tools.AddToolVersion("Swig", $(Get-SwigVersion)) $tools.AddToolVersion("VSWhere", $(Get-VSWhereVersion)) $tools.AddToolVersion("WinAppDriver", $(Get-WinAppDriver)) -$tools.AddToolVersion("WiX Toolset", $(Get-WixVersion)) +if (Test-IsX64) { + $tools.AddToolVersion("WiX Toolset", $(Get-WixVersion)) +} $tools.AddToolVersion("yamllint", $(Get-YAMLLintVersion)) -$tools.AddToolVersion("zstd", $(Get-ZstdVersion)) +if (Test-IsX64) { + $tools.AddToolVersion("zstd", $(Get-ZstdVersion)) +} $tools.AddToolVersion("Ninja", $(Get-NinjaVersion)) # CLI Tools $cliTools = $installedSoftware.AddHeader("CLI Tools") -if (-not (Test-IsWin25)) { +if (-not (Test-IsWin25-X64)) { $cliTools.AddToolVersion("Alibaba Cloud CLI", $(Get-AlibabaCLIVersion)) } $cliTools.AddToolVersion("AWS CLI", $(Get-AWSCLIVersion)) @@ -132,7 +144,7 @@ $rustTools.AddToolVersion("Rustdoc", $(Get-RustdocVersion)) $rustTools.AddToolVersion("Rustup", $(Get-RustupVersion)) $rustToolsPackages = $rustTools.AddHeader("Packages") -if (-not (Test-IsWin25)) { +if (-not (Test-IsWin25-X64)) { $rustToolsPackages.AddToolVersion("bindgen", $(Get-BindgenVersion)) $rustToolsPackages.AddToolVersion("cargo-audit", $(Get-CargoAuditVersion)) $rustToolsPackages.AddToolVersion("cargo-outdated", $(Get-CargoOutdatedVersion)) @@ -150,26 +162,32 @@ $browsersAndWebdrivers.AddHeader("Environment variables").AddTable($(Build-Brows $installedSoftware.AddHeader("Java").AddTable($(Get-JavaVersions)) # Shells -$installedSoftware.AddHeader("Shells").AddTable($(Get-ShellTarget)) +if (Test-IsX64) { + $installedSoftware.AddHeader("Shells").AddTable($(Get-ShellTarget)) +} # MSYS2 -$msys2 = $installedSoftware.AddHeader("MSYS2") -$msys2.AddToolVersion("Pacman", $(Get-PacmanVersion)) +if (Test-IsX64) { + $msys2 = $installedSoftware.AddHeader("MSYS2") + $msys2.AddToolVersion("Pacman", $(Get-PacmanVersion)) -$notes = @' + $notes = @' Location: C:\msys64 Note: MSYS2 is pre-installed on image but not added to PATH. '@ -$msys2.AddHeader("Notes").AddNote($notes) + $msys2.AddHeader("Notes").AddNote($notes) +} # Cached Tools $installedSoftware.AddHeader("Cached Tools").AddNodes($(Build-CachedToolsSection)) # Databases -$databases = $installedSoftware.AddHeader("Databases") -$databases.AddHeader("PostgreSQL").AddTable($(Get-PostgreSQLTable)) -$databases.AddHeader("MongoDB").AddTable($(Get-MongoDBTable)) +if (Test-IsX64) { + $databases = $installedSoftware.AddHeader("Databases") + $databases.AddHeader("PostgreSQL").AddTable($(Get-PostgreSQLTable)) + $databases.AddHeader("MongoDB").AddTable($(Get-MongoDBTable)) +} # Database tools $databaseTools = $installedSoftware.AddHeader("Database tools") @@ -178,9 +196,10 @@ $databaseTools.AddToolVersion("DacFx", $(Get-DacFxVersion)) $databaseTools.AddToolVersion("MySQL", $(Get-MySQLVersion)) $databaseTools.AddToolVersion("SQL OLEDB Driver 18", $(Get-SQLOLEDBDriver18Version)) $databaseTools.AddToolVersion("SQL OLEDB Driver 19", $(Get-SQLOLEDBDriver19Version)) -$databaseTools.AddToolVersion("SQLPS", $(Get-SQLPSVersion)) -$databaseTools.AddToolVersion("MongoDB Shell (mongosh)", $(Get-MongoshVersion)) - +if (Test-IsX64) { + $databaseTools.AddToolVersion("SQLPS", $(Get-SQLPSVersion)) + $databaseTools.AddToolVersion("MongoDB Shell (mongosh)", $(Get-MongoshVersion)) +} # Web Servers $installedSoftware.AddHeader("Web Servers").AddTable($(Build-WebServersSection)) @@ -216,13 +235,15 @@ $psModules.AddNodes($(Get-PowerShellModules)) # Android -$android = $installedSoftware.AddHeader("Android") -$android.AddTable($(Build-AndroidTable)) +if (Test-IsX64) { + $android = $installedSoftware.AddHeader("Android") + $android.AddTable($(Build-AndroidTable)) -$android.AddHeader("Environment variables").AddTable($(Build-AndroidEnvironmentTable)) + $android.AddHeader("Environment variables").AddTable($(Build-AndroidEnvironmentTable)) +} # Cached Docker images -if (-not (Test-IsWin25)) { +if (Test-IsWin22-X64) { $installedSoftware.AddHeader("Cached Docker images").AddTable($(Get-CachedDockerImagesTableData)) } diff --git a/images/windows/scripts/docs-gen/SoftwareReport.CachedTools.psm1 b/images/windows/scripts/docs-gen/SoftwareReport.CachedTools.psm1 index a62ed45257..a5cd816d3c 100644 --- a/images/windows/scripts/docs-gen/SoftwareReport.CachedTools.psm1 +++ b/images/windows/scripts/docs-gen/SoftwareReport.CachedTools.psm1 @@ -34,7 +34,7 @@ function Build-CachedToolsSection [ToolVersionsListNode]::new("Go", $(Get-ToolcacheGoVersions), '^\d+\.\d+', 'List'), [ToolVersionsListNode]::new("Node.js", $(Get-ToolcacheNodeVersions), '^\d+', 'List'), [ToolVersionsListNode]::new("Python", $(Get-ToolcachePythonVersions), '^\d+\.\d+', 'List'), - [ToolVersionsListNode]::new("PyPy", $(Get-ToolcachePyPyVersions), '^\d+\.\d+', 'List'), + $(if (-not (Test-IsWin11-Arm64)) { [ToolVersionsListNode]::new("PyPy", $(Get-ToolcachePyPyVersions), '^\d+\.\d+', 'List') }), [ToolVersionsListNode]::new("Ruby", $(Get-ToolcacheRubyVersions), '^\d+\.\d+', 'List') - ) + ) | Where-Object { $_ } } diff --git a/images/windows/scripts/docs-gen/SoftwareReport.Common.psm1 b/images/windows/scripts/docs-gen/SoftwareReport.Common.psm1 index 58d3a96db4..f480c546cb 100644 --- a/images/windows/scripts/docs-gen/SoftwareReport.Common.psm1 +++ b/images/windows/scripts/docs-gen/SoftwareReport.Common.psm1 @@ -297,9 +297,9 @@ function Build-PackageManagementEnvironmentTable { "Name" = "VCPKG_INSTALLATION_ROOT" "Value" = $env:VCPKG_INSTALLATION_ROOT }, - [PSCustomObject] @{ + $(if (-not (Test-IsWin11-Arm64)) { [PSCustomObject] @{ "Name" = "CONDA" "Value" = $env:CONDA - } - ) + } }) + ) | Where-Object { $_ } } diff --git a/images/windows/scripts/docs-gen/SoftwareReport.Java.psm1 b/images/windows/scripts/docs-gen/SoftwareReport.Java.psm1 index cd6c077d3e..2249451744 100644 --- a/images/windows/scripts/docs-gen/SoftwareReport.Java.psm1 +++ b/images/windows/scripts/docs-gen/SoftwareReport.Java.psm1 @@ -1,6 +1,10 @@ function Get-JavaVersions { $defaultJavaPath = $env:JAVA_HOME - $javaVersions = Get-Item env:JAVA_HOME_*_X64 + if (Test-IsArm64) { + $javaVersions = Get-Item env:JAVA_HOME_*_AARCH64 + } else { + $javaVersions = Get-Item env:JAVA_HOME_*_X64 + } $sortRules = @{ Expression = { [Int32] $_.Name.Split("_")[2] } Descending = $false diff --git a/images/windows/scripts/docs-gen/SoftwareReport.VisualStudio.psm1 b/images/windows/scripts/docs-gen/SoftwareReport.VisualStudio.psm1 index 082a840b11..241898169c 100644 --- a/images/windows/scripts/docs-gen/SoftwareReport.VisualStudio.psm1 +++ b/images/windows/scripts/docs-gen/SoftwareReport.VisualStudio.psm1 @@ -43,7 +43,7 @@ function Get-VisualStudioExtensions { ) # WDK - if (-not (Test-IsWin25)) { + if (-not (Test-IsWin25-X64)) { $wdkVersion = Get-WDKVersion $wdkPackages = @( @{Package = 'Windows Driver Kit'; Version = $wdkVersion } diff --git a/images/windows/scripts/helpers/ImageHelpers.psm1 b/images/windows/scripts/helpers/ImageHelpers.psm1 index 4ebbd8fc88..92f3346f15 100644 --- a/images/windows/scripts/helpers/ImageHelpers.psm1 +++ b/images/windows/scripts/helpers/ImageHelpers.psm1 @@ -25,6 +25,12 @@ Export-ModuleMember -Function @( 'Get-TCToolVersionPath' 'Test-IsWin25' 'Test-IsWin22' + 'Test-IsWin11' + 'Test-IsArm64' + 'Test-IsX64' + 'Test-IsWin25-X64' + 'Test-IsWin22-X64' + 'Test-IsWin11-Arm64' 'Expand-7ZipArchive' 'Get-WindowsUpdateStates' 'Invoke-ScriptBlockWithRetry' diff --git a/images/windows/scripts/helpers/InstallHelpers.ps1 b/images/windows/scripts/helpers/InstallHelpers.ps1 index 032e8b58be..1569af5519 100644 --- a/images/windows/scripts/helpers/InstallHelpers.ps1 +++ b/images/windows/scripts/helpers/InstallHelpers.ps1 @@ -322,6 +322,38 @@ function Get-TCToolVersionPath { return Join-Path $foundVersion $Arch } +function Test-IsArm64 { + <# + .SYNOPSIS + Checks if the current Windows operating system is running on an ARM64 architecture. + .DESCRIPTION + This function uses the Get-CimInstance cmdlet to retrieve information + about the current Windows operating system. It then checks if the OSArchitecture + property of the Win32_OperatingSystem class contains the string "ARM 64-bit", + indicating that the operating system is running on an ARM64 processor. + .OUTPUTS + Returns $true if the current Windows operating system is running on ARM64. + Otherwise, returns $false. + #> + (Get-CimInstance -ClassName Win32_OperatingSystem).OSArchitecture -match "ARM 64-bit" +} + +function Test-IsX64 { + <# + .SYNOPSIS + Checks if the current Windows operating system is running on an x64 architecture. + .DESCRIPTION + This function uses the Get-CimInstance cmdlet to retrieve information + about the current Windows operating system. It then checks if the OSArchitecture + property of the Win32_OperatingSystem class contains the string "x64", + indicating that the operating system is running on an x64 processor. + .OUTPUTS + Returns $true if the current Windows operating system is running on x64. + Otherwise, returns $false. + #> + (Get-CimInstance -ClassName Win32_OperatingSystem).OSArchitecture -eq "64-bit" +} + function Test-IsWin25 { <# .SYNOPSIS @@ -356,6 +388,63 @@ function Test-IsWin22 { (Get-CimInstance -ClassName Win32_OperatingSystem).Caption -match "2022" } +function Test-IsWin11 { + <# + .SYNOPSIS + Checks if the current Windows operating system is Windows 11. + .DESCRIPTION + This function uses the Get-CimInstance cmdlet to retrieve information + about the current Windows operating system. It then checks if the Caption + property of the Win32_OperatingSystem class contains the string "Windows 11", + indicating that the operating system is Windows 11. + .OUTPUTS + Returns $true if the current Windows operating system is Windows 11. + Otherwise, returns $false. + #> + (Get-CimInstance -ClassName Win32_OperatingSystem).Caption -match "Windows 11" +} + +function Test-IsWin25-X64 { + <# + .SYNOPSIS + Checks if the current Windows operating system is Windows Server 2025 running on x64 architecture. + .DESCRIPTION + This function combines the checks from Test-IsWin25 and Test-IsX64 functions to determine if the current Windows operating system is Windows Server 2025 running on an x64 architecture. + .OUTPUTS + Returns $true if the current Windows operating system is Windows Server 2025 running on x64 architecture. + Otherwise, returns $false. + #> + (Test-IsWin25) -and (Test-IsX64) +} + +function Test-IsWin22-X64 { + <# + .SYNOPSIS + Checks if the current Windows operating system is Windows Server 2022 running on x64 architecture. + + .DESCRIPTION + This function combines the checks from Test-IsWin22 and Test-IsX64 functions to determine if the current Windows operating system is Windows Server 2022 running on an x64 architecture. + + .OUTPUTS + Returns $true if the current Windows operating system is Windows Server 2022 running on x64 architecture. + Otherwise, returns $false. + #> + (Test-IsWin22) -and (Test-IsX64) +} + +function Test-IsWin11-Arm64 { + <# + .SYNOPSIS + Checks if the current Windows operating system is Windows 11 running on ARM64 architecture. + .DESCRIPTION + This function combines the checks from Test-IsWin11 and Test-IsArm64 functions to determine if the current Windows operating system is Windows 11 running on an ARM64 architecture. + .OUTPUTS + Returns $true if the current Windows operating system is Windows 11 running on ARM64 architecture. + Otherwise, returns $false. + #> + (Test-IsWin11) -and (Test-IsArm64) +} + function Expand-7ZipArchive { <# .SYNOPSIS diff --git a/images/windows/scripts/helpers/VisualStudioHelpers.ps1 b/images/windows/scripts/helpers/VisualStudioHelpers.ps1 index db02591a71..fd9eff81bd 100644 --- a/images/windows/scripts/helpers/VisualStudioHelpers.ps1 +++ b/images/windows/scripts/helpers/VisualStudioHelpers.ps1 @@ -32,7 +32,8 @@ Function Install-VisualStudio { [Parameter(Mandatory)] [String] $Channel, [String] $InstallChannelUri = "", [Parameter(Mandatory)] [String[]] $RequiredComponents, - [String] $ExtraArgs = "" + [String] $ExtraArgs = "", + [String] $Architecture = "x64" ) if ($env:INSTALL_VS_2026) { @@ -61,7 +62,7 @@ Function Install-VisualStudio { "channelUri" = $channelUri "channelId" = $channelId "productId" = $productId - "arch" = "x64" + "arch" = $Architecture "add" = $RequiredComponents | ForEach-Object { "$_;includeRecommended" } } diff --git a/images/windows/scripts/tests/Android.Tests.ps1 b/images/windows/scripts/tests/Android.Tests.ps1 index c53f99b3e3..791696827d 100644 --- a/images/windows/scripts/tests/Android.Tests.ps1 +++ b/images/windows/scripts/tests/Android.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "Android SDK" { +Describe "Android SDK" -Skip:(Test-IsArm64) { $androidToolset = (Get-ToolsetContent).android $androidInstalledPackages = Get-AndroidInstalledPackages diff --git a/images/windows/scripts/tests/CLI.Tools.Tests.ps1 b/images/windows/scripts/tests/CLI.Tools.Tests.ps1 index f97dc7c744..b9584da81f 100644 --- a/images/windows/scripts/tests/CLI.Tools.Tests.ps1 +++ b/images/windows/scripts/tests/CLI.Tools.Tests.ps1 @@ -11,7 +11,7 @@ Describe "Azure DevOps CLI" { } } -Describe "Aliyun CLI" -Skip:(Test-IsWin25) { +Describe "Aliyun CLI" -Skip:(Test-IsWin25-X64) { It "Aliyun CLI" { "aliyun version" | Should -ReturnZeroExitCode } diff --git a/images/windows/scripts/tests/ChocoPackages.Tests.ps1 b/images/windows/scripts/tests/ChocoPackages.Tests.ps1 index 1f283ca804..3de123b438 100644 --- a/images/windows/scripts/tests/ChocoPackages.Tests.ps1 +++ b/images/windows/scripts/tests/ChocoPackages.Tests.ps1 @@ -58,7 +58,7 @@ Describe "Pulumi" { } } -Describe "Svn" -Skip:(Test-IsWin25) { +Describe "Svn" -Skip:(-not(Test-IsWin22-X64)) { It "svn" { "svn --version --quiet" | Should -ReturnZeroExitCode } @@ -86,7 +86,7 @@ Describe "Julia" { } } -Describe "CMake" { +Describe "CMake" -Skip:(Test-IsArm64) { It "cmake" { "cmake --version" | Should -ReturnZeroExitCode } @@ -98,7 +98,7 @@ Describe "ImageMagick" { } } -Describe "Ninja" { +Describe "Ninja" -Skip:(Test-IsArm64) { BeforeAll { $ninjaProjectPath = $(Join-Path $env:TEMP_DIR "ninjaproject") New-item -Path $ninjaProjectPath -ItemType Directory -Force diff --git a/images/windows/scripts/tests/Databases.Tests.ps1 b/images/windows/scripts/tests/Databases.Tests.ps1 index 03d8921084..37eebe7818 100644 --- a/images/windows/scripts/tests/Databases.Tests.ps1 +++ b/images/windows/scripts/tests/Databases.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "MongoDB" { +Describe "MongoDB" -Skip:(Test-IsWin11-Arm64) { Context "Version" { It "" -TestCases @( @{ ToolName = "mongos" } @@ -33,7 +33,7 @@ Describe "MongoDB" { } } -Describe "PostgreSQL" { +Describe "PostgreSQL" -Skip:(Test-IsWin11-Arm64) { $psqlTests = @( @{envVar = "PGROOT"; pgPath = Get-EnvironmentVariable "PGROOT" } @{envVar = "PGBIN"; pgPath = Get-EnvironmentVariable "PGBIN" } diff --git a/images/windows/scripts/tests/Docker.Tests.ps1 b/images/windows/scripts/tests/Docker.Tests.ps1 index b994430e3f..30a34a4a36 100644 --- a/images/windows/scripts/tests/Docker.Tests.ps1 +++ b/images/windows/scripts/tests/Docker.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "Docker" { +Describe "Docker" -Skip:(Test-IsWin11-Arm64) { It "docker is installed" { "docker --version" | Should -ReturnZeroExitCode } @@ -12,20 +12,20 @@ Describe "Docker" { } } -Describe "DockerCompose" { +Describe "DockerCompose" -Skip:(Test-IsWin11-Arm64) { It "docker compose v2" { "docker compose version" | Should -ReturnZeroExitCode } } -Describe "DockerWinCred" { +Describe "DockerWinCred" -Skip:(Test-IsWin11-Arm64) { It "docker-wincred" { "docker-credential-wincred version" | Should -ReturnZeroExitCode } } -Describe "DockerImages" -Skip:(Test-IsWin25) { +Describe "DockerImages" -Skip:((Test-IsWin25-X64) -or (Test-IsWin11-Arm64)) { Context "docker images" { $testCases = (Get-ToolsetContent).docker.images | ForEach-Object { @{ ImageName = $_ } } diff --git a/images/windows/scripts/tests/Haskell.Tests.ps1 b/images/windows/scripts/tests/Haskell.Tests.ps1 index 866ef5dca6..328b06f803 100644 --- a/images/windows/scripts/tests/Haskell.Tests.ps1 +++ b/images/windows/scripts/tests/Haskell.Tests.ps1 @@ -1,33 +1,29 @@ -Describe "Haskell" { - $ghcPackagesPath = "c:\ghcup\ghc" - [array] $ghcVersionList = Get-ChildItem -Path $ghcPackagesPath -Filter "*" | ForEach-Object { $_.Name.Trim() } - $ghcCount = $ghcVersionList.Count - $defaultGhcVersion = $ghcVersionList | Sort-Object {[Version] $_} | Select-Object -Last 1 - $ghcDefaultCases = @{ - defaultGhcVersion = $defaultGhcVersion - defaultGhcShortVersion = ([version] $defaultGhcVersion).ToString(3) - } - - $ghcTestCases = $ghcVersionList | ForEach-Object { - $ghcVersion = $_ - $ghcShortVersion = ([version] $ghcVersion).ToString(3) - $binGhcPath = Join-Path $ghcPackagesPath "$ghcShortVersion\bin\ghc.exe" - @{ - ghcVersion = $ghcVersion - ghcShortVersion = $ghcShortVersion - binGhcPath = $binGhcPath +Describe "Haskell" -Skip:(Test-IsWin11-Arm64) { + BeforeDiscovery { + if (Test-IsWin11-Arm64) { return } + $ghcPackagesPath = "c:\ghcup\ghc" + [array] $ghcVersionList = Get-ChildItem -Path $ghcPackagesPath -Filter "*" | ForEach-Object { $_.Name.Trim() } + $ghcCount = $ghcVersionList.Count + $defaultGhcVersion = $ghcVersionList | Sort-Object { [Version] $_ } | Select-Object -Last 1 + $ghcDefaultCases = @{ + defaultGhcVersion = $defaultGhcVersion + defaultGhcShortVersion = ([version] $defaultGhcVersion).ToString(3) } - } - - $ghcupEnvExists = @( - @{envVar = "GHCUP_INSTALL_BASE_PREFIX"} - @{envVar = "GHCUP_MSYS2"} - ) - - If (Test-IsWin25) { - $numberOfVersions = 1 - } else { - $numberOfVersions = 3 + $ghcTestCases = $ghcVersionList | ForEach-Object { + $ghcVersion = $_ + $ghcShortVersion = ([version] $ghcVersion).ToString(3) + $binGhcPath = Join-Path $ghcPackagesPath "$ghcShortVersion\bin\ghc.exe" + @{ + ghcVersion = $ghcVersion + ghcShortVersion = $ghcShortVersion + binGhcPath = $binGhcPath + } + } + $ghcupEnvExists = @( + @{envVar = "GHCUP_INSTALL_BASE_PREFIX"} + @{envVar = "GHCUP_MSYS2"} + ) + $numberOfVersions = if (Test-IsWin25-X64) { 1 } else { 3 } } It " environment variable exists" -TestCases $ghcupEnvExists { diff --git a/images/windows/scripts/tests/Java.Tests.ps1 b/images/windows/scripts/tests/Java.Tests.ps1 index bf40a8d430..b8194967fa 100644 --- a/images/windows/scripts/tests/Java.Tests.ps1 +++ b/images/windows/scripts/tests/Java.Tests.ps1 @@ -5,9 +5,17 @@ Describe "Java" { [array] $testCases = $jdkVersions | ForEach-Object { @{Version = $_ } } + BeforeAll { + if (Test-IsArm64) { + $expectedArch = "AARCH64" + } else { + $expectedArch = "X64" + } + } + It "Java is default" -TestCases @(@{ DefaultJavaVersion = $defaultVersion }) { $actualJavaPath = Get-EnvironmentVariable "JAVA_HOME" - $expectedJavaPath = Get-EnvironmentVariable "JAVA_HOME_${DefaultJavaVersion}_X64" + $expectedJavaPath = Get-EnvironmentVariable "JAVA_HOME_${DefaultJavaVersion}_${expectedArch}" $actualJavaPath | Should -Not -BeNullOrEmpty $expectedJavaPath | Should -Not -BeNullOrEmpty @@ -24,7 +32,7 @@ Describe "Java" { } It "Java " -TestCases $testCases { - $javaVariableValue = Get-EnvironmentVariable "JAVA_HOME_${Version}_X64" + $javaVariableValue = Get-EnvironmentVariable "JAVA_HOME_${Version}_${expectedArch}" $javaVariableValue | Should -Not -BeNullOrEmpty $javaPath = Join-Path $javaVariableValue "bin\java" diff --git a/images/windows/scripts/tests/MSYS2.Tests.ps1 b/images/windows/scripts/tests/MSYS2.Tests.ps1 index c92e7a8da5..9f6089fb7e 100644 --- a/images/windows/scripts/tests/MSYS2.Tests.ps1 +++ b/images/windows/scripts/tests/MSYS2.Tests.ps1 @@ -3,7 +3,7 @@ BeforeAll { $originalPath = $env:PATH } -Describe "MSYS2 packages" { +Describe "MSYS2 packages" -Skip:(Test-IsWin11-Arm64) { BeforeEach { $env:PATH = "$msys2Dir;$env:PATH" } @@ -31,7 +31,7 @@ Describe "MSYS2 packages" { $mingwTypes = (Get-ToolsetContent).MsysPackages.mingw foreach ($mingwType in $mingwTypes) { - Describe "$($mingwType.arch) packages" { + Describe "$($mingwType.arch) packages" -Skip:(Test-IsWin11-Arm64) { $tools = $mingwType.runtime_packages $execDir = Join-Path "C:\msys64" $mingwType.exec_dir | Join-Path -ChildPath "bin" diff --git a/images/windows/scripts/tests/Miniconda.Tests.ps1 b/images/windows/scripts/tests/Miniconda.Tests.ps1 index 763a158e23..5a3894a344 100644 --- a/images/windows/scripts/tests/Miniconda.Tests.ps1 +++ b/images/windows/scripts/tests/Miniconda.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "Miniconda" { +Describe "Miniconda" -Skip:(Test-IsWin11-Arm64) { It "Miniconda Environment variables is set. " { ${env:CONDA} | Should -Not -BeNullOrEmpty } @@ -11,4 +11,4 @@ Describe "Miniconda" { $condaPath | Should -Exist "$condaPath --version" | Should -ReturnZeroExitCode } -} \ No newline at end of file +} diff --git a/images/windows/scripts/tests/Rust.Tests.ps1 b/images/windows/scripts/tests/Rust.Tests.ps1 index 717e80e428..4449d40561 100644 --- a/images/windows/scripts/tests/Rust.Tests.ps1 +++ b/images/windows/scripts/tests/Rust.Tests.ps1 @@ -5,7 +5,7 @@ Describe "Rust" { $env:Path += ";$env:CARGO_HOME\bin" } - if (Test-IsWin25) { + if (Test-IsWin25-X64) { $rustTools = @( @{ToolName = "rustup"; binPath = "C:\Users\Default\.cargo\bin\rustup.exe"} @{ToolName = "rustc"; binPath = "C:\Users\Default\.cargo\bin\rustc.exe"} diff --git a/images/windows/scripts/tests/Shell.Tests.ps1 b/images/windows/scripts/tests/Shell.Tests.ps1 index caddaf7fb7..9736da919d 100644 --- a/images/windows/scripts/tests/Shell.Tests.ps1 +++ b/images/windows/scripts/tests/Shell.Tests.ps1 @@ -1,9 +1,9 @@ Describe "Shell" { $shellTestCases = @( @{Name = "C:\shells\gitbash.exe"; Target = "$env:ProgramFiles\Git\bin\bash.exe"}, - @{Name = "C:\shells\msys2bash.cmd"; Target = $null} + $(if (-not (Test-IsWin11-Arm64)) { @{Name = "C:\shells\msys2bash.cmd"; Target = $null} }), @{Name = "C:\shells\wslbash.exe"; Target = "$env:SystemRoot\System32\bash.exe"} - ) + ) | Where-Object { $_ } It " target to " -TestCases $shellTestCases { (Get-Item $Name).Target | Should -BeExactly $Target diff --git a/images/windows/scripts/tests/Tools.Tests.ps1 b/images/windows/scripts/tests/Tools.Tests.ps1 index 3c6301613a..bc739ef5c0 100644 --- a/images/windows/scripts/tests/Tools.Tests.ps1 +++ b/images/windows/scripts/tests/Tools.Tests.ps1 @@ -56,7 +56,7 @@ Describe "DACFx" { } } -Describe "Mercurial" -Skip:(Test-IsWin25) { +Describe "Mercurial" -Skip:(Test-IsWin25-X64) { It "Mercurial" { "hg --version" | Should -ReturnZeroExitCode } @@ -96,7 +96,7 @@ Describe "NET48" { } } -Describe "NSIS" -Skip:(Test-IsWin25) { +Describe "NSIS" -Skip:(Test-IsWin25-X64) { It "NSIS" { "makensis /VERSION" | Should -ReturnZeroExitCode } @@ -118,7 +118,7 @@ Describe "Sbt" { } } -Describe "ServiceFabricSDK" { +Describe "ServiceFabricSDK" -Skip:(Test-IsWin11-Arm64) { It "PowerShell Module" { # Ignore PowerShell version check if running in PowerShell Core # https://github.com/microsoft/service-fabric/issues/1343 @@ -160,7 +160,7 @@ Describe "WebPlatformInstaller" { } } -Describe "Zstd" { +Describe "Zstd" -Skip:(Test-IsWin11-Arm64) { It "zstd" { "zstd -V" | Should -ReturnZeroExitCode } @@ -213,3 +213,37 @@ Describe "OpenSSL" { Get-ChildItem -Path "$env:SystemRoot\System32" -Filter "libssl-*.dll" -File -ErrorAction SilentlyContinue | Should -BeNullOrEmpty } } + +Describe "CMake" { + It "cmake" { + "cmake --version" | Should -ReturnZeroExitCode + } +} + +Describe "Ninja" { + BeforeAll { + $ninjaProjectPath = $(Join-Path $env:TEMP_DIR "ninjaproject") + New-item -Path $ninjaProjectPath -ItemType Directory -Force +@' +cmake_minimum_required(VERSION 3.10) +project(NinjaTest NONE) +'@ | Out-File -FilePath "$ninjaProjectPath/CMakeLists.txt" -Encoding utf8 + + $ninjaProjectBuildPath = $(Join-Path $ninjaProjectPath "build") + New-item -Path $ninjaProjectBuildPath -ItemType Directory -Force + Set-Location $ninjaProjectBuildPath + } + + It "Make a simple ninja project" { + "cmake -GNinja $ninjaProjectPath" | Should -ReturnZeroExitCode + } + + It "build.ninja file should exist" { + $buildFilePath = $(Join-Path $ninjaProjectBuildPath "build.ninja") + $buildFilePath | Should -Exist + } + + It "Ninja" { + "ninja --version" | Should -ReturnZeroExitCode + } +} diff --git a/images/windows/scripts/tests/Toolset.Tests.ps1 b/images/windows/scripts/tests/Toolset.Tests.ps1 index 83d4b9a40f..40401d2c6c 100644 --- a/images/windows/scripts/tests/Toolset.Tests.ps1 +++ b/images/windows/scripts/tests/Toolset.Tests.ps1 @@ -3,10 +3,6 @@ $toolsExecutables = @{ @{ Binary = "python.exe"; Arguments = "--version" }, @{ Binary = "Scripts\pip.exe"; Arguments = "--version" } ) - PyPy = @( - @{ Binary = "python.exe"; Arguments = "--version" }, - @{ Binary = "Scripts\pip.exe"; Arguments = "--version" } - ) Node = @( @{ Binary = "node.exe"; Arguments = "--version" }, @{ Binary = "npm"; Arguments = "--version" } @@ -19,6 +15,13 @@ $toolsExecutables = @{ ) } +if (Test-IsX64) { + $toolsExecutables.Add("PyPy", @( + @{ Binary = "python.exe"; Arguments = "--version" }, + @{ Binary = "Scripts\pip.exe"; Arguments = "--version" } + )) +} + function Get-ToolExecutables { Param ([String] $Name) if ($toolsExecutables.ContainsKey($Name)) { $toolsExecutables[$Name] } else { @() } diff --git a/images/windows/scripts/tests/VisualStudio.Tests.ps1 b/images/windows/scripts/tests/VisualStudio.Tests.ps1 index bc26c77236..2ce4de1ddd 100644 --- a/images/windows/scripts/tests/VisualStudio.Tests.ps1 +++ b/images/windows/scripts/tests/VisualStudio.Tests.ps1 @@ -25,7 +25,7 @@ Describe "Visual Studio" { } } -Describe "Windows 10 SDK" -Skip:(Test-IsWin25) { +Describe "Windows 10 SDK" -Skip:((Test-IsWin25-X64) -or (Test-IsWin11-Arm64)) { It "Verifies 17763 SDK is installed" { "${env:ProgramFiles(x86)}\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.17763.0\UAP.props" | Should -Exist } diff --git a/images/windows/scripts/tests/WDK.Tests.ps1 b/images/windows/scripts/tests/WDK.Tests.ps1 index 139670dace..8988e9b76a 100644 --- a/images/windows/scripts/tests/WDK.Tests.ps1 +++ b/images/windows/scripts/tests/WDK.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "WDK" -Skip:(Test-IsWin25) { +Describe "WDK" -Skip:(Test-IsWin25-X64) { It "WDK exists" { $regKey = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" $installedApplications = Get-ItemProperty -Path $regKey diff --git a/images/windows/scripts/tests/WindowsFeatures.Tests.ps1 b/images/windows/scripts/tests/WindowsFeatures.Tests.ps1 index ec8001b81a..a3b8f1cea7 100644 --- a/images/windows/scripts/tests/WindowsFeatures.Tests.ps1 +++ b/images/windows/scripts/tests/WindowsFeatures.Tests.ps1 @@ -79,12 +79,15 @@ Describe "Windows Updates" { if ( $Title -match "Microsoft Defender Antivirus" ) { $expect = "Installed", "Failed", "Running" } + if ( $Title -match "MicrosoftWindows.Client.WebExperience" ) { + $expect = "Installed", "Failed", "Running" + } $State | Should -BeIn $expect } } -Describe "WSL2" -Skip:(Test-IsWin22) { +Describe "WSL2" -Skip:((Test-IsWin22-X64) -or (Test-IsWin11-Arm64)) { It "WSL status should return zero exit code" { "wsl --status" | Should -ReturnZeroExitCode } diff --git a/images/windows/scripts/tests/Wix.Tests.ps1 b/images/windows/scripts/tests/Wix.Tests.ps1 index cf6fc2fdf1..7534915fca 100644 --- a/images/windows/scripts/tests/Wix.Tests.ps1 +++ b/images/windows/scripts/tests/Wix.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "Wix" { +Describe "Wix" -Skip:(Test-IsWin11-Arm64) { BeforeAll { $regKey = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" $installedApplications = Get-ItemProperty -Path $regKey diff --git a/images/windows/templates/build.windows-11-arm64.pkr.hcl b/images/windows/templates/build.windows-11-arm64.pkr.hcl new file mode 100644 index 0000000000..53ec3bbedc --- /dev/null +++ b/images/windows/templates/build.windows-11-arm64.pkr.hcl @@ -0,0 +1,282 @@ +build { + sources = ["source.azure-arm.image"] + name = "windows-11-arm64" + + provisioner "powershell" { + inline = [ + "New-Item -Path ${var.image_folder} -ItemType Directory -Force", + "New-Item -Path ${var.temp_dir} -ItemType Directory -Force" + ] + } + + provisioner "file" { + destination = "${var.image_folder}\\" + sources = [ + "${path.root}/../assets", + "${path.root}/../scripts", + "${path.root}/../toolsets" + ] + } + + provisioner "file" { + destination = "${var.image_folder}\\scripts\\docs-gen\\" + source = "${path.root}/../../../helpers/software-report-base" + } + + provisioner "powershell" { + inline = [ + "Move-Item '${var.image_folder}\\assets\\post-gen' 'C:\\post-generation'", + "Remove-Item -Recurse '${var.image_folder}\\assets'", + "Move-Item '${var.image_folder}\\scripts\\docs-gen' '${var.image_folder}\\SoftwareReport'", + "Move-Item '${var.image_folder}\\scripts\\helpers' '${var.helper_script_folder}\\ImageHelpers'", + "New-Item -Type Directory -Path '${var.helper_script_folder}\\TestsHelpers\\'", + "Move-Item '${var.image_folder}\\scripts\\tests\\Helpers.psm1' '${var.helper_script_folder}\\TestsHelpers\\TestsHelpers.psm1'", + "Move-Item '${var.image_folder}\\scripts\\tests' '${var.image_folder}\\tests'", + "Remove-Item -Recurse '${var.image_folder}\\scripts'", + "Move-Item '${var.image_folder}\\toolsets\\toolset-win-11-arm64.json' '${var.image_folder}\\toolset.json'", + "Remove-Item -Recurse '${var.image_folder}\\toolsets'" + ] + } + + provisioner "windows-shell" { + inline = [ + "net user ${var.install_user} ${var.install_password} /add /passwordchg:no /passwordreq:yes /active:yes /Y", + "net localgroup Administrators ${var.install_user} /add", + "winrm set winrm/config/service/auth @{Basic=\"true\"}", + "winrm get winrm/config/service/auth" + ] + } + + provisioner "powershell" { + inline = ["if (-not ((net localgroup Administrators) -contains '${var.install_user}')) { exit 1 }"] + } + + # Scheduled tasks spawned when using elevated_user provisioners requires the user to log in interactively on Windows Desktop + # Set AutoAdminLogon for elevated_user and reboot as a workaround + provisioner "powershell" { + inline = [ + "Set-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name AutoAdminLogon -Value 1 -type String", + "Set-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name DefaultUsername -Value \"${var.install_user}\" -type String", + "Set-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name DefaultPassword -Value \"${var.install_password}\" -type String", + ] + } + + provisioner "windows-restart" { + check_registry = true + restart_timeout = "10m" + } + + provisioner "powershell" { + elevated_password = "${var.install_password}" + elevated_user = "${var.install_user}" + inline = ["bcdedit.exe /set TESTSIGNING ON"] + } + + provisioner "powershell" { + environment_vars = ["IMAGE_VERSION=${var.image_version}", "IMAGE_OS=${var.image_os}", "AGENT_TOOLSDIRECTORY=${var.agent_tools_directory}", "IMAGEDATA_FILE=${var.imagedata_file}", "IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + execution_policy = "unrestricted" + scripts = [ + "${path.root}/../scripts/build/Configure-WindowsDefender.ps1", + "${path.root}/../scripts/build/Configure-PowerShell.ps1", + "${path.root}/../scripts/build/Install-PowerShellModules.ps1", + "${path.root}/../scripts/build/Install-WindowsFeatures.ps1", + "${path.root}/../scripts/build/Install-Chocolatey.ps1", + "${path.root}/../scripts/build/Configure-BaseImage.ps1", + "${path.root}/../scripts/build/Configure-ImageDataFile.ps1", + "${path.root}/../scripts/build/Configure-SystemEnvironment.ps1", + "${path.root}/../scripts/build/Configure-DotnetSecureChannel.ps1" + ] + } + + provisioner "windows-restart" { + check_registry = true + restart_check_command = "powershell -command \"& {while ( (Get-WindowsOptionalFeature -Online -FeatureName Containers -ErrorAction SilentlyContinue).State -ne 'Enabled' ) { Start-Sleep 30; Write-Output 'InProgress' }}\"" + restart_timeout = "10m" + } + + provisioner "powershell" { + inline = ["Set-Service -Name wlansvc -StartupType Manual", "if ($(Get-Service -Name wlansvc).Status -eq 'Running') { Stop-Service -Name wlansvc}"] + } + + provisioner "powershell" { + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-PowershellCore.ps1", + "${path.root}/../scripts/build/Install-WebPlatformInstaller.ps1" + ] + } + + provisioner "windows-restart" { + restart_timeout = "30m" + } + + provisioner "powershell" { + elevated_password = "${var.install_password}" + elevated_user = "${var.install_user}" + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-VisualStudio.ps1", + "${path.root}/../scripts/build/Install-KubernetesTools.ps1" + ] + valid_exit_codes = [0, 3010] + } + + provisioner "windows-restart" { + check_registry = true + restart_timeout = "10m" + } + + provisioner "powershell" { + pause_before = "2m0s" + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-WDK.ps1", + "${path.root}/../scripts/build/Install-VSExtensions.ps1", + "${path.root}/../scripts/build/Install-AzureCli.ps1", + "${path.root}/../scripts/build/Install-AzureDevOpsCli.ps1", + "${path.root}/../scripts/build/Install-ChocolateyPackages.ps1", + "${path.root}/../scripts/build/Install-CMake.ps1", + "${path.root}/../scripts/build/Install-Ninja.ps1", + "${path.root}/../scripts/build/Install-JavaTools.ps1", + "${path.root}/../scripts/build/Install-Kotlin.ps1", + "${path.root}/../scripts/build/Install-OpenSSL.ps1", + "${path.root}/../scripts/build/Install-LLVM.ps1" + ] + } + + provisioner "windows-restart" { + restart_timeout = "10m" + } + + provisioner "powershell" { + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-ActionsCache.ps1", + "${path.root}/../scripts/build/Install-Ruby.ps1", + "${path.root}/../scripts/build/Install-Toolset.ps1", + "${path.root}/../scripts/build/Configure-Toolset.ps1", + "${path.root}/../scripts/build/Install-NodeJS.ps1", + "${path.root}/../scripts/build/Install-PowershellAzModules.ps1", + "${path.root}/../scripts/build/Install-Pipx.ps1", + "${path.root}/../scripts/build/Install-Git.ps1", + "${path.root}/../scripts/build/Install-GitHub-CLI.ps1", + "${path.root}/../scripts/build/Install-PHP.ps1", + "${path.root}/../scripts/build/Install-Rust.ps1", + "${path.root}/../scripts/build/Install-Sbt.ps1", + "${path.root}/../scripts/build/Install-Chrome.ps1", + "${path.root}/../scripts/build/Install-EdgeDriver.ps1", + "${path.root}/../scripts/build/Install-Firefox.ps1", + "${path.root}/../scripts/build/Install-Selenium.ps1", + "${path.root}/../scripts/build/Install-IEWebDriver.ps1", + "${path.root}/../scripts/build/Install-Apache.ps1", + "${path.root}/../scripts/build/Install-Nginx.ps1", + "${path.root}/../scripts/build/Install-WinAppDriver.ps1", + "${path.root}/../scripts/build/Install-R.ps1", + "${path.root}/../scripts/build/Install-AWSTools.ps1", + "${path.root}/../scripts/build/Install-DACFx.ps1", + "${path.root}/../scripts/build/Install-MysqlCli.ps1", + "${path.root}/../scripts/build/Install-SQLPowerShellTools.ps1", + "${path.root}/../scripts/build/Install-SQLOLEDBDriver.ps1", + "${path.root}/../scripts/build/Install-DotnetSDK.ps1", + "${path.root}/../scripts/build/Install-Mingw64.ps1", + "${path.root}/../scripts/build/Install-Stack.ps1", + "${path.root}/../scripts/build/Install-AzureCosmosDbEmulator.ps1", + "${path.root}/../scripts/build/Install-Mercurial.ps1", + "${path.root}/../scripts/build/Install-NSIS.ps1", + "${path.root}/../scripts/build/Install-Vcpkg.ps1", + "${path.root}/../scripts/build/Install-Bazel.ps1", + "${path.root}/../scripts/build/Install-AliyunCli.ps1", + "${path.root}/../scripts/build/Install-RootCA.ps1", + "${path.root}/../scripts/build/Install-CodeQLBundle.ps1", + "${path.root}/../scripts/build/Configure-Diagnostics.ps1" + ] + } + + provisioner "powershell" { + elevated_password = "${var.install_password}" + elevated_user = "${var.install_user}" + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-WindowsUpdates.ps1", + "${path.root}/../scripts/build/Configure-DynamicPort.ps1", + "${path.root}/../scripts/build/Configure-GDIProcessHandleQuota.ps1", + "${path.root}/../scripts/build/Configure-Shell.ps1", + "${path.root}/../scripts/build/Configure-DeveloperMode.ps1" + ] + } + + # Scheduled tasks spawned when using elevated_user provisioners requires the user to log in interactively on Windows Desktop + # Remove AutoAdminLogon after all elevated_user tasks are completed and reboot + provisioner "powershell" { + inline = [ + "Remove-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name AutoAdminLogon", + "Remove-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name DefaultUsername", + "Remove-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name DefaultPassword", + ] + } + + provisioner "windows-restart" { + check_registry = true + restart_check_command = "powershell -command \"& {if ((-not (Get-Process TiWorker.exe -ErrorAction SilentlyContinue)) -and (-not [System.Environment]::HasShutdownStarted) ) { Write-Output 'Restart complete' }}\"" + restart_timeout = "30m" + } + + provisioner "powershell" { + pause_before = "2m0s" + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-WindowsUpdatesAfterReboot.ps1", + "${path.root}/../scripts/build/Invoke-Cleanup.ps1", + "${path.root}/../scripts/tests/RunAll-Tests.ps1" + ] + } + + provisioner "powershell" { + inline = ["if (-not (Test-Path ${var.image_folder}\\tests\\testResults.xml)) { throw '${var.image_folder}\\tests\\testResults.xml not found' }"] + } + + provisioner "powershell" { + environment_vars = ["IMAGE_VERSION=${var.image_version}", "IMAGE_FOLDER=${var.image_folder}"] + inline = ["pwsh -File '${var.image_folder}\\SoftwareReport\\Generate-SoftwareReport.ps1'"] + } + + provisioner "powershell" { + inline = ["if (-not (Test-Path C:\\software-report.md)) { throw 'C:\\software-report.md not found' }", "if (-not (Test-Path C:\\software-report.json)) { throw 'C:\\software-report.json not found' }"] + } + + provisioner "file" { + destination = "${path.root}/../Windows11-Arm64-Readme.md" + direction = "download" + source = "C:\\software-report.md" + } + + provisioner "file" { + destination = "${path.root}/../software-report.json" + direction = "download" + source = "C:\\software-report.json" + } + + provisioner "powershell" { + environment_vars = ["INSTALL_USER=${var.install_user}"] + scripts = [ + "${path.root}/../scripts/build/Install-NativeImages.ps1", + "${path.root}/../scripts/build/Configure-System.ps1", + "${path.root}/../scripts/build/Configure-User.ps1", + "${path.root}/../scripts/build/Post-Build-Validation.ps1" + ] + skip_clean = true + } + + provisioner "windows-restart" { + restart_timeout = "10m" + } + + provisioner "powershell" { + inline = [ + "if( Test-Path $env:SystemRoot\\System32\\Sysprep\\unattend.xml ){ rm $env:SystemRoot\\System32\\Sysprep\\unattend.xml -Force}", + "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /mode:vm /quiet /quit", + "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10 } else { break } }" + ] + } + +} diff --git a/images/windows/templates/build.windows-11-vs2026-arm64.pkr.hcl b/images/windows/templates/build.windows-11-vs2026-arm64.pkr.hcl new file mode 100644 index 0000000000..f0f3d8e8fe --- /dev/null +++ b/images/windows/templates/build.windows-11-vs2026-arm64.pkr.hcl @@ -0,0 +1,282 @@ +build { + sources = ["source.azure-arm.image"] + name = "windows-11-vs2026-arm64" + + provisioner "powershell" { + inline = [ + "New-Item -Path ${var.image_folder} -ItemType Directory -Force", + "New-Item -Path ${var.temp_dir} -ItemType Directory -Force" + ] + } + + provisioner "file" { + destination = "${var.image_folder}\\" + sources = [ + "${path.root}/../assets", + "${path.root}/../scripts", + "${path.root}/../toolsets" + ] + } + + provisioner "file" { + destination = "${var.image_folder}\\scripts\\docs-gen\\" + source = "${path.root}/../../../helpers/software-report-base" + } + + provisioner "powershell" { + inline = [ + "Move-Item '${var.image_folder}\\assets\\post-gen' 'C:\\post-generation'", + "Remove-Item -Recurse '${var.image_folder}\\assets'", + "Move-Item '${var.image_folder}\\scripts\\docs-gen' '${var.image_folder}\\SoftwareReport'", + "Move-Item '${var.image_folder}\\scripts\\helpers' '${var.helper_script_folder}\\ImageHelpers'", + "New-Item -Type Directory -Path '${var.helper_script_folder}\\TestsHelpers\\'", + "Move-Item '${var.image_folder}\\scripts\\tests\\Helpers.psm1' '${var.helper_script_folder}\\TestsHelpers\\TestsHelpers.psm1'", + "Move-Item '${var.image_folder}\\scripts\\tests' '${var.image_folder}\\tests'", + "Remove-Item -Recurse '${var.image_folder}\\scripts'", + "Move-Item '${var.image_folder}\\toolsets\\toolset-win-11-vs2026-arm64.json' '${var.image_folder}\\toolset.json'", + "Remove-Item -Recurse '${var.image_folder}\\toolsets'" + ] + } + + provisioner "windows-shell" { + inline = [ + "net user ${var.install_user} ${var.install_password} /add /passwordchg:no /passwordreq:yes /active:yes /Y", + "net localgroup Administrators ${var.install_user} /add", + "winrm set winrm/config/service/auth @{Basic=\"true\"}", + "winrm get winrm/config/service/auth" + ] + } + + provisioner "powershell" { + inline = ["if (-not ((net localgroup Administrators) -contains '${var.install_user}')) { exit 1 }"] + } + + # Scheduled tasks spawned when using elevated_user provisioners requires the user to log in interactively on Windows Desktop + # Set AutoAdminLogon for elevated_user and reboot as a workaround + provisioner "powershell" { + inline = [ + "Set-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name AutoAdminLogon -Value 1 -type String", + "Set-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name DefaultUsername -Value \"${var.install_user}\" -type String", + "Set-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name DefaultPassword -Value \"${var.install_password}\" -type String", + ] + } + + provisioner "windows-restart" { + check_registry = true + restart_timeout = "10m" + } + + provisioner "powershell" { + elevated_password = "${var.install_password}" + elevated_user = "${var.install_user}" + inline = ["bcdedit.exe /set TESTSIGNING ON"] + } + + provisioner "powershell" { + environment_vars = ["IMAGE_VERSION=${var.image_version}", "IMAGE_OS=${var.image_os}", "AGENT_TOOLSDIRECTORY=${var.agent_tools_directory}", "IMAGEDATA_FILE=${var.imagedata_file}", "IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}", "INSTALL_VS_2026=true"] + execution_policy = "unrestricted" + scripts = [ + "${path.root}/../scripts/build/Configure-WindowsDefender.ps1", + "${path.root}/../scripts/build/Configure-PowerShell.ps1", + "${path.root}/../scripts/build/Install-PowerShellModules.ps1", + "${path.root}/../scripts/build/Install-WindowsFeatures.ps1", + "${path.root}/../scripts/build/Install-Chocolatey.ps1", + "${path.root}/../scripts/build/Configure-BaseImage.ps1", + "${path.root}/../scripts/build/Configure-ImageDataFile.ps1", + "${path.root}/../scripts/build/Configure-SystemEnvironment.ps1", + "${path.root}/../scripts/build/Configure-DotnetSecureChannel.ps1" + ] + } + + provisioner "windows-restart" { + check_registry = true + restart_check_command = "powershell -command \"& {while ( (Get-WindowsOptionalFeature -Online -FeatureName Containers -ErrorAction SilentlyContinue).State -ne 'Enabled' ) { Start-Sleep 30; Write-Output 'InProgress' }}\"" + restart_timeout = "10m" + } + + provisioner "powershell" { + inline = ["Set-Service -Name wlansvc -StartupType Manual", "if ($(Get-Service -Name wlansvc).Status -eq 'Running') { Stop-Service -Name wlansvc}"] + } + + provisioner "powershell" { + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-PowershellCore.ps1", + "${path.root}/../scripts/build/Install-WebPlatformInstaller.ps1" + ] + } + + provisioner "windows-restart" { + restart_timeout = "30m" + } + + provisioner "powershell" { + elevated_password = "${var.install_password}" + elevated_user = "${var.install_user}" + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}", "INSTALL_VS_2026=true"] + scripts = [ + "${path.root}/../scripts/build/Install-VisualStudio.ps1", + "${path.root}/../scripts/build/Install-KubernetesTools.ps1" + ] + valid_exit_codes = [0, 3010] + } + + provisioner "windows-restart" { + check_registry = true + restart_timeout = "10m" + } + + provisioner "powershell" { + pause_before = "2m0s" + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-WDK.ps1", + "${path.root}/../scripts/build/Install-VSExtensions.ps1", + "${path.root}/../scripts/build/Install-AzureCli.ps1", + "${path.root}/../scripts/build/Install-AzureDevOpsCli.ps1", + "${path.root}/../scripts/build/Install-ChocolateyPackages.ps1", + "${path.root}/../scripts/build/Install-CMake.ps1", + "${path.root}/../scripts/build/Install-Ninja.ps1", + "${path.root}/../scripts/build/Install-JavaTools.ps1", + "${path.root}/../scripts/build/Install-Kotlin.ps1", + "${path.root}/../scripts/build/Install-OpenSSL.ps1", + "${path.root}/../scripts/build/Install-LLVM.ps1" + ] + } + + provisioner "windows-restart" { + restart_timeout = "10m" + } + + provisioner "powershell" { + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-ActionsCache.ps1", + "${path.root}/../scripts/build/Install-Ruby.ps1", + "${path.root}/../scripts/build/Install-Toolset.ps1", + "${path.root}/../scripts/build/Configure-Toolset.ps1", + "${path.root}/../scripts/build/Install-NodeJS.ps1", + "${path.root}/../scripts/build/Install-PowershellAzModules.ps1", + "${path.root}/../scripts/build/Install-Pipx.ps1", + "${path.root}/../scripts/build/Install-Git.ps1", + "${path.root}/../scripts/build/Install-GitHub-CLI.ps1", + "${path.root}/../scripts/build/Install-PHP.ps1", + "${path.root}/../scripts/build/Install-Rust.ps1", + "${path.root}/../scripts/build/Install-Sbt.ps1", + "${path.root}/../scripts/build/Install-Chrome.ps1", + "${path.root}/../scripts/build/Install-EdgeDriver.ps1", + "${path.root}/../scripts/build/Install-Firefox.ps1", + "${path.root}/../scripts/build/Install-Selenium.ps1", + "${path.root}/../scripts/build/Install-IEWebDriver.ps1", + "${path.root}/../scripts/build/Install-Apache.ps1", + "${path.root}/../scripts/build/Install-Nginx.ps1", + "${path.root}/../scripts/build/Install-WinAppDriver.ps1", + "${path.root}/../scripts/build/Install-R.ps1", + "${path.root}/../scripts/build/Install-AWSTools.ps1", + "${path.root}/../scripts/build/Install-DACFx.ps1", + "${path.root}/../scripts/build/Install-MysqlCli.ps1", + "${path.root}/../scripts/build/Install-SQLPowerShellTools.ps1", + "${path.root}/../scripts/build/Install-SQLOLEDBDriver.ps1", + "${path.root}/../scripts/build/Install-DotnetSDK.ps1", + "${path.root}/../scripts/build/Install-Mingw64.ps1", + "${path.root}/../scripts/build/Install-Stack.ps1", + "${path.root}/../scripts/build/Install-AzureCosmosDbEmulator.ps1", + "${path.root}/../scripts/build/Install-Mercurial.ps1", + "${path.root}/../scripts/build/Install-NSIS.ps1", + "${path.root}/../scripts/build/Install-Vcpkg.ps1", + "${path.root}/../scripts/build/Install-Bazel.ps1", + "${path.root}/../scripts/build/Install-AliyunCli.ps1", + "${path.root}/../scripts/build/Install-RootCA.ps1", + "${path.root}/../scripts/build/Install-CodeQLBundle.ps1", + "${path.root}/../scripts/build/Configure-Diagnostics.ps1" + ] + } + + provisioner "powershell" { + elevated_password = "${var.install_password}" + elevated_user = "${var.install_user}" + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-WindowsUpdates.ps1", + "${path.root}/../scripts/build/Configure-DynamicPort.ps1", + "${path.root}/../scripts/build/Configure-GDIProcessHandleQuota.ps1", + "${path.root}/../scripts/build/Configure-Shell.ps1", + "${path.root}/../scripts/build/Configure-DeveloperMode.ps1" + ] + } + + # Scheduled tasks spawned when using elevated_user provisioners requires the user to log in interactively on Windows Desktop + # Remove AutoAdminLogon after all elevated_user tasks are completed and reboot + provisioner "powershell" { + inline = [ + "Remove-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name AutoAdminLogon", + "Remove-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name DefaultUsername", + "Remove-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon' -Name DefaultPassword", + ] + } + + provisioner "windows-restart" { + check_registry = true + restart_check_command = "powershell -command \"& {if ((-not (Get-Process TiWorker.exe -ErrorAction SilentlyContinue)) -and (-not [System.Environment]::HasShutdownStarted) ) { Write-Output 'Restart complete' }}\"" + restart_timeout = "30m" + } + + provisioner "powershell" { + pause_before = "2m0s" + environment_vars = ["IMAGE_FOLDER=${var.image_folder}", "TEMP_DIR=${var.temp_dir}"] + scripts = [ + "${path.root}/../scripts/build/Install-WindowsUpdatesAfterReboot.ps1", + "${path.root}/../scripts/build/Invoke-Cleanup.ps1", + "${path.root}/../scripts/tests/RunAll-Tests.ps1" + ] + } + + provisioner "powershell" { + inline = ["if (-not (Test-Path ${var.image_folder}\\tests\\testResults.xml)) { throw '${var.image_folder}\\tests\\testResults.xml not found' }"] + } + + provisioner "powershell" { + environment_vars = ["IMAGE_VERSION=${var.image_version}", "IMAGE_FOLDER=${var.image_folder}"] + inline = ["pwsh -File '${var.image_folder}\\SoftwareReport\\Generate-SoftwareReport.ps1'"] + } + + provisioner "powershell" { + inline = ["if (-not (Test-Path C:\\software-report.md)) { throw 'C:\\software-report.md not found' }", "if (-not (Test-Path C:\\software-report.json)) { throw 'C:\\software-report.json not found' }"] + } + + provisioner "file" { + destination = "${path.root}/../Windows11-VS2026-Arm64-Readme.md" + direction = "download" + source = "C:\\software-report.md" + } + + provisioner "file" { + destination = "${path.root}/../software-report.json" + direction = "download" + source = "C:\\software-report.json" + } + + provisioner "powershell" { + environment_vars = ["INSTALL_USER=${var.install_user}"] + scripts = [ + "${path.root}/../scripts/build/Install-NativeImages.ps1", + "${path.root}/../scripts/build/Configure-System.ps1", + "${path.root}/../scripts/build/Configure-User.ps1", + "${path.root}/../scripts/build/Post-Build-Validation.ps1" + ] + skip_clean = true + } + + provisioner "windows-restart" { + restart_timeout = "10m" + } + + provisioner "powershell" { + inline = [ + "if( Test-Path $env:SystemRoot\\System32\\Sysprep\\unattend.xml ){ rm $env:SystemRoot\\System32\\Sysprep\\unattend.xml -Force}", + "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /mode:vm /quiet /quit", + "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10 } else { break } }" + ] + } + +} diff --git a/images/windows/templates/locals.windows.pkr.hcl b/images/windows/templates/locals.windows.pkr.hcl index 6cca76993e..8a5f12993c 100644 --- a/images/windows/templates/locals.windows.pkr.hcl +++ b/images/windows/templates/locals.windows.pkr.hcl @@ -11,6 +11,14 @@ locals { "win25-vs2026" = { source_image_marketplace_sku = "MicrosoftWindowsServer:WindowsServer:2025-Datacenter-g2" os_disk_size_gb = 150 + }, + "win11-arm64" = { + source_image_marketplace_sku = "microsoftwindowsdesktop:windows11preview-arm64:win11-25h2-ent" + os_disk_size_gb = 256 + }, + "win11-vs2026-arm64" = { + source_image_marketplace_sku = "microsoftwindowsdesktop:windows11preview-arm64:win11-25h2-ent" + os_disk_size_gb = 256 } } diff --git a/images/windows/toolsets/toolset-win-11-arm64.json b/images/windows/toolsets/toolset-win-11-arm64.json new file mode 100644 index 0000000000..0a8421cb47 --- /dev/null +++ b/images/windows/toolsets/toolset-win-11-arm64.json @@ -0,0 +1,315 @@ +{ + "toolcache": [ + { + "name": "Ruby", + "arch": "aarch64", + "platform" : "win32", + "versions": [ + "3.4" + ], + "default": "3.4" + }, + { + "name": "Python", + "url" : "https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json", + "arch": "x64", + "platform" : "win32", + "versions": [ + "3.13.*" + ] + }, + { + "name": "Python", + "url" : "https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json", + "arch": "arm64", + "platform" : "win32", + "versions": [ + "3.12.*", + "3.13.*", + "3.14.*" + ], + "default": "3.13.*" + }, + { + "name": "node", + "url" : "https://raw.githubusercontent.com/actions/node-versions/main/versions-manifest.json", + "arch": "arm64", + "platform" : "win32", + "versions": [ + "20.*", + "22.*", + "24.*" + ] + }, + { + "name": "go", + "url" : "https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json", + "arch": "arm64", + "platform" : "win32", + "versions": [ + "1.22.*", + "1.23.*", + "1.24.*", + "1.25.*" + ], + "default": "1.24.*" + } + ], + "powershellModules": [ + { "name": "DockerMsftProvider" }, + { "name": "MarkdownPS" }, + { "name": "Pester" }, + { "name": "PowerShellGet" }, + { "name": "PSScriptAnalyzer" }, + { "name": "PSWindowsUpdate" }, + { "name": "SqlServer" }, + { "name": "VSSetup" }, + { "name": "Microsoft.Graph" }, + { "name": "AWSPowershell" } + ], + "azureModules": [ + { + "name": "az", + "versions": [ + "12.5.0" + ], + "zip_versions": [ + + ] + } + ], + "java": { + "default": "21", + "versions": [ "21", "23" ] + }, + "android": { + "commandline_tools_url": "https://dl.google.com/android/repository/commandlinetools-win-9123335_latest.zip", + "hash": "8A90E6A3DEB2FA13229B2E335EFD07687DCC8A55A3C544DA9F40B41404993E7D", + "platform_min_version": "31", + "build_tools_min_version": "31.0.0", + "extras": [ + "android;m2repository", + "google;m2repository", + "google;google_play_services" + ], + "addons": [], + "additional_tools": [ + "cmake;3.18.1", + "cmake;3.22.1" + ], + "ndk": { + "default": "27", + "versions": [ + "26", "27", "28" + ] + } + }, + "mingw": { + "version": "14.*", + "runtime": "ucrt" + }, + "MsysPackages": { + "msys2": [], + "mingw": [] + }, + "windowsFeatures": [ + { "name": "Containers", "optionalFeature": true }, + { "name": "Microsoft-Windows-Subsystem-Linux", "optionalFeature": true }, + { "name": "VirtualMachinePlatform", "optionalFeature": true }, + { "name": "NetFx4-AdvSrvs", "optionalFeature": true }, + { "name": "Client-ProjFS", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V-All", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V-Tools-All", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V-Hypervisor", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V-Management-PowerShell", "optionalFeature": true } + ], + "visualStudio": { + "version" : "2022", + "subversion" : "17", + "edition" : "Enterprise", + "channel": "release", + "installChannelUri": "", + "workloads": [ + "Component.Dotfuscator", + "Component.Linux.CMake", + "Component.Unreal.Android", + "Component.Xamarin", + "Microsoft.Component.VC.Runtime.UCRTSDK", + "Microsoft.Net.Component.4.7.2.SDK", + "Microsoft.Net.Component.4.7.TargetingPack", + "Microsoft.Net.Component.4.7.2.TargetingPack", + "Microsoft.Net.Component.4.8.1.SDK", + "Microsoft.Net.Component.4.8.1.TargetingPack", + "Microsoft.VisualStudio.Component.AspNet45", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Microsoft.VisualStudio.Component.EntityFramework", + "Microsoft.VisualStudio.Component.DslTools", + "Microsoft.VisualStudio.Component.SQL.SSDT", + "Microsoft.VisualStudio.Component.PortableLibrary", + "Microsoft.VisualStudio.Component.TestTools.CodedUITest", + "Microsoft.VisualStudio.Component.TestTools.WebLoadTest", + "Microsoft.VisualStudio.Component.UWP.VC.ARM64", + "Microsoft.VisualStudio.Component.UWP.VC.ARM64EC", + "Microsoft.VisualStudio.Component.VC.CLI.Support", + "Microsoft.VisualStudio.Component.VC.CMake.Project", + "Microsoft.VisualStudio.Component.VC.DiagnosticTools", + "Microsoft.VisualStudio.Component.VC.Llvm.Clang", + "Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset", + "Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest", + "Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest", + "Microsoft.VisualStudio.Component.VC.Tools.ARM", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64EC", + "Microsoft.VisualStudio.Component.VC.Redist.MSM", + "Microsoft.VisualStudio.Component.VC.Runtimes.ARM.Spectre", + "Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre", + "Microsoft.VisualStudio.Component.VC.Runtimes.ARM64EC.Spectre", + "Microsoft.VisualStudio.Component.VC.MFC.ARM64", + "Microsoft.VisualStudio.Component.VC.MFC.ARM64.Spectre", + "Microsoft.VisualStudio.Component.VC.ATLMFC", + "Microsoft.VisualStudio.Component.VC.ATLMFC.Spectre", + "Microsoft.VisualStudio.Component.VC.ATL", + "Microsoft.VisualStudio.Component.VC.ATL.Spectre", + "Microsoft.VisualStudio.Component.VC.ATL.ARM", + "Microsoft.VisualStudio.Component.VC.ATL.ARM.Spectre", + "Microsoft.VisualStudio.Component.VC.ATL.ARM64", + "Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre", + "Microsoft.VisualStudio.Component.VC.ASAN", + "Microsoft.VisualStudio.Component.Windows10SDK.19041", + "Microsoft.VisualStudio.Component.Windows11SDK.22621", + "Microsoft.VisualStudio.Component.Windows11SDK.26100", + "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Llvm.Clang", + "Microsoft.VisualStudio.ComponentGroup.UWP.VC.v142", + "Microsoft.VisualStudio.ComponentGroup.Web.CloudTools", + "Microsoft.VisualStudio.Workload.ManagedDesktop", + "Microsoft.VisualStudio.Workload.ManagedGame", + "Microsoft.VisualStudio.Workload.NativeCrossPlat", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.VisualStudio.Workload.NativeGame", + "Microsoft.VisualStudio.Workload.NetCrossPlat", + "Microsoft.VisualStudio.Workload.NetWeb", + "Microsoft.VisualStudio.Workload.Node", + "Microsoft.VisualStudio.Workload.Universal", + "Microsoft.VisualStudio.Workload.VisualStudioExtension", + "Component.MDD.Linux", + "Component.Microsoft.Windows.DriverKit", + "wasm.tools", + "Microsoft.Component.MSBuild" + ], + "vsix": [ + "SSIS.MicrosoftDataToolsIntegrationServices", + "VisualStudioClient.MicrosoftVisualStudio2022InstallerProjectsArm64" + ] + }, + "docker": { + "images": [ + "mcr.microsoft.com/windows/servercore:ltsc2022", + "mcr.microsoft.com/windows/nanoserver:ltsc2022", + "mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2022", + "mcr.microsoft.com/dotnet/framework/runtime:4.8-windowsservercore-ltsc2022", + "mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2022" + ], + "components": { + "docker": "26.1.3", + "compose": "2.27.1" + } + }, + "pipx": [ + { + "package": "yamllint", + "cmd": "yamllint --version" + } + ], + "selenium": { + "version": "4" + }, + "npm": { + "global_packages": [ + { "name": "yarn", "test": "yarn --version" }, + { "name": "newman", "test": "newman --version" }, + { "name": "lerna", "test": "lerna --version" }, + { "name": "gulp-cli", "test": "gulp --version" }, + { "name": "grunt-cli", "test": "grunt --version" } + ] + }, + "serviceFabric": { + "runtime": { + "version": "10.1.2493.9590", + "checksum": "09C63A971BACDE338282C73B3C9174BED9AAD53E1D3A1B73D44515852C9C00CF" + }, + "sdk": { + "version": "7.1.2493", + "checksum": "0CB1084156C75CF5075EA91ABA330CF10B58648B8E036C9C2F286805263C497F" + } + }, + "dotnet": { + "versions": [ + "6.0", + "8.0", + "9.0", + "10.0" + ], + "tools": [ + { "name": "nbgv", "test": "nbgv --version", "getversion": "nbgv --version" } + ], + "warmup": false + }, + "choco": { + "common_packages": [ + { "name": "7zip.install" }, + { "name": "aria2" }, + { "name": "azcopy10" }, + { "name": "Bicep" }, + { "name": "innosetup" }, + { "name": "jq" }, + { "name": "NuGet.CommandLine" }, + { "name": "packer" }, + { + "name": "strawberryperl" , + "args": [ "--version", "5.32.1.1" ] + }, + { "name": "pulumi" }, + { "name": "swig" }, + { "name": "vswhere" }, + { + "name": "julia", + "args": [ "--ia", "/DIR=C:\\Julia" ] + }, + { "name": "imagemagick" } + ] + }, + "node": { + "default": "24.*" + }, + "maven": { + "version": "3.9" + }, + "mysql": { + "version": "8.0" + }, + "mongodb": { + "version": "5.0" + }, + "nsis": { + "version": "3.10" + }, + "llvm": { + "version": "20.1.6" + }, + "php": { + "version": "8.4" + }, + "postgresql": { + "version": "14" + }, + "kotlin": { + "version": "latest" + }, + "openssl": { + "version": "3.*" + }, + "pwsh": { + "version": "7.4" + } +} diff --git a/images/windows/toolsets/toolset-win-11-vs2026-arm64.json b/images/windows/toolsets/toolset-win-11-vs2026-arm64.json new file mode 100644 index 0000000000..642ac98df7 --- /dev/null +++ b/images/windows/toolsets/toolset-win-11-vs2026-arm64.json @@ -0,0 +1,307 @@ +{ + "toolcache": [ + { + "name": "Ruby", + "arch": "aarch64", + "platform" : "win32", + "versions": [ + "3.4" + ], + "default": "3.4" + }, + { + "name": "Python", + "url" : "https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json", + "arch": "x64", + "platform" : "win32", + "versions": [ + "3.13.*" + ] + }, + { + "name": "Python", + "url" : "https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json", + "arch": "arm64", + "platform" : "win32", + "versions": [ + "3.12.*", + "3.13.*", + "3.14.*" + ], + "default": "3.13.*" + }, + { + "name": "node", + "url" : "https://raw.githubusercontent.com/actions/node-versions/main/versions-manifest.json", + "arch": "arm64", + "platform" : "win32", + "versions": [ + "20.*", + "22.*", + "24.*" + ] + }, + { + "name": "go", + "url" : "https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json", + "arch": "arm64", + "platform" : "win32", + "versions": [ + "1.22.*", + "1.23.*", + "1.24.*", + "1.25.*" + ], + "default": "1.24.*" + } + ], + "powershellModules": [ + { "name": "DockerMsftProvider" }, + { "name": "MarkdownPS" }, + { "name": "Pester" }, + { "name": "PowerShellGet" }, + { "name": "PSScriptAnalyzer" }, + { "name": "PSWindowsUpdate" }, + { "name": "SqlServer" }, + { "name": "VSSetup" }, + { "name": "Microsoft.Graph" }, + { "name": "AWSPowershell" } + ], + "azureModules": [ + { + "name": "az", + "versions": [ + "12.5.0" + ], + "zip_versions": [ + + ] + } + ], + "java": { + "default": "21", + "versions": [ "21", "23" ] + }, + "android": { + "commandline_tools_url": "https://dl.google.com/android/repository/commandlinetools-win-9123335_latest.zip", + "hash": "8A90E6A3DEB2FA13229B2E335EFD07687DCC8A55A3C544DA9F40B41404993E7D", + "platform_min_version": "31", + "build_tools_min_version": "31.0.0", + "extras": [ + "android;m2repository", + "google;m2repository", + "google;google_play_services" + ], + "addons": [], + "additional_tools": [ + "cmake;3.18.1", + "cmake;3.22.1" + ], + "ndk": { + "default": "27", + "versions": [ + "26", "27", "28" + ] + } + }, + "mingw": { + "version": "14.*", + "runtime": "ucrt" + }, + "MsysPackages": { + "msys2": [], + "mingw": [] + }, + "windowsFeatures": [ + { "name": "Containers", "optionalFeature": true }, + { "name": "Microsoft-Windows-Subsystem-Linux", "optionalFeature": true }, + { "name": "VirtualMachinePlatform", "optionalFeature": true }, + { "name": "NetFx4-AdvSrvs", "optionalFeature": true }, + { "name": "Client-ProjFS", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V-All", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V-Tools-All", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V-Hypervisor", "optionalFeature": true }, + { "name": "Microsoft-Hyper-V-Management-PowerShell", "optionalFeature": true } + ], + "visualStudio": { + "version" : "2026", + "subversion" : "18", + "edition" : "Enterprise", + "channel": "stable", + "installChannelUri": "", + "workloads": [ + "Component.Linux.CMake", + "Component.Unreal.Android", + "Microsoft.Component.VC.Runtime.UCRTSDK", + "Microsoft.Net.Component.4.7.2.SDK", + "Microsoft.Net.Component.4.7.TargetingPack", + "Microsoft.Net.Component.4.7.2.TargetingPack", + "Microsoft.Net.Component.4.8.1.SDK", + "Microsoft.Net.Component.4.8.1.TargetingPack", + "Microsoft.VisualStudio.Component.AspNet45", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Microsoft.VisualStudio.Component.EntityFramework", + "Microsoft.VisualStudio.Component.DslTools", + "Microsoft.VisualStudio.Component.SQL.SSDT", + "Microsoft.VisualStudio.Component.PortableLibrary", + "Microsoft.VisualStudio.Component.UWP.VC.ARM64", + "Microsoft.VisualStudio.Component.UWP.VC.ARM64EC", + "Microsoft.VisualStudio.Component.VC.CLI.Support", + "Microsoft.VisualStudio.Component.VC.CMake.Project", + "Microsoft.VisualStudio.Component.VC.DiagnosticTools", + "Microsoft.VisualStudio.Component.VC.Llvm.Clang", + "Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset", + "Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest", + "Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64EC", + "Microsoft.VisualStudio.Component.VC.Redist.MSM", + "Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre", + "Microsoft.VisualStudio.Component.VC.Runtimes.ARM64EC.Spectre", + "Microsoft.VisualStudio.Component.VC.MFC.ARM64", + "Microsoft.VisualStudio.Component.VC.MFC.ARM64.Spectre", + "Microsoft.VisualStudio.Component.VC.ATLMFC", + "Microsoft.VisualStudio.Component.VC.ATLMFC.Spectre", + "Microsoft.VisualStudio.Component.VC.ATL", + "Microsoft.VisualStudio.Component.VC.ATL.Spectre", + "Microsoft.VisualStudio.Component.VC.ATL.ARM64", + "Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre", + "Microsoft.VisualStudio.Component.VC.ASAN", + "Microsoft.VisualStudio.Component.VC.14.44.17.14.ARM64", + "Microsoft.VisualStudio.Component.Windows11SDK.22621", + "Microsoft.VisualStudio.Component.Windows11SDK.26100", + "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Llvm.Clang", + "Microsoft.VisualStudio.ComponentGroup.UWP.VC.v142", + "Microsoft.VisualStudio.ComponentGroup.Web.CloudTools", + "Microsoft.VisualStudio.Workload.ManagedDesktop", + "Microsoft.VisualStudio.Workload.ManagedGame", + "Microsoft.VisualStudio.Workload.NativeCrossPlat", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.VisualStudio.Workload.NativeGame", + "Microsoft.VisualStudio.Workload.NetCrossPlat", + "Microsoft.VisualStudio.Workload.NetWeb", + "Microsoft.VisualStudio.Workload.Node", + "Microsoft.VisualStudio.Workload.Universal", + "Microsoft.VisualStudio.Workload.VisualStudioExtension", + "Component.MDD.Linux", + "Component.Microsoft.Windows.DriverKit", + "wasm.tools", + "Microsoft.Component.MSBuild" + ], + "vsix": [ + "SSIS.MicrosoftDataToolsIntegrationServices", + "VisualStudioClient.MicrosoftVisualStudio2022InstallerProjectsArm64" + ] + }, + "docker": { + "images": [ + "mcr.microsoft.com/windows/servercore:ltsc2022", + "mcr.microsoft.com/windows/nanoserver:ltsc2022", + "mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2022", + "mcr.microsoft.com/dotnet/framework/runtime:4.8-windowsservercore-ltsc2022", + "mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2022" + ], + "components": { + "docker": "26.1.3", + "compose": "2.27.1" + } + }, + "pipx": [ + { + "package": "yamllint", + "cmd": "yamllint --version" + } + ], + "selenium": { + "version": "4" + }, + "npm": { + "global_packages": [ + { "name": "yarn", "test": "yarn --version" }, + { "name": "newman", "test": "newman --version" }, + { "name": "lerna", "test": "lerna --version" }, + { "name": "gulp-cli", "test": "gulp --version" }, + { "name": "grunt-cli", "test": "grunt --version" } + ] + }, + "serviceFabric": { + "runtime": { + "version": "10.1.2493.9590", + "checksum": "09C63A971BACDE338282C73B3C9174BED9AAD53E1D3A1B73D44515852C9C00CF" + }, + "sdk": { + "version": "7.1.2493", + "checksum": "0CB1084156C75CF5075EA91ABA330CF10B58648B8E036C9C2F286805263C497F" + } + }, + "dotnet": { + "versions": [ + "6.0", + "8.0", + "9.0", + "10.0" + ], + "tools": [ + { "name": "nbgv", "test": "nbgv --version", "getversion": "nbgv --version" } + ], + "warmup": false + }, + "choco": { + "common_packages": [ + { "name": "7zip.install" }, + { "name": "aria2" }, + { "name": "azcopy10" }, + { "name": "Bicep" }, + { "name": "innosetup" }, + { "name": "jq" }, + { "name": "NuGet.CommandLine" }, + { "name": "packer" }, + { + "name": "strawberryperl" , + "args": [ "--version", "5.32.1.1" ] + }, + { "name": "pulumi" }, + { "name": "swig" }, + { "name": "vswhere" }, + { + "name": "julia", + "args": [ "--ia", "/DIR=C:\\Julia" ] + }, + { "name": "imagemagick" } + ] + }, + "node": { + "default": "24.*" + }, + "maven": { + "version": "3.9" + }, + "mysql": { + "version": "8.0" + }, + "mongodb": { + "version": "5.0" + }, + "nsis": { + "version": "3.10" + }, + "llvm": { + "version": "20.1.6" + }, + "php": { + "version": "8.4" + }, + "postgresql": { + "version": "14" + }, + "kotlin": { + "version": "latest" + }, + "openssl": { + "version": "3.*" + }, + "pwsh": { + "version": "7.4" + } +}