Skip to content

Commit d417c72

Browse files
committed
Use conda-forge LLVM on Windows
1 parent abdb945 commit d417c72

10 files changed

Lines changed: 250 additions & 235 deletions

File tree

.github/workflows/julia-release.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,20 @@ jobs:
153153
if: runner.os == 'Windows'
154154
shell: pwsh
155155
run: |
156-
$llvmPrefix = Join-Path $env:USERPROFILE ".pecos\deps\llvm-21.1"
157-
Write-Host "Installing LLVM 21.1 development archive..."
158-
./scripts/ci/install-llvm-21-windows.ps1 -InstallDir $llvmPrefix -Version ${{ env.LLVM_RELEASE_VERSION }}
156+
$llvmRoot = Join-Path $env:USERPROFILE ".pecos\deps\llvm-21.1"
157+
$llvmPrefix = Join-Path $llvmRoot "Library"
158+
Write-Host "Installing conda-forge LLVM 21.1..."
159+
./scripts/ci/install-llvm-21-windows.ps1 -InstallDir $llvmRoot -Version ${{ env.LLVM_RELEASE_VERSION }}
159160
160161
Write-Host "Setting LLVM environment variables..."
161162
$env:PECOS_LLVM = $llvmPrefix
162163
$env:LLVM_SYS_211_PREFIX = $env:PECOS_LLVM
164+
$env:LIBCLANG_PATH = Join-Path $llvmPrefix "bin"
163165
cargo run --locked -p pecos-cli --release -- llvm configure "$env:PECOS_LLVM"
164166
165167
"PECOS_LLVM=$env:PECOS_LLVM" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
166168
"LLVM_SYS_211_PREFIX=$env:LLVM_SYS_211_PREFIX" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
169+
"LIBCLANG_PATH=$env:LIBCLANG_PATH" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
167170
168171
Write-Host "Verifying LLVM installation..."
169172
cargo run --locked -p pecos-cli --release -- llvm check

