Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 46 additions & 20 deletions .github/actions/setup-randblas-deps-windows/setup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,59 @@ function Find-PackageConfigDirectory {
return $config.Directory.FullName
}

function Clone-Head {
# Fetch exactly one commit or tag, and record where it came from.
#
# This replaces a clone that took a branch name and returned early whenever the
# destination merely existed. Two problems with that: a branch tip moves, so
# two runs of the same script could build different source; and reuse keyed on
# presence means changing a ref is a silent no-op for anyone who already has
# the directory, so the new pin never takes effect. The stamp is needed
# because a shallow fetch of a tag does not keep the tag ref locally, so git
# cannot be asked afterwards whether a tree is at the pin.
function Clone-Pinned {
param(
[Parameter(Mandatory = $true)][string] $Url,
[Parameter(Mandatory = $true)][string] $Destination,
[string] $Branch = ""
[Parameter(Mandatory = $true)][string] $Ref
)

if (Test-Path -LiteralPath $Destination) {
$stampPath = Join-Path $Destination ".randblas-provenance"
$stamp = "$Url@$Ref"
if ((Test-Path -LiteralPath $stampPath) -and
((Get-Content -LiteralPath $stampPath -Raw).Trim() -eq $stamp)) {
Write-Host "Reusing $Destination (already at $Ref)"
return
}

$arguments = @("clone", "--depth", "1")
if ($Branch) {
$arguments += @("--branch", $Branch)
if (Test-Path -LiteralPath $Destination) {
Remove-Item -Recurse -Force -LiteralPath $Destination
}
$arguments += @($Url, $Destination)
Invoke-Checked -Program "git" -Arguments $arguments
New-Item -ItemType Directory -Force -Path $Destination | Out-Null
Invoke-Checked -Program "git" -Arguments @("-C", $Destination, "init", "--quiet")
Invoke-Checked -Program "git" -Arguments @("-C", $Destination, "remote", "add", "origin", $Url)
Invoke-Checked -Program "git" -Arguments @("-C", $Destination, "fetch", "--quiet", "--depth", "1", "origin", $Ref)
Invoke-Checked -Program "git" -Arguments @("-C", $Destination, "checkout", "--quiet", "FETCH_HEAD")
Set-Content -LiteralPath $stampPath -Value $stamp -Encoding ascii
}

#------------------------------------------------------------------ pins ------
# Immutable refs only: a tag or a full commit hash, never a branch. These match
# install/install.sh and the refs RandLAPACK validated, so the two installers
# and CI cannot disagree about what they built.
#
# BLAS++ and LAPACK++ previously came from personal forks carrying one-line
# MSVC fixes. Both merged upstream on 2026-08-06 (icl-utk-edu/blaspp#132,
# icl-utk-edu/lapackpp#87), so both now come from icl-utk-edu, pinned to the
# merge commits: the latest release of each, v2025.05.28, predates the fixes.
$BlasppUrl = "https://github.com/icl-utk-edu/blaspp.git"
$BlasppRef = "30571853f980d3a2a1737124ea4789e025a5e045"
$LapackppUrl = "https://github.com/icl-utk-edu/lapackpp.git"
$LapackppRef = "40b9d0daf29b6f1f3fa58bc3f22bd6cfb2c67fe4"
$Random123Url = "https://github.com/DEShawResearch/Random123.git"
$Random123Ref = "v1.14.0"
$GTestUrl = "https://github.com/google/googletest.git"
$GTestRef = "v1.18.0"

function Export-GitHubValue {
param(
[Parameter(Mandatory = $true)][string] $Name,
Expand Down Expand Up @@ -188,8 +222,7 @@ $gtestVariant = if ($SanitizeAddress) { "googletest-asan" } else { "googletest"
$gtestBuild = Join-Path $DependencyRoot "$gtestVariant-build"
$gtestInstall = Join-Path $DependencyRoot "$gtestVariant-install"
if (-not (Test-Path -LiteralPath (Join-Path $gtestInstall "lib\cmake\GTest\GTestConfig.cmake"))) {
Clone-Head -Url "https://github.com/google/googletest.git" `
-Destination $gtestSource -Branch "v1.17.0"
Clone-Pinned -Url $GTestUrl -Destination $gtestSource -Ref $GTestRef
$gtestArguments = @(
"-S", $gtestSource,
"-B", $gtestBuild,
Expand All @@ -215,8 +248,7 @@ $random123Source = Join-Path $DependencyRoot "Random123"
$random123Install = Join-Path $DependencyRoot "Random123-install"
$random123Include = Join-Path $random123Install "include"
if (-not (Test-Path -LiteralPath (Join-Path $random123Include "Random123\philox.h"))) {
Clone-Head -Url "https://github.com/DEShawResearch/Random123.git" `
-Destination $random123Source
Clone-Pinned -Url $Random123Url -Destination $random123Source -Ref $Random123Ref
New-Item -ItemType Directory -Force -Path $random123Include | Out-Null
Copy-Item -LiteralPath (Join-Path $random123Source "include\Random123") `
-Destination $random123Include -Recurse
Expand All @@ -229,10 +261,7 @@ $blasppConfig = Get-ChildItem -LiteralPath $blasppInstall -Recurse -File `
-Filter "blasppConfig.cmake" -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $blasppConfig) {
Clone-Head `
-Url "https://github.com/RaphaelArkadyMeyerNYU/blaspp.git" `
-Destination $blasppSource `
-Branch "windows-portability"
Clone-Pinned -Url $BlasppUrl -Destination $blasppSource -Ref $BlasppRef
$blasLibraryArgument = ($mklLibraries | ForEach-Object {
Convert-ToCMakePath $_
}) -join ";"
Expand Down Expand Up @@ -267,10 +296,7 @@ if ($InstallLapackpp) {
-Filter "lapackppConfig.cmake" -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $lapackppConfig) {
Clone-Head `
-Url "https://github.com/RaphaelArkadyMeyerNYU/lapackpp.git" `
-Destination $lapackppSource `
-Branch "msvc-compatibility"
Clone-Pinned -Url $LapackppUrl -Destination $lapackppSource -Ref $LapackppRef

Invoke-Checked -Program "cmake" -Arguments @(
"-S", $lapackppSource,
Expand Down
75 changes: 75 additions & 0 deletions .github/scripts/windows/toolchain-arch.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Toolchain architecture detection, shared by install/install.ps1 (user-facing
# preflight) and .github/actions/setup-randlapack-deps-windows/setup.ps1 (which
# also runs standalone in CI). Dot-source it; it defines functions only.
#
# Why this check exists: RandBLAS and every BLAS backend the installer
# provisions are 64-bit, but the "Developer PowerShell for VS" and "Developer
# Command Prompt for VS" Start-menu entries both default to an *x86* toolchain.
# An x86 linker cannot use an x64 import library, and the failure surfaces
# three layers down as BLAS++ reporting "BLAS library not found" -- which
# blames the libraries when the compiler is at fault. Note that the shell's own
# bitness is not a usable signal: the Developer Command Prompt is a 64-bit
# process that still selects x86 tools.

function Get-ClTargetArchitecture {
# Returns the compiler's TARGET architecture, lowercased ("x64", "x86",
# "arm64", "arm"), or "" if it genuinely cannot be determined.
#
# Three independent signals, most reliable first -- the same
# probe-several-things approach Find-OneMklLayout uses, and for the same
# reason: a missed detection here fails *open*, which defeats the check.
# 1. VSCMD_ARG_TGT_ARCH, exported by vcvarsall.bat / VsDevCmd (and so
# by ilammy/msvc-dev-cmd in CI). Never localized.
# 2. The toolset path: MSVC lays cl.exe out as
# ...\bin\Host<host>\<target>\cl.exe, a stable convention.
# 3. The banner, last, for anything matching neither of the above.
# On its own this would be wrong on a localized Visual Studio, where
# the words around the architecture are translated.
if ($env:VSCMD_ARG_TGT_ARCH) { return $env:VSCMD_ARG_TGT_ARCH.ToLowerInvariant() }
$cl = Get-Command "cl.exe" -ErrorAction SilentlyContinue
if (-not $cl) { return "" }
if ($cl.Source -match '\\bin\\Host[^\\]+\\([^\\]+)\\cl\.exe$') {
return $Matches[1].ToLowerInvariant()
}
# Native stderr merged via 2>&1 becomes ErrorRecords, which would throw
# under $ErrorActionPreference = "Stop"; relax it for this one call.
$previous = $ErrorActionPreference
$ErrorActionPreference = "Continue"
try {
$banner = (& $cl.Source 2>&1 | Out-String)
} finally {
$ErrorActionPreference = $previous
}
if ($banner -match '\bfor\s+(x64|x86|ARM64|ARM)\b') { return $Matches[1].ToLowerInvariant() }
return ""
}

function Get-ToolchainArchitectureProblem {
# Returns a description of why $Arch is unusable, or "" if it is fine.
# x86 and ARM64 fail for completely different reasons and deserve
# different advice: x86 means the wrong shell was opened and is a
# one-command fix, ARM64 means the platform is genuinely unsupported.
param([string]$Arch)
if ($Arch -eq "" -or $Arch -eq "x64" -or $Arch -eq "amd64") { return "" }
if ($Arch -eq "x86") {
# Single-quoted: the cmd one-liner contains both double quotes and
# backticks, which are literal here but would need escaping in a
# double-quoted PowerShell string.
$vcvarsHint = 'for /f "usebackq delims=" %i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -property installationPath`) do call "%i\VC\Auxiliary\Build\vcvars64.bat"'
return ("cl.exe targets x86, but RandBLAS and its BLAS backends are 64-bit " +
"(x64).`n" +
" You are in a 32-bit developer shell. 'Developer PowerShell for VS 2022' and " +
"'Developer Command Prompt for VS 2022' both default to x86.`n" +
" Fix: open 'x64 Native Tools Command Prompt for VS 2022' from the Start menu, " +
"or run this in any Command Prompt (any edition or version):`n" +
" $vcvarsHint`n" +
" Then delete the RandNLA-project directory before retrying: dependencies already " +
"configured by the x86 compiler are reused as-is and would keep failing.")
}
return ("cl.exe targets $Arch, which this installer does not support: the Windows build " +
"is x64-only.`n" +
" Intel oneMKL publishes no $Arch build, and the OpenBLAS binaries pinned here are " +
"x64. Supplying an $Arch BLAS/LAPACK through -Backend custom is the only route, and " +
"it is untested.`n" +
" If you meant to build x64, open 'x64 Native Tools Command Prompt for VS 2022'.")
}
Loading
Loading