diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 00000000..045d18ab --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,35 @@ +name: Check Changelog + +on: + pull_request: + branches: + - main + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6.0.1 + with: + fetch-depth: 0 + + - name: Check version differs from main + run: | + version=$(grep "^version = " pyproject.toml | sed 's/version = "//;s/"//') + main_version=$(git show origin/main:pyproject.toml | grep "^version = " | sed 's/version = "//;s/"//') + if [[ "$version" == "$main_version" ]]; then + echo "ERROR: pyproject.toml version ($version) is the same as main ($main_version)" + echo "Please bump the version before submitting a PR." + exit 1 + fi + echo "Version check passed: $version (main is $main_version)" + + - name: Check changelog has entry for version + run: | + version=$(grep "^version = " pyproject.toml | sed 's/version = "//;s/"//') + if ! grep -q "^### $version " CHANGELOG.md; then + echo "ERROR: CHANGELOG.md has no entry for $version" + echo "Please run tools/update_changelog.sh and edit the entry before submitting." + exit 1 + fi + echo "Changelog check passed: found entry for $version" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cd139036..835e3b2e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,7 +4,9 @@ on: workflow_dispatch: inputs: environment: - description: Which PyPI environment to upload to, if any + description: | + Which PyPI environment to upload to? + Be sure to push an annotated tag to 'main' before choosing 'pypi' required: true type: choice options: [ "none", "testpypi", "pypi" ] diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..3954c2a5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,96 @@ +## OpenBLAS v0.3.31.126 (v0.3.31-126-g55b16e59) + +### 0.3.31.126.6 (2026-03-17) +- Replace the VERSION = in Makefile.rule with the one from pyproject.toml + +### 0.3.31.126.5 (2026-03-12) +- use single workflow step for publishing to PyPI + +### 0.3.31.126.4 (2026-03-12) +- refactor, add pypi publishing + +### 0.3.31.126.3 (2026-03-10) +- disambiguate bewteen a NIGHTLY build and a publish build + +### 0.3.31.126.2 (2026-03-10) +- Trusted publishing work + +### 0.3.31.126.1 (2026-03-08) +- fix bad re-zip: use 'w' not 'a' + +### 0.3.31.126.0 (2026-03-06) +- update to 0.3.31-126-g55b16e59 + +## OpenBLAS v0.3.31.22 (v0.3.31-22-g5ffbf38b) + +### 0.3.31.22.1 (2026-02-01) +- feat: build riscv64+glibc wheel + +### 0.3.31.22.0 (2026-01-20) +- update to v0.3.31-22-g5ffbf38b + +## OpenBLAS v0.3.30.443 (v0.3.30-443-g52ec7faf) + +### 0.3.30.443.1 (2026-01-14) +- fix typo which created bad pkgconfig file on arm64 32-bit interface + +### 0.3.30.443.0 (2026-01-11) +- version + +## OpenBLAS v0.3.30.359 (v0.3.30-359-g29fab2b9) + +### 0.3.30.359.2 (2026-01-11) +- update OpenBLAS version + +### 0.3.30.359.1 (2025-12-17) +- cleanup and single-use OPENBLAS_COMMIT via a file + +### 0.3.30.359.0 (2025-11-30) +- Use clang instead of gcc to build on Linux + +## OpenBLAS v0.3.30.349 + +### 0.3.30.349.1 (2025-11-29) +- Always use gfortran-11 on macos + +### 0.3.30.349.0 (2025-11-17) +- update OpenBLAS version to v0.3.30-322-gef6f9762 + +## OpenBLAS v0.3.30.0 + +### 0.3.30.0.7 (2025-11-03) +- patch out extraneous lock/unlock + +### 0.3.30.0.6 (2025-10-29) +- use gfortran-11 on macos-x86_64 build + +### 0.3.30.0.5 (2025-10-23) +- cleanup clean_code, remove repo_dir, checkout OpenBLAS commit in ci-before-build.sh + +### 0.3.30.0.4 (2025-10-22) +- patch to remove OpenBLAS PR 4741, cleanup unused bash code + +### 0.3.30.0.3 (2025-10-21) +- Use cibuildwheel to replace multibuild + +### 0.3.30.0.2 (2025-10-12) +- Using USE_THREADS & NUM_THREADS while building openblas for win arm64 + +### 0.3.30.0.0 (2025-06-26) +- update OpenBLAS to 0.3.30 + +## OpenBLAS v0.3.29.265 + +### 0.3.29.265.2 (2025-06-09) +- fix cmake and README + +### 0.3.29.265.1 (2025-06-06) +- Refactor confusing BUILD_BITS variable in CI + +### 0.3.29.265.0 (2025-06-04) +- Refactor CI to produce 64-bit integer interface wheels for WoA + +## OpenBLAS v0.3.29.0 + +### 0.3.29.0.0 (2025-04-03) +- Add build script for Windows on ARM64 diff --git a/README.md b/README.md index 92670b12..509a5698 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,14 @@ https://anaconda.org/scientific=python-nightly-wheels/scipy_openblas64 via There are workflow triggers for repo admins. They can trigger a testpypi build or a pypi build with the publish workflow, which will upload the wheels using trusted publishing. In order to publish to PyPI, there must be a tag at the HEAD -of the branch used to publish. Use annotated tags: +of the branch used to publish. After merging a PR, be sure to update to main and +use annotated tags: ``` +git checkout main; git pull git tag -a v0.3.31.126.4 -m"fixed something" ``` The wheel is self-contained, it includes all needed gfortran support libraries. -On windows, this is a single DLL. +On windows, this is a single DLL. ## Buildtime diff --git a/ci-before-build.sh b/ci-before-build.sh index 519ce524..3c6e1c04 100755 --- a/ci-before-build.sh +++ b/ci-before-build.sh @@ -51,7 +51,9 @@ if [[ "$NIGHTLY" = "true" ]]; then sed -e "s/^version = .*/version = \"${version}\"/" -i.bak pyproject.toml else export OPENBLAS_COMMIT=$(cat openblas_commit.txt) + version=$(grep "^version =" pyproject.toml | sed 's/version = "//;s/"//') fi +sed -e "s/^VERSION = .*/VERSION = ${version}/" -i.bak OpenBLAS/Makefile.rule echo "creating wheel from $OPENBLAS_COMMIT (NIGHTLY is $NIGHTLY)" if [ "$(uname)" != "Darwin" ]; then diff --git a/ci-test.sh b/ci-test.sh index 326a5822..0cdc0c1d 100755 --- a/ci-test.sh +++ b/ci-test.sh @@ -12,14 +12,21 @@ if [ "$(uname)" == "Darwin" -a "${PLAT}" == "x86_64" ]; then which python3.9 PYTHON="arch -x86_64 python3.9" fi + +# Make sure the module works and that the version strings match +# cibuildwheel will install the wheel automatically if [ "${INTERFACE64}" != "1" ]; then - # cibuildwheel will install the wheel automatically - # $PYTHON -m pip install --no-index --find-links /tmp/cibuildwheel/repaired_wheel scipy_openblas32 - $PYTHON -m scipy_openblas32 + config_str=$($PYTHON -m scipy_openblas32) else - # $PYTHON -m pip install --no-index --find-links /tmp/cibuildwheel/repaired_wheel scipy_openblas64 - $PYTHON -m scipy_openblas64 + config_str=$($PYTHON -m scipy_openblas64) +fi +version=$($PYTHON -m pip list | grep scipy-openblas | sed 's/.*[[:space:]]//') +if [[ "$config_str" != *"$version"* ]]; then + echo "config_str version does not match the pyproject.toml" + exit -1 fi + + $PYTHON -m pip install pkgconf $PYTHON -m pkgconf scipy-openblas --cflags diff --git a/pyproject.toml b/pyproject.toml index 46a1584c..f1f744a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "scipy-openblas64" # v0.3.31-126-g55b16e59 -version = "0.3.31.126.5" +version = "0.3.31.126.6" requires-python = ">=3.7" description = "Provides OpenBLAS for python packaging" readme = "README.md" diff --git a/tools/build_steps_win_arm64.bat b/tools/build_steps_win_arm64.bat index 001921ad..de6e5bdb 100755 --- a/tools/build_steps_win_arm64.bat +++ b/tools/build_steps_win_arm64.bat @@ -1,16 +1,16 @@ -:: Build script for scipy_openblas wheel on Windows on ARM64 - -:: Usage: build_steps_win_arm64.bat [build_bits] [if_bits] -:: e.g build_steps_win_arm64.bat 64 64 - -:: build_bits (default binary architecture, 32 or 64, unspec -> 64). -:: if_bits (default interface size, 32 or 64, unspec -> 32) -:: If INTERFACE64 environment variable is 1, then if_bits defaults to 64 -:: Expects these binaries on the PATH: -:: clang-cl, flang-new, cmake, perl -:: First commit containing WoA build fixes. -:: Minimum OpenBLAS commit to build; we'll update to this if commit not -:: present. +REM Build script for scipy_openblas wheel on Windows on ARM64 + +REM Usage: build_steps_win_arm64.bat [build_bits] [if_bits] +REM e.g build_steps_win_arm64.bat 64 64 + +REM build_bits (default binary architecture, 32 or 64, unspec -> 64). +REM if_bits (default interface size, 32 or 64, unspec -> 32) +REM If INTERFACE64 environment variable is 1, then if_bits defaults to 64 +REM Expects these binaries on the PATH: +REM clang-cl, flang-new, cmake, perl +REM First commit containing WoA build fixes. +REM Minimum OpenBLAS commit to build; we'll update to this if commit not +REM present. set first_woa_buildable_commit="de2380e5a6149706a633322a16a0f66faa5591fc" @echo off @@ -33,7 +33,7 @@ if "%2"=="" ( ) echo Building for %build_bits%-bit binary, %if_bits%-bit interface... -:: Define destination directory +REM Define destination directory pushd "%~dp0\.." set "ob_out_root=%CD%\local\scipy_openblas" set "ob_64=%ob_out_root%64" @@ -54,13 +54,13 @@ if "%if_bits%"=="64" ( ) ) -:: Clone OpenBLAS +REM Clone OpenBLAS echo Cloning OpenBLAS repository with submodules... git submodule update --init --recursive OpenBLAS if errorlevel 1 exit /b 1 set /p OPENBLAS_COMMIT=NUL @@ -70,30 +70,38 @@ if errorlevel 1 ( exit /b 2 ) -:: Patch +REM Patch for /r %%f in (..\patches\*) do git apply %%f if errorlevel 1 exit /b 1 -:: Set suffixed-ILP64 flags +REM Patch VERSION +REM version=$(grep "^version =" ../pyproject.toml | sed 's/version = "//;s/"//') +REM sed -e "s/^VERSION = .*/VERSION = ${version}/" -i.bak Makefile.rule + +for /f "tokens=3 delims= " %%v in ('findstr /b "version = " ..\pyproject.toml') do set version=%%v +set version=%version:"=% +powershell -Command "(Get-Content OpenBLAS/Makefile.rule) -replace '^VERSION = .*', 'VERSION = %version%' | Set-Content Makefile.rule" + +REM Set suffixed-ILP64 flags if "%if_bits%"=="64" ( set "interface_flags=-DINTERFACE64=1 -DSYMBOLSUFFIX=64_" ) else ( set "interface_flags=" ) -:: Create build directory and navigate to it +REM Create build directory and navigate to it if exist build (rmdir /S /Q build || exit /b 1) mkdir build || exit /b 1 & cd build || exit /b 1 echo Setting up ARM64 Developer Command Prompt and running CMake... -:: Initialize VS ARM64 environment +REM Initialize VS ARM64 environment CALL "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsarm64.bat" -:: Prefer LLVM flang +REM Prefer LLVM flang PATH=C:\Program Files\LLVM\bin;%PATH% -:: Run CMake and Ninja build +REM Run CMake and Ninja build set CFLAGS=-Wno-reserved-macro-identifier -Wno-unsafe-buffer-usage -Wno-unused-macros -Wno-sign-conversion -Wno-reserved-identifier cmake .. -G Ninja ^ @@ -132,13 +140,13 @@ if "%if_bits%"=="32" ( cd .. ) -:: Prepare destination directory +REM Prepare destination directory cd OpenBLAS/build echo Preparing destination directory at %DEST_DIR% if not exist "%DEST_DIR%\lib\cmake\OpenBLAS" mkdir "%DEST_DIR%\lib\cmake\OpenBLAS" if not exist "%DEST_DIR%\include" mkdir "%DEST_DIR%\include" -:: Move library files +REM Move library files echo Moving library files... if exist lib\release ( move /Y lib\release\*.dll "%DEST_DIR%\lib\" @@ -154,19 +162,19 @@ if exist lib\release ( exit /b 1 ) -:: Copy CMake configuration files +REM Copy CMake configuration files echo Copying CMake configuration files... if exist openblasconfig.cmake copy /Y openblasconfig.cmake "%DEST_DIR%\lib\cmake\openblas\" if exist openblasconfigversion.cmake copy /Y openblasconfigversion.cmake "%DEST_DIR%\lib\cmake\openblas\" -:: Copy header files +REM Copy header files echo Copying generated header files... if exist generated xcopy /E /Y generated "%DEST_DIR%\include\" if exist lapacke_mangling.h copy /Y lapacke_mangling.h "%DEST_DIR%\include\" if exist openblas_config.h copy /Y openblas_config.h "%DEST_DIR%\include\" -:: Copy LAPACKE header files +REM Copy LAPACKE header files echo Copying LAPACKE header files... xcopy /Y "..\lapack-netlib\lapacke\include\*.h" "%DEST_DIR%\include\" if errorlevel 1 exit /b 1 @@ -189,14 +197,14 @@ if errorlevel 1 ( exit /b 1 ) -:: Move back to the root directory +REM Move back to the root directory cd .. if errorlevel 1 ( echo Current directory %CD%, cannot cd .. exit /b 1 ) -:: Build the Wheel & Install It +REM Build the Wheel & Install It echo Running 'python -m build' to build the wheel in %CD% python -c "import build" 2>NUL || pip install build if "%if_bits%"=="64" ( @@ -213,7 +221,7 @@ if "%if_bits%"=="32" ( move /Y "%CD%\ob64_backup" "%ob_64%" ) -:: Rename the wheel +REM Rename the wheel for %%f in (dist\*any.whl) do ( set WHEEL_FILE=dist\%%f set "filename=%%~nxf" @@ -221,7 +229,7 @@ for %%f in (dist\*any.whl) do ( ren "dist\!filename!" "!newname!" ) -:: Locate the built wheel +REM Locate the built wheel for /f %%f in ('dir /b dist\scipy_openblas*.whl 2^>nul') do set WHEEL_FILE=dist\%%f if not defined WHEEL_FILE ( diff --git a/tools/build_steps_windows.sh b/tools/build_steps_windows.sh index 5ae3cc36..d4e7bdde 100644 --- a/tools/build_steps_windows.sh +++ b/tools/build_steps_windows.sh @@ -94,6 +94,10 @@ OPENBLAS_VERSION=$(git describe --tags --abbrev=8) # with libquadmath patch -p1 < ../patches-windows/openblas-make-libs.patch +# Patch VERSION +version=$(grep "^version =" ../pyproject.toml | sed 's/version = "//;s/"//') +sed -e "s/^VERSION = .*/VERSION = ${version}/" -i.bak Makefile.rule + # Build OpenBLAS CFLAGS="$CFLAGS -fvisibility=protected -fno-ident" \ make BINARY=$build_bits DYNAMIC_ARCH=1 USE_THREAD=1 USE_OPENMP=0 \ diff --git a/tools/local_build.bat b/tools/local_build.bat new file mode 100644 index 00000000..e69de29b diff --git a/tools/local_build.sh b/tools/local_build.sh index 441375d7..57202036 100755 --- a/tools/local_build.sh +++ b/tools/local_build.sh @@ -20,7 +20,9 @@ else echo got nothing exit -1 fi -export OPENBLAS_COMMIT="v0.3.30-349-gf6df9beb" +export OPENBLAS_COMMIT=$(cat openblas_commit.txt) +version=$(echo $OPENBLAS_COMMIT | sed -e "s/^v\(.*\)-g.*/\1/" | sed -e "s/-/./g").0 +sed -e "s/^VERSION = .*/VERSION = ${version}/" -i.bak OpenBLAS/Makefile.rule # export MB_ML_LIBC=musllinux # export MB_ML_VER=_1_2 diff --git a/tools/update_changelog.sh b/tools/update_changelog.sh new file mode 100644 index 00000000..e40824f5 --- /dev/null +++ b/tools/update_changelog.sh @@ -0,0 +1,69 @@ +#!/bin/bash +set -euo pipefail + +REPO_DIR=$(git rev-parse --show-toplevel) +CHANGELOG="$REPO_DIR/CHANGELOG.md" +PYPROJECT="pyproject.toml" +OPENBLAS_COMMIT_FILE="openblas_commit.txt" + +# ── Get current version ─────────────────────────────────────────────────── +version=$(grep "^version = " "$PYPROJECT" | sed 's/version = "//;s/"//') + +# ── Check version is different from main ───────────────────────────────── +main_version=$(git show origin/main:"$PYPROJECT" | grep "^version = " | sed 's/version = "//;s/"//') +if [[ "$version" == "$main_version" ]]; then + echo "ERROR: pyproject.toml version ($version) is the same as main." + echo "Please bump the version before submitting a PR." + exit 1 +fi + +# ── Guard: skip if version already in changelog ─────────────────────────── +if grep -q "^### $version " "$CHANGELOG" 2>/dev/null; then + echo "CHANGELOG.md already contains $version — skipping." + exit 0 +fi + +# ── Get OpenBLAS info ───────────────────────────────────────────────────── +openblas_raw=$(cat "$OPENBLAS_COMMIT_FILE") +openblas_tag=$(echo "$openblas_raw" | sed 's/^\(v[0-9]*\.[0-9]*\.[0-9]*\)-\([0-9]*\).*/\1.\2/') + +# ── Detect if OpenBLAS version changed vs main ──────────────────────────── +main_openblas_raw=$(git show origin/main:"$OPENBLAS_COMMIT_FILE" 2>/dev/null || true) + +# ── Get date ────────────────────────────────────────────────────────────── +date_str=$(date +%Y-%m-%d) + +# ── Get first meaningful commit message ─────────────────────────────────── +merge_base=$(git merge-base origin/main HEAD) +first_commit_msg=$(git log "$merge_base"..HEAD --format="%s" --reverse \ + | grep -iv "^typo\|^fix test\|^wip\|^minor\|^cleanup\|^merge" \ + | head -1 || true) +[[ -z "$first_commit_msg" ]] && first_commit_msg="(no description)" + +# ── Build new entry ─────────────────────────────────────────────────────── +new_entry="" +if [[ -n "$main_openblas_raw" && "$openblas_raw" != "$main_openblas_raw" ]]; then + new_entry="## OpenBLAS $openblas_tag ($openblas_raw)\n\n" +fi +new_entry+="### $version ($date_str)\n- $first_commit_msg\n\n" + +# ── Prepend to changelog ────────────────────────────────────────────────── +existing=$(cat "$CHANGELOG" 2>/dev/null || true) + +if [[ -n "$main_openblas_raw" && "$openblas_raw" != "$main_openblas_raw" ]]; then + # New OpenBLAS header + entry go at the very top + printf "%b%s" "$new_entry" "$existing" > "$CHANGELOG" +else + # Insert ### entry after the existing ## OpenBLAS header + printf "%b" "$existing" | awk -v entry="### $version ($date_str)\n- $first_commit_msg\n" ' + /^### /{ + if (!inserted) { + printf "%s\n", entry + inserted=1 + } + } + { print } + ' > "$CHANGELOG" +fi +echo "Changelog updated: $version" +echo "Please review and edit CHANGELOG.md before committing."