.github/workflows/python-release.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -281,19 +281,19 @@ jobs:
281281
pipx run abi3audit --strict --report {wheel}
282282
# Windows configuration - CUDA via Jimver/cuda-toolkit (installed before cibuildwheel)
283283
CIBW_ENVIRONMENT_WINDOWS: >
284-
PATH="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\bin;C:\\Users\\runneradmin\\.pecos\\deps\\cmake-${{ env.PECOS_CMAKE_VERSION }}\\bin;$PATH"
285-
LLVM_SYS_211_PREFIX="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1"
286-
LIBCLANG_PATH="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\bin"
284+
PATH="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\Library\\bin;C:\\Users\\runneradmin\\.pecos\\deps\\cmake-${{ env.PECOS_CMAKE_VERSION }}\\bin;$PATH"
285+
LLVM_SYS_211_PREFIX="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\Library"
286+
LIBCLANG_PATH="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\Library\\bin"
287287
CMAKE="C:\\Users\\runneradmin\\.pecos\\deps\\cmake-${{ env.PECOS_CMAKE_VERSION }}\\bin\\cmake.exe"
288288
MATURIN_PEP517_ARGS="--locked --features=extension-module,mwpf"
289289
CIBW_BEFORE_ALL_WINDOWS: >
290-
echo "=== Installing LLVM 21.1 development archive ===" &&
290+
echo "=== Installing conda-forge LLVM 21.1 ===" &&
291291
rustup update &&
292292
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\ci\install-llvm-21-windows.ps1 -InstallDir "C:\Users\runneradmin\.pecos\deps\llvm-21.1" -Version ${{ env.LLVM_RELEASE_VERSION }} &&
293-
cargo run --locked --release -p pecos-cli -- llvm configure "C:\Users\runneradmin\.pecos\deps\llvm-21.1" &&
293+
cargo run --locked --release -p pecos-cli -- llvm configure "C:\Users\runneradmin\.pecos\deps\llvm-21.1\Library" &&
294294
cargo run --locked --release -p pecos-cli -- install cmake --force &&
295295
echo "=== Checking LLVM installation ===" &&
296-
if exist "C:\Users\runneradmin\.pecos\deps\llvm-21.1\bin\llvm-config.exe" (echo LLVM directory exists) else (echo ERROR: LLVM directory not found! && exit /b 1)
296+
if exist "C:\Users\runneradmin\.pecos\deps\llvm-21.1\Library\bin\llvm-config.exe" (echo LLVM directory exists) else (echo ERROR: LLVM directory not found! && exit /b 1)
297297
# Install delvewheel and patch it to ignore ext-ms-win-* API sets
298298
# (delvewheel ignores api-ms-win-* but not ext-ms-win-* which are also Windows API sets)
299299
CIBW_BEFORE_BUILD_WINDOWS: >
@@ -302,7 +302,7 @@ jobs:
302302
# Note: --no-dll excludes Windows system DLLs that should not be bundled
303303
# combase.dll and rmclient.dll are core Windows components that fail when bundled
304304
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >
305-
delvewheel repair -v --add-path "C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\bin" --no-dll "combase.dll;rmclient.dll" -w {dest_dir} {wheel} &&
305+
delvewheel repair -v --add-path "C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\Library\\bin" --no-dll "combase.dll;rmclient.dll" -w {dest_dir} {wheel} &&
306306
pipx run abi3audit --strict --report {wheel}
307307
308308
- name: Upload pecos-rslib wheels
@@ -375,18 +375,18 @@ jobs:
375375
PATH=$HOME/.pecos/bin:$PATH DYLD_LIBRARY_PATH=$HOME/.pecos/deps/llvm-21.1/lib delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} &&
376376
pipx run abi3audit --strict --report {wheel}
377377
CIBW_ENVIRONMENT_WINDOWS: >
378-
PATH="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\bin;$PATH"
379-
LLVM_SYS_211_PREFIX="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1"
380-
LIBCLANG_PATH="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\bin"
378+
PATH="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\Library\\bin;$PATH"
379+
LLVM_SYS_211_PREFIX="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\Library"
380+
LIBCLANG_PATH="C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\Library\\bin"
381381
CIBW_BEFORE_ALL_WINDOWS: >
382382
rustup update &&
383-
if not exist "C:\Users\runneradmin\.pecos\deps\llvm-21.1\bin\llvm-config.exe" (powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\ci\install-llvm-21-windows.ps1 -InstallDir "C:\Users\runneradmin\.pecos\deps\llvm-21.1" -Version ${{ env.LLVM_RELEASE_VERSION }}) else (echo LLVM already installed from pecos-rslib build) &&
384-
cargo run --locked --release -p pecos-cli -- llvm configure "C:\Users\runneradmin\.pecos\deps\llvm-21.1"
383+
if not exist "C:\Users\runneradmin\.pecos\deps\llvm-21.1\Library\bin\llvm-config.exe" (powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\ci\install-llvm-21-windows.ps1 -InstallDir "C:\Users\runneradmin\.pecos\deps\llvm-21.1" -Version ${{ env.LLVM_RELEASE_VERSION }}) else (echo LLVM already installed from pecos-rslib build) &&
384+
cargo run --locked --release -p pecos-cli -- llvm configure "C:\Users\runneradmin\.pecos\deps\llvm-21.1\Library"
385385
CIBW_BEFORE_BUILD_WINDOWS: >
386386
pip install delvewheel &&
387387
python -c "import delvewheel._dll_list as d,inspect,re as r;p=inspect.getfile(d);c=open(p).read();n=chr(10);open(p,'w').write(c.replace(r\"re.compile('api-.*'),\",r\"re.compile('api-.*'),\"+n+r\" re.compile('ext-.*'),\")) if 'ext-.*' not in c else None"
388388
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >
389-
delvewheel repair -v --add-path "C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\bin" --no-dll "combase.dll;rmclient.dll" -w {dest_dir} {wheel} &&
389+
delvewheel repair -v --add-path "C:\\Users\\runneradmin\\.pecos\\deps\\llvm-21.1\\Library\\bin" --no-dll "combase.dll;rmclient.dll" -w {dest_dir} {wheel} &&
390390
pipx run abi3audit --strict --report {wheel}
391391
392392
- name: Upload pecos-rslib-llvm wheels

