Skip to content

Add install/install.ps1, and pin the Windows dependency provisioner - #190

Closed
mmelnich wants to merge 1 commit into
randblas-install-shfrom
randblas-install-ps1
Closed

Add install/install.ps1, and pin the Windows dependency provisioner#190
mmelnich wants to merge 1 commit into
randblas-install-shfrom
randblas-install-ps1

Conversation

@mmelnich

Copy link
Copy Markdown
Contributor

Problem

RandBLAS has no Windows installer, and its Windows dependency provisioner has three reproducibility holes.

No installer. setup.ps1 provisions dependencies for CI but is not a user-facing installer: no project layout, no RandBLAS build, no verification, no toolchain checking.

No toolchain guard. This is the one that actually bites people. "Developer PowerShell for VS 2022" and "Developer Command Prompt for VS 2022" both default to an x86 toolchain, and an x86 linker cannot use the x64 import libraries every BLAS backend here ships. The failure surfaces three layers down as BLAS++ reporting BLAS library not found, which blames the libraries when the compiler is at fault. Shell bitness is not a usable signal either — the Developer Command Prompt is a 64-bit process that still selects x86 tools. This is exactly how the equivalent RandLAPACK failure was misdiagnosed.

Unpinned sources. Clone-Head took a branch name and returned early whenever the destination merely existed. So a branch tip could move between runs, and changing a ref was a silent no-op for anyone who already had the directory. Random123 was fetched at its default branch with no pin at all.

Personal forks. BLAS++ and LAPACK++ came from RaphaelArkadyMeyerNYU/*, carrying one-line MSVC fixes. Both merged upstream on 2026-08-06.

What this PR does

  1. install/install.ps1 — same RandNLA-project layout as install.sh, same RANDNLA_PROJECT_DIR precedence, same post-install examples offer. -ModifyEnvironment persists RANDNLA_PROJECT_DIR at User scope, the Windows equivalent of --modify-rc, and is opt-in.

  2. toolchain-arch.ps1, ported from RandLAPACK: reads VSCMD_ARG_TGT_ARCH, then the bin\Host<host>\<target>\ layout convention, then cl.exe's banner. Three signals because a missed detection fails open, which defeats the check; the banner is last because it is localized. x86 and arm64 get different messages — x86 is the wrong shell and a one-command fix, arm64 is genuinely unsupported.

  3. Upstream, pinned sources. BLAS++ 3057185 and LAPACK++ 40b9d0d from icl-utk-edu (the merge commits; the latest release of each, v2025.05.28, predates the fixes), Random123 v1.14.0, GoogleTest v1.18.0. Clone-Pinned fetches exactly one ref and writes a provenance stamp, so reuse is gated on what it is rather than that it exists.

  4. randblas_stage_runtime_dlls() is exported from the installed package. Windows searches an executable's own directory first and PATH last, so a downstream project linking installed RandBLAS had no way to find the BLAS DLLs at run time — the function lived only in the build tree. Found because the installer's own verification step is such a consumer and could not configure without it. This one benefits every Windows consumer, not just the installer.

Verification

On Windows 11, Windows PowerShell 5.1 (not pwsh 7), VS 2022 Build Tools:

Scenario Result
Plain shell, no cl.exe/cmake refused at preflight, naming both and giving the vcvars64 one-liner
Real x86 toolchain (vcvars32.bat, VSCMD_ARG_TGT_ARCH=x86) refused, with the x86-specific explanation
Full x64 install from scratch oneMKL via vcpkg, BLAS++, GoogleTest, RandBLAS — install succeeded
Verification program compiled, linked, staged its DLLs, ran, reported ILP64
Re-run with dependencies cached reused everything

Notes for reviewers

  • Stacked on Add installer scripts for Linux, macOS and Windows #187, which is stacked on CMake: state the real version floor, pin the examples fetch, summarize the configuration #186. Retarget as those merge.
  • Two bugs here were only reachable on a real machine, which is worth noting for how this gets reviewed. $LASTEXITCODE is unset until some native command runs, and Set-StrictMode turns reading an unset variable into an error — so the installer failed on exactly the runs where every dependency was cached and no native command had run yet. And the missing randblas_stage_runtime_dlls export only appears when something consumes the installed package.
  • vcpkg is kept, deliberately. My plan called for replacing it with pinned NuGet as RandLAPACK did, but Windows: fetch oneMKL through vcpkg manifest mode (fixes setup on VS-bundled vcpkg) #185 has just made vcpkg work in manifest mode with a pinned baseline, and ripping that out immediately would be churn. It is worth revisiting: the vcpkg oneMKL path expanded to 6.2 GB on disk during this testing, against roughly 155 MB for RandLAPACK's NuGet fetch. Filed as a follow-up rather than done here.
  • Windows CI for the installer is not added yet; the existing core-windows lanes cover the provisioner changes.

Completes the installer pair. install.ps1 produces the same RandNLA-project
layout as install.sh, honours RANDNLA_PROJECT_DIR with the same precedence, and
delegates dependency provisioning to the setup script CI already uses so there
is one implementation rather than two that drift.

The x64 toolchain guard is the reason this exists in the form it does.
"Developer PowerShell for VS" and "Developer Command Prompt for VS" both
default to an *x86* toolchain, and an x86 linker cannot use the x64 import
libraries every BLAS backend ships. Left unchecked the failure surfaces three
layers down as BLAS++ reporting "BLAS library not found", blaming the
libraries when the compiler is at fault -- which is exactly how this was
diagnosed in RandLAPACK. toolchain-arch.ps1 reads VSCMD_ARG_TGT_ARCH, then the
bin\Host<host>\<target>\ convention, then cl.exe's banner, and refuses x86 and
arm64 with different messages because they need different answers.

Provisioner changes:

* Off personal forks. BLAS++ and LAPACK++ came from
  RaphaelArkadyMeyerNYU/*; both MSVC fixes 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.

* Pinned and provenance-stamped. Clone-Head took a branch name and returned
  early whenever the destination merely existed, so a branch tip could move
  between runs and changing a ref was a silent no-op for anyone who already
  had the directory. Random123 in particular was fetched at the default
  branch, unpinned. Clone-Pinned fetches one ref and records it.

Also exports randblas_stage_runtime_dlls() from the installed package. Windows
searches an executable's own directory first and PATH last, so a downstream
project linking installed RandBLAS could not find the BLAS DLLs at run time --
the function existed only in the build tree. Found because the installer's own
verification step is such a consumer and could not configure without it.

Verified on Windows 11 with Windows PowerShell 5.1 and VS 2022 Build Tools:
missing-prerequisite path, x86 toolchain refused at preflight under a real
vcvars32 environment, and a full x64 install from scratch -- oneMKL through
vcpkg, BLAS++, GoogleTest, RandBLAS -- ending with the verification program
compiling, linking, staging its DLLs and running, reporting ILP64.
@mmelnich

Copy link
Copy Markdown
Contributor Author

Folded into #187 at Riley's request ("please combine PRs 187, 190, and 191 — they have no business landing separately"). The commit is unchanged, now sitting on randblas-install-sh alongside the rest of the installer work. Nothing was dropped: the consolidated branch's tree is byte-identical to the state that was tested and green here.

@mmelnich mmelnich closed this Aug 13, 2026
An error occurred while trying to automatically change base from randblas-install-sh to main August 13, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant