From cd7552967c00a32d17819d4102e46111c0295803 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 18 Mar 2026 21:11:52 +0200 Subject: [PATCH 01/10] Initial approach --- .github/workflows/build.yml | 9 + .github/workflows/jit.yml | 4 + .github/workflows/reusable-windows-msi.yml | 5 + .github/workflows/reusable-windows.yml | 23 +++ .github/workflows/tail-call.yml | 4 + Modules/cpython-sys/build.rs | 123 ++++++++++++- PCbuild/_base64.vcxproj | 163 ++++++++++++++++++ PCbuild/_base64.vcxproj.filters | 19 ++ PCbuild/build.bat | 2 +- PCbuild/pcbuild.proj | 2 +- PCbuild/pcbuild.sln | 35 ++++ PCbuild/readme.txt | 1 + Tools/msi/freethreaded/freethreaded_files.wxs | 2 +- Tools/msi/lib/lib_files.wxs | 2 +- 14 files changed, 384 insertions(+), 10 deletions(-) create mode 100644 PCbuild/_base64.vcxproj create mode 100644 PCbuild/_base64.vcxproj.filters diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ab9a73627ae1df..32f9aa3d82b56f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -167,6 +167,15 @@ jobs: arch: ${{ matrix.arch }} free-threading: ${{ matrix.free-threading }} + build-windows-system-llvm: + name: Windows (Chocolatey LLVM) + needs: build-context + if: fromJSON(needs.build-context.outputs.run-windows-tests) + uses: ./.github/workflows/reusable-windows.yml + with: + arch: x64 + llvm-from-choco: true + build-windows-msi: # ${{ '' } is a hack to nest jobs under the same sidebar category. name: Windows MSI${{ '' }} # zizmor: ignore[obfuscation] diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 3349eb042425dd..9ff9923d508e66 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -100,6 +100,10 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.11' + - uses: dtolnay/rust-toolchain@1.91.1 + if: runner.os == 'Windows' + with: + targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc # PCbuild downloads LLVM automatically: - name: Windows diff --git a/.github/workflows/reusable-windows-msi.yml b/.github/workflows/reusable-windows-msi.yml index c95e40a38095f9..7095f9e56c0353 100644 --- a/.github/workflows/reusable-windows-msi.yml +++ b/.github/workflows/reusable-windows-msi.yml @@ -22,10 +22,15 @@ jobs: env: ARCH: ${{ inputs.arch }} IncludeFreethreaded: true + IncludeLLVM: true + LIBCLANG_PATH: "${{ github.workspace }}\\externals\\llvm-21.1.4.0\\bin" steps: - uses: actions/checkout@v4 with: persist-credentials: false + - uses: dtolnay/rust-toolchain@1.91.1 + with: + targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - name: Build CPython installer run: ./Tools/msi/build.bat --doc -"${ARCH}" shell: bash diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 0648b770753255..2438ebb73d6da0 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -7,6 +7,11 @@ on: description: CPU architecture required: true type: string + llvm-from-choco: + description: Whether to install LLVM from Chocolatey and expose LIBCLANG_PATH + required: false + type: boolean + default: false free-threading: description: Whether to compile CPython in free-threading mode required: false @@ -29,6 +34,24 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false + - uses: dtolnay/rust-toolchain@1.91.1 + with: + targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + - name: Install LLVM from Chocolatey + if: fromJSON(inputs.llvm-from-choco) + shell: cmd + run: | + choco install llvm --allow-downgrade --no-progress --version 21.1.0 + if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 + echo IncludeLLVM=false>> "%GITHUB_ENV%" + echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" + echo LLVMInstallDir=C:\Program Files\LLVM>> "%GITHUB_ENV%" + - name: Use bundled LLVM + if: ${{ !fromJSON(inputs.llvm-from-choco) }} + shell: cmd + run: | + echo IncludeLLVM=true>> "%GITHUB_ENV%" + echo LIBCLANG_PATH=%GITHUB_WORKSPACE%\externals\llvm-21.1.4.0\bin>> "%GITHUB_ENV%" - name: Register MSVC problem matcher if: inputs.arch != 'Win32' run: echo "::add-matcher::.github/problem-matchers/msvc.json" diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index e99e317182eaa6..93a63899d67288 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -78,6 +78,10 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.11' + - uses: dtolnay/rust-toolchain@1.91.1 + if: runner.os == 'Windows' + with: + targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - name: Native Windows (debug) if: runner.os == 'Windows' && matrix.architecture != 'ARM64' diff --git a/Modules/cpython-sys/build.rs b/Modules/cpython-sys/build.rs index 701a3be550ae0b..e23b114bbbc1c6 100644 --- a/Modules/cpython-sys/build.rs +++ b/Modules/cpython-sys/build.rs @@ -9,14 +9,19 @@ fn main() { .expect("expected Modules/cpython-sys to live under the source tree"); let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); let builddir = env::var("PYTHON_BUILD_DIR").ok(); - if gil_disabled(srcdir, builddir.as_deref()) { + let gil_disabled = gil_disabled(srcdir, builddir.as_deref()); + if gil_disabled { println!("cargo:rustc-cfg=py_gil_disabled"); } println!("cargo::rustc-check-cfg=cfg(py_gil_disabled)"); - generate_c_api_bindings(srcdir, builddir.as_deref(), out_path.as_path()); + generate_c_api_bindings(srcdir, builddir.as_deref(), out_path.as_path(), gil_disabled); } fn gil_disabled(srcdir: &Path, builddir: Option<&str>) -> bool { + if env_var_is_truthy("PY_GIL_DISABLED") { + return true; + } + let mut candidates = Vec::new(); if let Some(build) = builddir { candidates.push(PathBuf::from(build)); @@ -33,12 +38,26 @@ fn gil_disabled(srcdir: &Path, builddir: Option<&str>) -> bool { false } -fn generate_c_api_bindings(srcdir: &Path, builddir: Option<&str>, out_path: &Path) { +fn env_var_is_truthy(name: &str) -> bool { + matches!( + env::var(name).as_deref(), + Ok("1") | Ok("true") | Ok("TRUE") | Ok("yes") | Ok("YES") + ) +} + +fn generate_c_api_bindings(srcdir: &Path, builddir: Option<&str>, out_path: &Path, gil_disabled: bool) { let mut builder = bindgen::Builder::default().header("wrapper.h"); // Suppress all clang warnings (deprecation warnings, etc.) builder = builder.clang_arg("-w"); + if env_var_is_truthy("PY_DEBUG") { + builder = builder.clang_arg("-D_DEBUG"); + } + if gil_disabled { + builder = builder.clang_arg("-DPy_GIL_DISABLED=1"); + } + // Tell clang the correct target triple for cross-compilation. // LLVM_TARGET is the clang/LLVM triple which may differ from the Rust // target (e.g. arm64-apple-macosx vs aarch64-apple-darwin, or @@ -140,8 +159,100 @@ fn generate_c_api_bindings(srcdir: &Path, builddir: Option<&str>, out_path: &Pat .generate() .expect("Unable to generate bindings"); + let dll_name = python_dll_name(srcdir, env_var_is_truthy("PY_DEBUG"), gil_disabled); + let bindings = patch_windows_imported_pointer_globals(bindings.to_string(), &dll_name); + // Write the bindings to the $OUT_DIR/c_api.rs file. - bindings - .write_to_file(out_path.join("c_api.rs")) - .expect("Couldn't write bindings!"); + std::fs::write(out_path.join("c_api.rs"), bindings).expect("Couldn't write bindings!"); +} + +/// Build the Windows DLL base name: `python{major}{minor}[t][_d]`. +fn python_dll_name(srcdir: &Path, debug: bool, gil_disabled: bool) -> String { + let patchlevel = srcdir.join("Include").join("patchlevel.h"); + let contents = + std::fs::read_to_string(&patchlevel).expect("failed to read Include/patchlevel.h"); + + let major = extract_define_int(&contents, "PY_MAJOR_VERSION"); + let minor = extract_define_int(&contents, "PY_MINOR_VERSION"); + + let mut name = format!("python{major}{minor}"); + if gil_disabled { + name.push('t'); + } + if debug { + name.push_str("_d"); + } + name +} + +fn extract_define_int(contents: &str, name: &str) -> u32 { + for line in contents.lines() { + let trimmed = line.trim(); + if let Some(rest) = trimmed.strip_prefix("#define") + && let Some(value) = rest.trim().strip_prefix(name) + && let Ok(n) = value.trim().parse() + { + return n; + } + } + panic!("could not find #define {name} in patchlevel.h"); +} + +fn patch_windows_imported_pointer_globals(bindings: String, dll_name: &str) -> String { + // On Windows/MSVC, exported data is imported through a synthetic + // "__imp_" pointer in the import address table (IAT). A plain + // `extern { pub static X: *mut T; }` linked via import library fails for + // data symbols because the import library only defines `__imp_X`, not `X`. + // + // Using `#[link_name = "__imp_X"]` links successfully but produces a + // single load — returning the *address* of the variable (the IAT slot + // value) rather than the variable's value. C's `__declspec(dllimport)` + // generates two loads to chase the indirection. + // + // The fix: annotate pointer-valued extern statics with `raw-dylib` on + // Windows so Rust generates the import thunk itself and handles the IAT + // indirection correctly — two loads, matching `__declspec(dllimport)`. + let lines: Vec<_> = bindings.lines().collect(); + let mut patched = String::with_capacity(bindings.len()); + let mut index = 0; + + while index < lines.len() { + if lines[index] == "unsafe extern \"C\" {" + && lines.get(index + 1).and_then(|l| parse_pointer_static_decl(l)).is_some() + && lines.get(index + 2).is_some_and(|l| l.trim() == "}") + { + patched.push_str(&format!( + "#[cfg_attr(windows, link(name = \"{dll_name}\", kind = \"raw-dylib\"))]\n" + )); + // Keep the original extern block unchanged. + for i in index..index + 3 { + patched.push_str(lines[i]); + patched.push('\n'); + } + index += 3; + continue; + } + + patched.push_str(lines[index]); + patched.push('\n'); + index += 1; + } + + patched +} + +fn parse_pointer_static_decl(line: &str) -> Option<(&str, bool, &str)> { + let mut decl = line.trim().strip_prefix("pub static ")?; + let is_mut = decl.starts_with("mut "); + if is_mut { + decl = decl.strip_prefix("mut ")?; + } + + let (name, ty) = decl.split_once(':')?; + let ty = ty.trim().strip_suffix(';')?; + if !ty.starts_with('*') { + return None; + } + + Some((name.trim(), is_mut, ty)) } diff --git a/PCbuild/_base64.vcxproj b/PCbuild/_base64.vcxproj new file mode 100644 index 00000000000000..94ab00bbbd16f3 --- /dev/null +++ b/PCbuild/_base64.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + ARM + + + PGInstrument + ARM64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + ARM + + + PGUpdate + ARM64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4} + _base64 + MakeFileProj + + + + + Makefile + NotSet + false + + + + $(PyStdlibPydExt) + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + llvm-21.1.4.0 + dev + release + debug + release + i686-pc-windows-msvc + x86_64-pc-windows-msvc + thumbv7a-pc-windows-msvc + aarch64-pc-windows-msvc + $(IntDir)cargo\ + $(CargoTargetDir.TrimEnd(`\`)) + $(BuildPath.TrimEnd(`\`)) + $(PySourcePath)PC + $(PySourcePath)Cargo.toml + $(LIBCLANG_PATH) + $(ExternalsDir)$(BundledLlvmTag)\bin + $(ExternalsDir)$(BundledLlvmTag)\bin + $(LLVMInstallDir)\bin + $(LLVMInstallDir)\bin + $(VCInstallDir)Tools\Llvm\x64\bin + $(VCInstallDir)Tools\Llvm\x64\bin + $(VCInstallDir)Tools\Llvm\bin + $(VCInstallDir)Tools\Llvm\bin + C:\Program Files\LLVM\bin + C:\Program Files\LLVM\bin + $(OutDir) + $(TargetDir)$(TargetName)$(TargetExt) + $(CargoTargetDirNoSlash)\$(CargoTarget)\$(CargoBuildSubdir)\_base64.dll + $(CargoTargetDirNoSlash)\$(CargoTarget)\$(CargoBuildSubdir)\_base64.pdb + $(OutDir)$(TargetName).pdb + setlocal +if "$(Configuration)"=="Debug" (set "PY_DEBUG=1") else (set "PY_DEBUG=") +if "$(DisableGil)"=="true" (set "PY_GIL_DISABLED=1") else (set "PY_GIL_DISABLED=") +where cargo >NUL 2>NUL || (echo WARNING: cargo was not found on PATH, skipping _base64 & exit /b 0) +if not "$(LibClangPath)"=="" set "LIBCLANG_PATH=$(LibClangPath)" +if "$(LibClangPath)"=="" if not defined LIBCLANG_PATH (echo ERROR: libclang.dll was not found. Install LLVM or the Visual Studio Clang tools and set LIBCLANG_PATH. & exit /b 1) +if not exist "$(CargoTargetDirNoSlash)" mkdir "$(CargoTargetDirNoSlash)" +set "CARGO_TARGET_DIR=$(CargoTargetDirNoSlash)" +set "PYTHON_BUILD_DIR=$(PythonBuildDir)" +set "LIBPYTHON="/LIBPATH:$(BuildPathNoSlash)" "$(PyDllName).lib"" +cargo build --lib --locked --package _base64 --manifest-path "$(CargoWorkspaceManifest)" --profile $(CargoProfile) --target $(CargoTarget) +if errorlevel 1 exit /b 1 +if not exist "$(RustExtensionPath)" (echo ERROR: cargo did not produce $(RustExtensionPath) & exit /b 1) +copy /Y "$(RustExtensionPath)" "$(TargetPath)" >NUL +if errorlevel 1 exit /b 1 +if exist "$(RustExtensionPdb)" copy /Y "$(RustExtensionPdb)" "$(TargetPdb)" >NUL + if exist "$(TargetPath)" del /F /Q "$(TargetPath)" +if exist "$(TargetPdb)" del /F /Q "$(TargetPdb)" +if exist "$(CargoTargetDirNoSlash)" rmdir /S /Q "$(CargoTargetDirNoSlash)" + $(TargetPath) + + + + + + + + + {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} + false + + + + + + + + + + diff --git a/PCbuild/_base64.vcxproj.filters b/PCbuild/_base64.vcxproj.filters new file mode 100644 index 00000000000000..0ba48e32c44518 --- /dev/null +++ b/PCbuild/_base64.vcxproj.filters @@ -0,0 +1,19 @@ + + + + + {86A93473-99A3-4B0B-9B78-4A09FF3A0A6F} + + + + + Rust Sources + + + Rust Sources + + + Rust Sources + + + diff --git a/PCbuild/build.bat b/PCbuild/build.bat index 602357048867d6..43183fe06132cb 100644 --- a/PCbuild/build.bat +++ b/PCbuild/build.bat @@ -111,7 +111,7 @@ if "%IncludeExternals%"=="" set IncludeExternals=true if "%IncludeCTypes%"=="" set IncludeCTypes=true if "%IncludeSSL%"=="" set IncludeSSL=true if "%IncludeTkinter%"=="" set IncludeTkinter=true -if "%UseJIT%" NEQ "true" set IncludeLLVM=false +if "%IncludeLLVM%"=="" if "%UseJIT%"=="true" (set IncludeLLVM=true) else (set IncludeLLVM=false) if "%IncludeExternals%"=="true" call "%dir%get_externals.bat" diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj index 7a5327bf016cea..97a4e952e221b6 100644 --- a/PCbuild/pcbuild.proj +++ b/PCbuild/pcbuild.proj @@ -66,7 +66,7 @@ - + diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln index 7296ea75301157..2f441dd47eb9fe 100644 --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -23,6 +23,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "python.vcxproj", {28B5D777-DDF2-4B6B-B34F-31D938813856} = {28B5D777-DDF2-4B6B-B34F-31D938813856} {36D0C52C-DF4E-45D0-8BC7-E294C3ABC781} = {36D0C52C-DF4E-45D0-8BC7-E294C3ABC781} {384C224A-7474-476E-A01B-750EA7DE918C} = {384C224A-7474-476E-A01B-750EA7DE918C} + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4} = {D7B7A122-80A0-4AFB-9C06-18C29B3178E4} {447F05A8-F581-4CAC-A466-5AC7936E207E} = {447F05A8-F581-4CAC-A466-5AC7936E207E} {4946ECAC-2E69-4BF8-A90A-F5136F5094DF} = {4946ECAC-2E69-4BF8-A90A-F5136F5094DF} {494BAC80-A60C-43A9-99E7-ACB691CE2C4D} = {494BAC80-A60C-43A9-99E7-ACB691CE2C4D} @@ -134,6 +135,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testconsole", "_testconsol EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_asyncio", "_asyncio.vcxproj", "{384C224A-7474-476E-A01B-750EA7DE918C}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_base64", "_base64.vcxproj", "{D7B7A122-80A0-4AFB-9C06-18C29B3178E4}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_zoneinfo", "_zoneinfo.vcxproj", "{FCBE1EF2-E0F0-40B1-88B5-00A35D378742}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_queue", "_queue.vcxproj", "{78D80A15-BD8C-44E2-B49E-1F05B0A0A687}" @@ -1352,6 +1355,38 @@ Global {384C224A-7474-476E-A01B-750EA7DE918C}.Release|Win32.Build.0 = Release|Win32 {384C224A-7474-476E-A01B-750EA7DE918C}.Release|x64.ActiveCfg = Release|x64 {384C224A-7474-476E-A01B-750EA7DE918C}.Release|x64.Build.0 = Release|x64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Debug|ARM.ActiveCfg = Debug|ARM + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Debug|ARM.Build.0 = Debug|ARM + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Debug|ARM64.Build.0 = Debug|ARM64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Debug|Win32.ActiveCfg = Debug|Win32 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Debug|Win32.Build.0 = Debug|Win32 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Debug|x64.ActiveCfg = Debug|x64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Debug|x64.Build.0 = Debug|x64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGInstrument|ARM.ActiveCfg = PGInstrument|ARM + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGInstrument|ARM.Build.0 = PGInstrument|ARM + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGInstrument|ARM64.ActiveCfg = PGInstrument|ARM64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGInstrument|ARM64.Build.0 = PGInstrument|ARM64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGUpdate|ARM.ActiveCfg = PGUpdate|ARM + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGUpdate|ARM.Build.0 = PGUpdate|ARM + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGUpdate|ARM64.ActiveCfg = PGUpdate|ARM64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGUpdate|ARM64.Build.0 = PGUpdate|ARM64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Release|ARM.ActiveCfg = Release|ARM + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Release|ARM.Build.0 = Release|ARM + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Release|ARM64.ActiveCfg = Release|ARM64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Release|ARM64.Build.0 = Release|ARM64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Release|Win32.ActiveCfg = Release|Win32 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Release|Win32.Build.0 = Release|Win32 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Release|x64.ActiveCfg = Release|x64 + {D7B7A122-80A0-4AFB-9C06-18C29B3178E4}.Release|x64.Build.0 = Release|x64 {FCBE1EF2-E0F0-40B1-88B5-00A35D378742}.Debug|ARM.ActiveCfg = Debug|ARM {FCBE1EF2-E0F0-40B1-88B5-00A35D378742}.Debug|ARM.Build.0 = Debug|ARM {FCBE1EF2-E0F0-40B1-88B5-00A35D378742}.Debug|ARM64.ActiveCfg = Debug|ARM64 diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index 27c0d382281bdb..18ee141e7f8b8d 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -171,6 +171,7 @@ The following sub-projects are for individual modules of the standard library which are implemented in C; each one builds a DLL (renamed to .pyd) of the same name as the project: * _asyncio + * _base64 * _ctypes * _ctypes_test * _decimal diff --git a/Tools/msi/freethreaded/freethreaded_files.wxs b/Tools/msi/freethreaded/freethreaded_files.wxs index 0707e77b5e9ab2..67ec4f911e2683 100644 --- a/Tools/msi/freethreaded/freethreaded_files.wxs +++ b/Tools/msi/freethreaded/freethreaded_files.wxs @@ -103,7 +103,7 @@ - + diff --git a/Tools/msi/lib/lib_files.wxs b/Tools/msi/lib/lib_files.wxs index 4d44299f783909..dfb10f47c85398 100644 --- a/Tools/msi/lib/lib_files.wxs +++ b/Tools/msi/lib/lib_files.wxs @@ -1,6 +1,6 @@  - + From 3d19e35024629ca4def7c6938e2ff779ec812d92 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 18 Mar 2026 21:48:23 +0200 Subject: [PATCH 02/10] wow, cargo is present on all Windows jobs.. but not libclang, unfortunately --- .github/workflows/jit.yml | 5 ----- .github/workflows/tail-call.yml | 5 ----- PCbuild/_base64.vcxproj | 2 +- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 9ff9923d508e66..dc4210c59e195b 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -100,11 +100,6 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.11' - - uses: dtolnay/rust-toolchain@1.91.1 - if: runner.os == 'Windows' - with: - targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - # PCbuild downloads LLVM automatically: - name: Windows if: runner.os == 'Windows' diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index 93a63899d67288..795e2722d65144 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -78,11 +78,6 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.11' - - uses: dtolnay/rust-toolchain@1.91.1 - if: runner.os == 'Windows' - with: - targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - - name: Native Windows (debug) if: runner.os == 'Windows' && matrix.architecture != 'ARM64' shell: cmd diff --git a/PCbuild/_base64.vcxproj b/PCbuild/_base64.vcxproj index 94ab00bbbd16f3..d2eee6430e2d3a 100644 --- a/PCbuild/_base64.vcxproj +++ b/PCbuild/_base64.vcxproj @@ -126,7 +126,7 @@ if "$(Configuration)"=="Debug" (set "PY_DEBUG=1") else (set "PY_DEBUG=") if "$(DisableGil)"=="true" (set "PY_GIL_DISABLED=1") else (set "PY_GIL_DISABLED=") where cargo >NUL 2>NUL || (echo WARNING: cargo was not found on PATH, skipping _base64 & exit /b 0) if not "$(LibClangPath)"=="" set "LIBCLANG_PATH=$(LibClangPath)" -if "$(LibClangPath)"=="" if not defined LIBCLANG_PATH (echo ERROR: libclang.dll was not found. Install LLVM or the Visual Studio Clang tools and set LIBCLANG_PATH. & exit /b 1) +if "$(LibClangPath)"=="" if not defined LIBCLANG_PATH (echo WARNING: libclang.dll was not found, skipping _base64. Install LLVM or the Visual Studio Clang tools and set LIBCLANG_PATH. & exit /b 0) if not exist "$(CargoTargetDirNoSlash)" mkdir "$(CargoTargetDirNoSlash)" set "CARGO_TARGET_DIR=$(CargoTargetDirNoSlash)" set "PYTHON_BUILD_DIR=$(PythonBuildDir)" From 2326b9a6ff4c9e77b882eb6b0f70bf87ce80ec1a Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 18 Mar 2026 22:04:30 +0200 Subject: [PATCH 03/10] cargo fmt + fixes to not run on other jobs --- Modules/cpython-sys/build.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Modules/cpython-sys/build.rs b/Modules/cpython-sys/build.rs index ce9e6f1a599011..a521f6b840871a 100644 --- a/Modules/cpython-sys/build.rs +++ b/Modules/cpython-sys/build.rs @@ -15,7 +15,12 @@ fn main() { println!("cargo:rustc-cfg=py_gil_disabled"); } println!("cargo::rustc-check-cfg=cfg(py_gil_disabled)"); - generate_c_api_bindings(srcdir, builddir.as_deref(), out_path.as_path(), gil_disabled); + generate_c_api_bindings( + srcdir, + builddir.as_deref(), + out_path.as_path(), + gil_disabled, + ); } // Bindgen depends on build-time env and, on iOS, can also inherit the @@ -69,7 +74,12 @@ fn env_var_is_truthy(name: &str) -> bool { ) } -fn generate_c_api_bindings(srcdir: &Path, builddir: Option<&str>, out_path: &Path, gil_disabled: bool) { +fn generate_c_api_bindings( + srcdir: &Path, + builddir: Option<&str>, + out_path: &Path, + gil_disabled: bool, +) { let mut builder = bindgen::Builder::default().header("wrapper.h"); // Suppress all clang warnings (deprecation warnings, etc.) @@ -240,7 +250,10 @@ fn patch_windows_imported_pointer_globals(bindings: String, dll_name: &str) -> S while index < lines.len() { if lines[index] == "unsafe extern \"C\" {" - && lines.get(index + 1).and_then(|l| parse_pointer_static_decl(l)).is_some() + && lines + .get(index + 1) + .and_then(|l| parse_pointer_static_decl(l)) + .is_some() && lines.get(index + 2).is_some_and(|l| l.trim() == "}") { patched.push_str(&format!( From 476508df451ab9b3fd2fcacfb1d1396ffefd6149 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 18 Mar 2026 22:32:58 +0200 Subject: [PATCH 04/10] maybe install llvm for all windows jobs? --- .github/workflows/build.yml | 9 --------- .github/workflows/reusable-windows-msi.yml | 9 +++++++-- .github/workflows/reusable-windows.yml | 15 +-------------- PCbuild/_base64.vcxproj | 3 ++- 4 files changed, 10 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 32f9aa3d82b56f..ab9a73627ae1df 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -167,15 +167,6 @@ jobs: arch: ${{ matrix.arch }} free-threading: ${{ matrix.free-threading }} - build-windows-system-llvm: - name: Windows (Chocolatey LLVM) - needs: build-context - if: fromJSON(needs.build-context.outputs.run-windows-tests) - uses: ./.github/workflows/reusable-windows.yml - with: - arch: x64 - llvm-from-choco: true - build-windows-msi: # ${{ '' } is a hack to nest jobs under the same sidebar category. name: Windows MSI${{ '' }} # zizmor: ignore[obfuscation] diff --git a/.github/workflows/reusable-windows-msi.yml b/.github/workflows/reusable-windows-msi.yml index 7095f9e56c0353..d53a2ef5850b6f 100644 --- a/.github/workflows/reusable-windows-msi.yml +++ b/.github/workflows/reusable-windows-msi.yml @@ -22,8 +22,6 @@ jobs: env: ARCH: ${{ inputs.arch }} IncludeFreethreaded: true - IncludeLLVM: true - LIBCLANG_PATH: "${{ github.workspace }}\\externals\\llvm-21.1.4.0\\bin" steps: - uses: actions/checkout@v4 with: @@ -31,6 +29,13 @@ jobs: - uses: dtolnay/rust-toolchain@1.91.1 with: targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + - name: Install LLVM for bindgen + shell: cmd + run: | + choco install llvm --allow-downgrade --no-progress --version 21.1.0 + if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 + echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" + echo LLVMInstallDir=C:\Program Files\LLVM>> "%GITHUB_ENV%" - name: Build CPython installer run: ./Tools/msi/build.bat --doc -"${ARCH}" shell: bash diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 2438ebb73d6da0..08129cfcb73055 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -7,11 +7,6 @@ on: description: CPU architecture required: true type: string - llvm-from-choco: - description: Whether to install LLVM from Chocolatey and expose LIBCLANG_PATH - required: false - type: boolean - default: false free-threading: description: Whether to compile CPython in free-threading mode required: false @@ -37,21 +32,13 @@ jobs: - uses: dtolnay/rust-toolchain@1.91.1 with: targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - - name: Install LLVM from Chocolatey - if: fromJSON(inputs.llvm-from-choco) + - name: Install LLVM for bindgen shell: cmd run: | choco install llvm --allow-downgrade --no-progress --version 21.1.0 if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 - echo IncludeLLVM=false>> "%GITHUB_ENV%" echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" echo LLVMInstallDir=C:\Program Files\LLVM>> "%GITHUB_ENV%" - - name: Use bundled LLVM - if: ${{ !fromJSON(inputs.llvm-from-choco) }} - shell: cmd - run: | - echo IncludeLLVM=true>> "%GITHUB_ENV%" - echo LIBCLANG_PATH=%GITHUB_WORKSPACE%\externals\llvm-21.1.4.0\bin>> "%GITHUB_ENV%" - name: Register MSVC problem matcher if: inputs.arch != 'Win32' run: echo "::add-matcher::.github/problem-matchers/msvc.json" diff --git a/PCbuild/_base64.vcxproj b/PCbuild/_base64.vcxproj index d2eee6430e2d3a..916069c1aea82a 100644 --- a/PCbuild/_base64.vcxproj +++ b/PCbuild/_base64.vcxproj @@ -126,7 +126,8 @@ if "$(Configuration)"=="Debug" (set "PY_DEBUG=1") else (set "PY_DEBUG=") if "$(DisableGil)"=="true" (set "PY_GIL_DISABLED=1") else (set "PY_GIL_DISABLED=") where cargo >NUL 2>NUL || (echo WARNING: cargo was not found on PATH, skipping _base64 & exit /b 0) if not "$(LibClangPath)"=="" set "LIBCLANG_PATH=$(LibClangPath)" -if "$(LibClangPath)"=="" if not defined LIBCLANG_PATH (echo WARNING: libclang.dll was not found, skipping _base64. Install LLVM or the Visual Studio Clang tools and set LIBCLANG_PATH. & exit /b 0) +if "$(LibClangPath)"=="" if not defined LIBCLANG_PATH (echo WARNING: libclang was not found, skipping _base64 & exit /b 0) +if defined LIBCLANG_PATH if not exist "%LIBCLANG_PATH%\libclang.dll" if not exist "%LIBCLANG_PATH%\clang.dll" (echo WARNING: libclang.dll not found at %LIBCLANG_PATH%, skipping _base64 & exit /b 0) if not exist "$(CargoTargetDirNoSlash)" mkdir "$(CargoTargetDirNoSlash)" set "CARGO_TARGET_DIR=$(CargoTargetDirNoSlash)" set "PYTHON_BUILD_DIR=$(PythonBuildDir)" From e9ca08f38c81540024e63d2a517f1624c2380429 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 18 Mar 2026 22:56:08 +0200 Subject: [PATCH 05/10] Install llvm for arm --- .github/workflows/reusable-windows-msi.yml | 13 +++++++++++++ .github/workflows/reusable-windows.yml | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/.github/workflows/reusable-windows-msi.yml b/.github/workflows/reusable-windows-msi.yml index d53a2ef5850b6f..baa45707e137aa 100644 --- a/.github/workflows/reusable-windows-msi.yml +++ b/.github/workflows/reusable-windows-msi.yml @@ -30,12 +30,25 @@ jobs: with: targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - name: Install LLVM for bindgen + if: inputs.arch != 'arm64' shell: cmd run: | choco install llvm --allow-downgrade --no-progress --version 21.1.0 if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" echo LLVMInstallDir=C:\Program Files\LLVM>> "%GITHUB_ENV%" + # Chocolatey's LLVM package only ships x64 binaries, which an ARM64-native + # cargo process cannot load. Install the official ARM64 build directly. + - name: Install LLVM for bindgen (ARM64) + if: inputs.arch == 'arm64' + shell: pwsh + run: | + $installer = Join-Path $env:RUNNER_TEMP 'LLVM-21.1.0-woa64.exe' + Invoke-WebRequest 'https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0/LLVM-21.1.0-woa64.exe' -OutFile $installer + Start-Process -Wait -FilePath $installer -ArgumentList '/S','/D=C:\Program Files\LLVM' + if (!(Test-Path 'C:\Program Files\LLVM\bin\libclang.dll')) { exit 1 } + echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV + echo "LLVMInstallDir=C:\Program Files\LLVM" >> $env:GITHUB_ENV - name: Build CPython installer run: ./Tools/msi/build.bat --doc -"${ARCH}" shell: bash diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 08129cfcb73055..3c68e52c8f52c5 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -33,12 +33,25 @@ jobs: with: targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - name: Install LLVM for bindgen + if: inputs.arch != 'arm64' shell: cmd run: | choco install llvm --allow-downgrade --no-progress --version 21.1.0 if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" echo LLVMInstallDir=C:\Program Files\LLVM>> "%GITHUB_ENV%" + # Chocolatey's LLVM package only ships x64 binaries, which an ARM64-native + # cargo process cannot load. Install the official ARM64 build directly. + - name: Install LLVM for bindgen (ARM64) + if: inputs.arch == 'arm64' + shell: pwsh + run: | + $installer = Join-Path $env:RUNNER_TEMP 'LLVM-21.1.0-woa64.exe' + Invoke-WebRequest 'https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0/LLVM-21.1.0-woa64.exe' -OutFile $installer + Start-Process -Wait -FilePath $installer -ArgumentList '/S','/D=C:\Program Files\LLVM' + if (!(Test-Path 'C:\Program Files\LLVM\bin\libclang.dll')) { exit 1 } + echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV + echo "LLVMInstallDir=C:\Program Files\LLVM" >> $env:GITHUB_ENV - name: Register MSVC problem matcher if: inputs.arch != 'Win32' run: echo "::add-matcher::.github/problem-matchers/msvc.json" From 24bc8508b854b172e21186a3f7a588eeb8779c9a Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Thu, 19 Mar 2026 23:09:46 +0200 Subject: [PATCH 06/10] Address Sergey's review --- .github/setup-rust-windows/action.yml | 36 ++++++++++++++++++++++ .github/workflows/reusable-windows-msi.yml | 24 ++------------- .github/workflows/reusable-windows.yml | 24 ++------------- Modules/cpython-sys/build.rs | 9 +++--- 4 files changed, 45 insertions(+), 48 deletions(-) create mode 100644 .github/setup-rust-windows/action.yml diff --git a/.github/setup-rust-windows/action.yml b/.github/setup-rust-windows/action.yml new file mode 100644 index 00000000000000..c50c3c957cbe89 --- /dev/null +++ b/.github/setup-rust-windows/action.yml @@ -0,0 +1,36 @@ +name: Set up Rust and LLVM for Windows +description: >- + Install the pinned Rust toolchain with Windows cross-compile targets and + a version of LLVM whose libclang is loadable by bindgen. + +inputs: + arch: + description: CPU architecture (x64, Win32, arm64) + required: true + +runs: + using: composite + steps: + - uses: dtolnay/rust-toolchain@1.91.1 + with: + targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + - name: Install LLVM for bindgen + if: inputs.arch != 'arm64' + shell: cmd + run: | + choco install llvm --allow-downgrade --no-progress --version 21.1.0 + if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 + echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" + echo LLVMInstallDir=C:\Program Files\LLVM>> "%GITHUB_ENV%" + # Chocolatey's LLVM package only ships x64 binaries, which an ARM64-native + # cargo process cannot load. Install the official ARM64 build directly. + - name: Install LLVM for bindgen (ARM64) + if: inputs.arch == 'arm64' + shell: pwsh + run: | + $installer = Join-Path $env:RUNNER_TEMP 'LLVM-21.1.0-woa64.exe' + Invoke-WebRequest 'https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0/LLVM-21.1.0-woa64.exe' -OutFile $installer + Start-Process -Wait -FilePath $installer -ArgumentList '/S','/D=C:\Program Files\LLVM' + if (!(Test-Path 'C:\Program Files\LLVM\bin\libclang.dll')) { exit 1 } + echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV + echo "LLVMInstallDir=C:\Program Files\LLVM" >> $env:GITHUB_ENV diff --git a/.github/workflows/reusable-windows-msi.yml b/.github/workflows/reusable-windows-msi.yml index baa45707e137aa..af9139d161f6b3 100644 --- a/.github/workflows/reusable-windows-msi.yml +++ b/.github/workflows/reusable-windows-msi.yml @@ -26,29 +26,9 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false - - uses: dtolnay/rust-toolchain@1.91.1 + - uses: ./.github/setup-rust-windows with: - targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - - name: Install LLVM for bindgen - if: inputs.arch != 'arm64' - shell: cmd - run: | - choco install llvm --allow-downgrade --no-progress --version 21.1.0 - if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 - echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" - echo LLVMInstallDir=C:\Program Files\LLVM>> "%GITHUB_ENV%" - # Chocolatey's LLVM package only ships x64 binaries, which an ARM64-native - # cargo process cannot load. Install the official ARM64 build directly. - - name: Install LLVM for bindgen (ARM64) - if: inputs.arch == 'arm64' - shell: pwsh - run: | - $installer = Join-Path $env:RUNNER_TEMP 'LLVM-21.1.0-woa64.exe' - Invoke-WebRequest 'https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0/LLVM-21.1.0-woa64.exe' -OutFile $installer - Start-Process -Wait -FilePath $installer -ArgumentList '/S','/D=C:\Program Files\LLVM' - if (!(Test-Path 'C:\Program Files\LLVM\bin\libclang.dll')) { exit 1 } - echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV - echo "LLVMInstallDir=C:\Program Files\LLVM" >> $env:GITHUB_ENV + arch: ${{ inputs.arch }} - name: Build CPython installer run: ./Tools/msi/build.bat --doc -"${ARCH}" shell: bash diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 3c68e52c8f52c5..8132d205f9bf62 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -29,29 +29,9 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false - - uses: dtolnay/rust-toolchain@1.91.1 + - uses: ./.github/setup-rust-windows with: - targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - - name: Install LLVM for bindgen - if: inputs.arch != 'arm64' - shell: cmd - run: | - choco install llvm --allow-downgrade --no-progress --version 21.1.0 - if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 - echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" - echo LLVMInstallDir=C:\Program Files\LLVM>> "%GITHUB_ENV%" - # Chocolatey's LLVM package only ships x64 binaries, which an ARM64-native - # cargo process cannot load. Install the official ARM64 build directly. - - name: Install LLVM for bindgen (ARM64) - if: inputs.arch == 'arm64' - shell: pwsh - run: | - $installer = Join-Path $env:RUNNER_TEMP 'LLVM-21.1.0-woa64.exe' - Invoke-WebRequest 'https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0/LLVM-21.1.0-woa64.exe' -OutFile $installer - Start-Process -Wait -FilePath $installer -ArgumentList '/S','/D=C:\Program Files\LLVM' - if (!(Test-Path 'C:\Program Files\LLVM\bin\libclang.dll')) { exit 1 } - echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV - echo "LLVMInstallDir=C:\Program Files\LLVM" >> $env:GITHUB_ENV + arch: ${{ inputs.arch }} - name: Register MSVC problem matcher if: inputs.arch != 'Win32' run: echo "::add-matcher::.github/problem-matchers/msvc.json" diff --git a/Modules/cpython-sys/build.rs b/Modules/cpython-sys/build.rs index a521f6b840871a..3692d384f698e3 100644 --- a/Modules/cpython-sys/build.rs +++ b/Modules/cpython-sys/build.rs @@ -30,6 +30,8 @@ fn emit_rerun_instructions(builddir: Option<&str>) { for var in [ "IPHONEOS_DEPLOYMENT_TARGET", "LLVM_TARGET", + "PY_DEBUG", + "PY_GIL_DISABLED", "PYTHON_BUILD_DIR", "PY_CC", "PY_CPPFLAGS", @@ -68,10 +70,9 @@ fn gil_disabled(srcdir: &Path, builddir: Option<&str>) -> bool { } fn env_var_is_truthy(name: &str) -> bool { - matches!( - env::var(name).as_deref(), - Ok("1") | Ok("true") | Ok("TRUE") | Ok("yes") | Ok("YES") - ) + env::var(name) + .map(|v| matches!(v.to_ascii_lowercase().as_str(), "1" | "true" | "yes")) + .unwrap_or(false) } fn generate_c_api_bindings( From e48350b76e1f0842500e47bc70f8ce7433bf6b9c Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Thu, 19 Mar 2026 23:22:18 +0200 Subject: [PATCH 07/10] Remove GITHUB_ENV --- .github/setup-rust-windows/action.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/setup-rust-windows/action.yml b/.github/setup-rust-windows/action.yml index c50c3c957cbe89..cb47cc8253cf84 100644 --- a/.github/setup-rust-windows/action.yml +++ b/.github/setup-rust-windows/action.yml @@ -20,8 +20,6 @@ runs: run: | choco install llvm --allow-downgrade --no-progress --version 21.1.0 if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 - echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" - echo LLVMInstallDir=C:\Program Files\LLVM>> "%GITHUB_ENV%" # Chocolatey's LLVM package only ships x64 binaries, which an ARM64-native # cargo process cannot load. Install the official ARM64 build directly. - name: Install LLVM for bindgen (ARM64) @@ -32,5 +30,3 @@ runs: Invoke-WebRequest 'https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0/LLVM-21.1.0-woa64.exe' -OutFile $installer Start-Process -Wait -FilePath $installer -ArgumentList '/S','/D=C:\Program Files\LLVM' if (!(Test-Path 'C:\Program Files\LLVM\bin\libclang.dll')) { exit 1 } - echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV - echo "LLVMInstallDir=C:\Program Files\LLVM" >> $env:GITHUB_ENV From f1a15552c382bfb76f2e318a6f101beadc3ed190 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Thu, 19 Mar 2026 23:35:14 +0200 Subject: [PATCH 08/10] Add a comment --- .github/setup-rust-windows/action.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/setup-rust-windows/action.yml b/.github/setup-rust-windows/action.yml index cb47cc8253cf84..4b12499274331f 100644 --- a/.github/setup-rust-windows/action.yml +++ b/.github/setup-rust-windows/action.yml @@ -14,12 +14,17 @@ runs: - uses: dtolnay/rust-toolchain@1.91.1 with: targets: i686-pc-windows-msvc,x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + # LIBCLANG_PATH must be set explicitly so the vcxproj uses the LLVM we + # install here rather than the VS-bundled LLVM whose clang headers have + # AVX intrinsic bugs. The values are hardcoded literals (no attacker- + # controlled input), so the GITHUB_ENV writes are safe. - name: Install LLVM for bindgen if: inputs.arch != 'arm64' shell: cmd run: | choco install llvm --allow-downgrade --no-progress --version 21.1.0 if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 + echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" # Chocolatey's LLVM package only ships x64 binaries, which an ARM64-native # cargo process cannot load. Install the official ARM64 build directly. - name: Install LLVM for bindgen (ARM64) @@ -30,3 +35,4 @@ runs: Invoke-WebRequest 'https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0/LLVM-21.1.0-woa64.exe' -OutFile $installer Start-Process -Wait -FilePath $installer -ArgumentList '/S','/D=C:\Program Files\LLVM' if (!(Test-Path 'C:\Program Files\LLVM\bin\libclang.dll')) { exit 1 } + echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV # zizmor: ignore[environment-file] From 640f61681e94e9e2edf0888e9ea316fc1f4d29e0 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Thu, 19 Mar 2026 23:38:12 +0200 Subject: [PATCH 09/10] fix job --- .github/setup-rust-windows/action.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/setup-rust-windows/action.yml b/.github/setup-rust-windows/action.yml index 4b12499274331f..765b847cebb564 100644 --- a/.github/setup-rust-windows/action.yml +++ b/.github/setup-rust-windows/action.yml @@ -18,7 +18,7 @@ runs: # install here rather than the VS-bundled LLVM whose clang headers have # AVX intrinsic bugs. The values are hardcoded literals (no attacker- # controlled input), so the GITHUB_ENV writes are safe. - - name: Install LLVM for bindgen + - name: Install LLVM for bindgen # zizmor: ignore[github-env] if: inputs.arch != 'arm64' shell: cmd run: | @@ -27,7 +27,7 @@ runs: echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" # Chocolatey's LLVM package only ships x64 binaries, which an ARM64-native # cargo process cannot load. Install the official ARM64 build directly. - - name: Install LLVM for bindgen (ARM64) + - name: Install LLVM for bindgen (ARM64) # zizmor: ignore[github-env] if: inputs.arch == 'arm64' shell: pwsh run: | @@ -35,4 +35,4 @@ runs: Invoke-WebRequest 'https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0/LLVM-21.1.0-woa64.exe' -OutFile $installer Start-Process -Wait -FilePath $installer -ArgumentList '/S','/D=C:\Program Files\LLVM' if (!(Test-Path 'C:\Program Files\LLVM\bin\libclang.dll')) { exit 1 } - echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV # zizmor: ignore[environment-file] + echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV From 4f45bc6d2d36fe8b7524a1474d4d58e1746e1baf Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Thu, 19 Mar 2026 23:40:28 +0200 Subject: [PATCH 10/10] i should've checked the doc --- .github/setup-rust-windows/action.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/setup-rust-windows/action.yml b/.github/setup-rust-windows/action.yml index 765b847cebb564..97e0288592b146 100644 --- a/.github/setup-rust-windows/action.yml +++ b/.github/setup-rust-windows/action.yml @@ -18,19 +18,19 @@ runs: # install here rather than the VS-bundled LLVM whose clang headers have # AVX intrinsic bugs. The values are hardcoded literals (no attacker- # controlled input), so the GITHUB_ENV writes are safe. - - name: Install LLVM for bindgen # zizmor: ignore[github-env] + - name: Install LLVM for bindgen if: inputs.arch != 'arm64' shell: cmd - run: | + run: | # zizmor: ignore[github-env] choco install llvm --allow-downgrade --no-progress --version 21.1.0 if not exist "C:\Program Files\LLVM\bin\libclang.dll" exit /b 1 echo LIBCLANG_PATH=C:\Program Files\LLVM\bin>> "%GITHUB_ENV%" # Chocolatey's LLVM package only ships x64 binaries, which an ARM64-native # cargo process cannot load. Install the official ARM64 build directly. - - name: Install LLVM for bindgen (ARM64) # zizmor: ignore[github-env] + - name: Install LLVM for bindgen (ARM64) if: inputs.arch == 'arm64' shell: pwsh - run: | + run: | # zizmor: ignore[github-env] $installer = Join-Path $env:RUNNER_TEMP 'LLVM-21.1.0-woa64.exe' Invoke-WebRequest 'https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0/LLVM-21.1.0-woa64.exe' -OutFile $installer Start-Process -Wait -FilePath $installer -ArgumentList '/S','/D=C:\Program Files\LLVM'