.github/workflows/rust-test.yml

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -297,23 +297,4 @@ jobs:
297297
shell: bash
298298
run: |
299299
set -euo pipefail
300-
# Windows CI uses the official LLVM development archive, which is
301-
# static-only for MSVC. Keep this lane targeted so it still exercises
302-
# LLVM without fanning out many static HUGR linker jobs at once.
303-
cargo test --locked --workspace --release \
304-
--exclude pecos-rslib \
305-
--exclude pecos-rslib-cuda \
306-
--exclude pecos-julia-ffi \
307-
--exclude pecos-go-ffi \
308-
--exclude pecos-rslib-exp \
309-
--exclude pecos-rslib-llvm \
310-
--exclude pecos-cuquantum \
311-
--exclude pecos-cli \
312-
--exclude pecos-decoders \
313-
--exclude pecos-gpu-sims \
314-
--exclude pecos-hugr-qis \
315-
--exclude pecos-llvm
316-
cargo test --locked -p pecos-cli --features=runtime --release
317-
cargo test --locked -p pecos-llvm --release
318-
cargo test --locked -p pecos-qis --no-default-features --features=llvm --release
319-
cargo test --locked -p pecos-hugr-qis --release
300+
cargo run --locked -p pecos-cli --release -- rust test

Justfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ ci-env: _msvc-bootstrap
7171
{{pecos}} llvm configure "$(brew --prefix llvm@21)"
7272
;;
7373
Windows*|MINGW*|MSYS*|CYGWIN*)
74-
LLVM_PREFIX="${USERPROFILE:-$HOME}\\.pecos\\deps\\llvm-21.1"
75-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/ci/install-llvm-21-windows.ps1 -InstallDir "$LLVM_PREFIX" -Version "$LLVM_RELEASE_VERSION"
74+
LLVM_ENV_ROOT="${USERPROFILE:-$HOME}\\.pecos\\deps\\llvm-21.1"
75+
LLVM_PREFIX="${LLVM_ENV_ROOT}\\Library"
76+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/ci/install-llvm-21-windows.ps1 -InstallDir "$LLVM_ENV_ROOT" -Version "$LLVM_RELEASE_VERSION"
7677
{{pecos}} llvm configure "$LLVM_PREFIX"
7778
;;
7879
*)

crates/pecos-build/src/llvm.rs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ pub fn is_required_llvm_version(version: &str) -> bool {
6262
pub fn find_llvm(repo_root: Option<PathBuf>) -> Option<PathBuf> {
6363
// 1. Check versioned deps path: ~/.pecos/deps/llvm-{version}/
6464
if let Ok(deps_llvm) = crate::home::get_llvm_dir_path()
65-
&& is_valid_llvm(&deps_llvm)
65+
&& let Some(llvm_prefix) = valid_llvm_prefix(&deps_llvm)
6666
{
67-
return Some(deps_llvm);
67+
return Some(llvm_prefix);
6868
}
6969

7070
// 2. Check legacy top-level path: ~/.pecos/llvm/
@@ -74,31 +74,47 @@ pub fn find_llvm(repo_root: Option<PathBuf>) -> Option<PathBuf> {
7474
#[cfg(target_os = "windows")]
7575
{
7676
let user_llvm_new = pecos_dir.join(format!("LLVM-{REQUIRED_VERSION}"));
77-
if is_valid_llvm(&user_llvm_new) {
78-
crate::home::print_legacy_warning("LLVM", &user_llvm_new);
79-
return Some(user_llvm_new);
77+
if let Some(llvm_prefix) = valid_llvm_prefix(&user_llvm_new) {
78+
crate::home::print_legacy_warning("LLVM", &llvm_prefix);
79+
return Some(llvm_prefix);
8080
}
8181
}
8282

8383
let user_llvm_legacy = pecos_dir.join("llvm");
84-
if is_valid_llvm(&user_llvm_legacy) {
85-
crate::home::print_legacy_warning("LLVM", &user_llvm_legacy);
86-
return Some(user_llvm_legacy);
84+
if let Some(llvm_prefix) = valid_llvm_prefix(&user_llvm_legacy) {
85+
crate::home::print_legacy_warning("LLVM", &llvm_prefix);
86+
return Some(llvm_prefix);
8787
}
8888
}
8989

9090
// 3. Check for project-local LLVM
9191
if let Some(root) = repo_root {
9292
let local_llvm = root.join("llvm");
93-
if is_valid_llvm(&local_llvm) {
94-
return Some(local_llvm);
93+
if let Some(llvm_prefix) = valid_llvm_prefix(&local_llvm) {
94+
return Some(llvm_prefix);
9595
}
9696
}
9797

9898
// 4. Check system installations
9999
find_system_llvm()
100100
}
101101

102+
fn valid_llvm_prefix(path: &Path) -> Option<PathBuf> {
103+
if is_valid_llvm(path) {
104+
return Some(path.to_path_buf());
105+
}
106+
107+
#[cfg(target_os = "windows")]
108+
{
109+
let conda_library_prefix = path.join("Library");
110+
if is_valid_llvm(&conda_library_prefix) {
111+
return Some(conda_library_prefix);
112+
}
113+
}
114+
115+
None
116+
}
117+
102118
/// Find the LLVM installation Cargo should use for this project.
103119
///
104120
/// An explicit `.cargo/config.toml` setting takes priority because `cargo`
@@ -405,11 +421,11 @@ pub fn print_llvm_not_found_error() {
405421

406422
#[cfg(target_os = "windows")]
407423
{
408-
eprintln!("Windows MSVC LLVM builds do not provide shared libLLVM.");
409-
eprintln!("Use WSL2/Linux for the full HUGR test lane, or configure a full");
410-
eprintln!("LLVM 21 package for targeted static LLVM builds:");
424+
eprintln!("The official Windows LLVM installer is not sufficient for PECOS.");
425+
eprintln!("Use scripts\\ci\\install-llvm-21-windows.ps1 for the conda-forge");
426+
eprintln!("LLVM 21.1 toolchain, then configure its Library prefix:");
411427
eprintln!();
412-
eprintln!(" {cmd} llvm configure C:\\path\\to\\llvm");
428+
eprintln!(" {cmd} llvm configure %USERPROFILE%\\.pecos\\deps\\llvm-21.1\\Library");
413429
eprintln!();
414430
}
415431

crates/pecos-build/src/llvm/installer.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ pub fn managed_install_unavailable_reason() -> Option<&'static str> {
3737
#[cfg(target_os = "windows")]
3838
{
3939
Some(
40-
"PECOS-managed shared LLVM is not available on Windows MSVC because \
41-
LLVM does not provide the libLLVM shared-library target there. Use \
42-
WSL2/Linux for the full HUGR test lane, or configure a full LLVM 21 \
43-
package for targeted static LLVM builds with `pecos llvm configure \
44-
C:\\path\\to\\llvm`.",
40+
"PECOS-managed LLVM is not implemented in the CLI on Windows yet. \
41+
Use `scripts\\ci\\install-llvm-21-windows.ps1` to install the \
42+
conda-forge LLVM 21.1 toolchain under `%USERPROFILE%\\.pecos\\deps`, \
43+
then run `pecos llvm configure \
44+
%USERPROFILE%\\.pecos\\deps\\llvm-21.1\\Library`, or configure \
45+
your own full LLVM 21.1 install.",
4546
)
4647
}
4748

docs/development/dev-tools.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ large toolchain install. `pecos install llvm` prints what it is about to install
121121
and asks for confirmation before downloading.
122122

123123
On macOS, install Homebrew LLVM 21 (`brew install llvm@21`) and run
124-
`pecos llvm configure`. On native Windows MSVC, LLVM does not provide shared
125-
`libLLVM`; use WSL2/Linux for the full HUGR test lane, or configure a full LLVM
126-
development package for targeted static builds.
124+
`pecos llvm configure`. On native Windows MSVC, use
125+
`scripts\ci\install-llvm-21-windows.ps1` to install the conda-forge LLVM 21.1
126+
toolchain, then configure `~\.pecos\deps\llvm-21.1\Library`.
127127

128128
`pecos rust test` requires shared LLVM for the workspace HUGR test lane. LLVM
129129
21.1 static test links can use multiple GB of RAM each, so PECOS fails early
@@ -231,8 +231,8 @@ cargo build -p pecos --features llvm
231231
```
232232

233233
On macOS use `brew install llvm@21 && pecos llvm configure`. On native Windows
234-
MSVC, use WSL2/Linux for the full HUGR test lane or configure a full LLVM 21
235-
package for targeted static builds.
234+
MSVC, use `scripts\ci\install-llvm-21-windows.ps1` and configure
235+
`~\.pecos\deps\llvm-21.1\Library`.
236236

237237
Or using Justfile:
238238
```bash

docs/user-guide/llvm-setup.md

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ The `install` command automatically:
4242
This is the **recommended approach** where PECOS can provide a verified shared
4343
LLVM package. On Debian/Ubuntu-compatible Linux distributions, PECOS downloads
4444
the apt.llvm.org LLVM 21 packages into `~/.pecos/deps/llvm-21.1/` without using
45-
`sudo`. On macOS, use Homebrew for LLVM 21. On Windows MSVC, LLVM does not
46-
provide the shared `libLLVM` target PECOS requires for the full workspace HUGR
47-
test lane; use WSL2/Linux for that lane, or configure a full LLVM package for
48-
targeted static LLVM builds.
45+
`sudo`. On macOS, use Homebrew for LLVM 21. On Windows MSVC, use the
46+
conda-forge helper in the Windows section below; it installs a full LLVM
47+
development environment under `~/.pecos/deps/llvm-21.1/` and configures
48+
`~/.pecos/deps/llvm-21.1/Library` as the LLVM prefix.
4949

5050
This is a developer toolchain install: the CLI prints the install size/behavior
5151
and asks for confirmation before downloading. Use `--yes` to accept the prompt
@@ -92,11 +92,17 @@ Install LLVM 21.1 using your system's package manager, then configure PECOS:
9292

9393
=== "Windows"
9494
!!! warning "Windows LLVM Requirement"
95-
The official LLVM Windows installer (`LLVM-*.exe`) is **toolchain-only** and lacks required development files (`llvm-config.exe` and headers). LLVM's MSVC builds also do not provide shared `libLLVM`, so `pecos rust test` / `just dev` with the full HUGR test lane is not supported on native Windows.
95+
The official LLVM Windows installer (`LLVM-*.exe`) is **toolchain-only** and lacks required development files (`llvm-config.exe`, headers, and `libclang.dll`). Use a full LLVM development package built for the MSVC dynamic runtime.
9696

97-
**Recommended for full development tests:** Use WSL2/Linux and Option 1 above.
97+
**Recommended for full development tests:** Use the PECOS conda-forge helper:
9898

99-
**Alternative for targeted static LLVM builds:** Download a full development package from:
99+
```powershell
100+
.\scripts\ci\install-llvm-21-windows.ps1 -InstallDir "$env:USERPROFILE\.pecos\deps\llvm-21.1"
101+
cargo run -p pecos-cli -- llvm configure "$env:USERPROFILE\.pecos\deps\llvm-21.1\Library"
102+
cargo build --features llvm
103+
```
104+
105+
**Alternative:** Configure another full LLVM 21.1 development package that includes `llvm-config.exe`, headers, static MSVC libraries built against the dynamic runtime, and `libclang.dll`.
100106

101107
- [bitgate/llvm-windows-full-builds](https://github.com/bitgate/llvm-windows-full-builds) (recommended)
102108
- [vovkos/llvm-package-windows](https://github.com/vovkos/llvm-package-windows)
@@ -297,13 +303,15 @@ this order:
297303

298304
**Windows:**
299305

300-
- Native Windows LLVM is static-only for PECOS's purposes
301-
- Use WSL2/Linux for the full HUGR test lane
302-
- For targeted static LLVM builds, configure a full development package with `pecos llvm configure C:\path\to\llvm`
306+
- The official LLVM installer is not sufficient for PECOS development builds
307+
- Use `scripts\ci\install-llvm-21-windows.ps1` for the conda-forge LLVM 21.1 toolchain
308+
- Configure `~\.pecos\deps\llvm-21.1\Library`, not the conda environment root
303309

304310
### Security
305311

306-
All downloaded LLVM packages are verified with SHA256 checksums to ensure integrity.
312+
Linux managed packages are checked against apt metadata hashes. Windows helper
313+
packages are installed by micromamba from conda-forge, using conda package
314+
metadata and checksums.
307315

308316
## Troubleshooting
309317

0 commit comments

Comments
 (0)