From 9e0dd5ef88f8cb2322dce3802ad27ce3bda5f83e Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 18 Dec 2025 13:39:11 +0200 Subject: [PATCH 01/11] add entrypoint.txt for pyconf-pypi, cleanup --- .github/workflows/windows.yml | 8 +++ README.md | 2 +- ci-before-build.sh | 2 +- ci-test.sh | 3 ++ local/scipy_openblas64/__init__.py | 13 +++-- pyproject.toml | 3 ++ ...uild_prepare.sh => build_prepare_wheel.sh} | 5 +- tools/build_steps_win_arm64.bat | 21 ++++++-- tools/build_wheel.sh | 52 ------------------- 9 files changed, 47 insertions(+), 62 deletions(-) rename tools/{build_prepare.sh => build_prepare_wheel.sh} (86%) delete mode 100644 tools/build_wheel.sh diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index bbd61d9c..c2b34608 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -115,6 +115,7 @@ jobs: fi sed -e "s/bin/lib/" -i local/scipy_openblas64/lib/cmake/openblas/OpenBLASConfig.cmake sed -e "s/dll/lib/" -i local/scipy_openblas64/lib/cmake/openblas/OpenBLASConfig.cmake + mkdir local/scipy_openblas64/lib/pkgconfig if [[ "${INTERFACE64}" != "1" ]]; then mv local/scipy_openblas64 local/scipy_openblas32 # rewrite the name of the project to scipy-openblas32 @@ -125,6 +126,9 @@ jobs: sed -e "s/cflags =.*/cflags = '-DBLAS_SYMBOL_PREFIX=scipy_'/" -i local/scipy_openblas32/__init__.py sed -e "s/openblas64/openblas32/" -i local/scipy_openblas32/__init__.py sed -e "s/openblas64/openblas32/" -i local/scipy_openblas32/__main__.py + PYTHONPATH=$PWD/local python -c "import scipy_openblas32 as s; print(s.get_pkg_config(use_prefix=True))" > local/scipy_openblas32/lib/pkgconfig/scipy-openblas.pc + else + PYTHONPATH=$PWD/local python -c "import scipy_openblas64 as s; print(s.get_pkg_config(use_prefix=True))" > local/scipy_openblas64/lib/pkgconfig/scipy-openblas.pc fi echo "" >> LICENSE.txt echo "----" >> LICENSE.txt @@ -153,6 +157,8 @@ jobs: python -m pip install --no-index --find-links dist scipy_openblas64 python -m scipy_openblas64 python -c "import scipy_openblas64; print(scipy_openblas64.get_pkg_config())" + python -m pip install pkgconf + python -m pkgconf scipy-openblas --cflags - name: Test 32-bit interface wheel if: matrix.INTERFACE64 != '1' @@ -160,6 +166,8 @@ jobs: python -m pip install --no-index --find-links dist scipy_openblas32 python -m scipy_openblas32 python -c "import scipy_openblas32; print(scipy_openblas32.get_pkg_config())" + python -m pip install pkgconf + python -m pkgconf scipy-openblas --cflags - uses: conda-incubator/setup-miniconda@v3.1.1 with: diff --git a/README.md b/README.md index 650b06dc..813b16a4 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ First, tarballs are built using `build_lib` in `tools/build_steps.sh` (on posix in a docker and drectly on macos) or `tools/build_steps_windows.sh` on windows. Then the shared object and header files from the tarball are used to build the -wheel via `tools/build_wheel.sh`, and the wheels uploaded to +wheel via `tools/build_prepare_wheel.sh` and `pip build wheel`, and the wheels uploaded to https://anaconda.org/scientific=python-nightly-wheels/scipy_openblas32 and https://anaconda.org/scientific=python-nightly-wheels/scipy_openblas64 via `tools/upload_to_anaconda_staging.sh`. For a release, the wheels are uploaded diff --git a/ci-before-build.sh b/ci-before-build.sh index 83fbe493..1288d9da 100755 --- a/ci-before-build.sh +++ b/ci-before-build.sh @@ -73,4 +73,4 @@ unset -f popd source build-openblas.sh # Build wheel -source tools/build_prepare.sh +source tools/build_prepare_wheel.sh diff --git a/ci-test.sh b/ci-test.sh index 1a553636..326a5822 100755 --- a/ci-test.sh +++ b/ci-test.sh @@ -20,3 +20,6 @@ else # $PYTHON -m pip install --no-index --find-links /tmp/cibuildwheel/repaired_wheel scipy_openblas64 $PYTHON -m scipy_openblas64 fi + +$PYTHON -m pip install pkgconf +$PYTHON -m pkgconf scipy-openblas --cflags diff --git a/local/scipy_openblas64/__init__.py b/local/scipy_openblas64/__init__.py index 3d34ef76..5811416f 100644 --- a/local/scipy_openblas64/__init__.py +++ b/local/scipy_openblas64/__init__.py @@ -60,7 +60,7 @@ def get_library(fullname=False): # remove the leading lib from libscipy_openblas* return os.path.splitext(libs[0])[0][3:] -def get_pkg_config(use_preloading=False): +def get_pkg_config(use_preloading=False, use_prefix=False): """Return a multi-line string that, when saved to a file, can be used with pkg-config for build systems like meson @@ -81,9 +81,16 @@ def get_pkg_config(use_preloading=False): else: libs_flags = f"${{libdir}}/{get_library(fullname=True)} -Wl,-rpath,${{libdir}}" cflags = "-DBLAS_SYMBOL_PREFIX=scipy_ -DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64 -DOPENBLAS_ILP64_NAMING_SCHEME" + if use_prefix: + libdir = "${pcfiledir}/../../lib + incdir = "${pcfiledir}/../../include + else: + # Don't use `$prefix` since the file may be located outside the package tree + libdir = get_lib_dir() + incdir = get_include_dir() return dedent(f"""\ - libdir={get_lib_dir()} - includedir={get_include_dir()} + libdir={libdir} + includedir={incdir} openblas_config= {get_openblas_config()} version={get_openblas_config().split(" ")[1]} extralib={extralib} diff --git a/pyproject.toml b/pyproject.toml index c538cb82..a1f01f0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,3 +57,6 @@ environment-pass = [ ] [tool.cibuildwheel.linux] environment = { CC = "/opt/clang/bin/clang", CXX = "/opt/clang/bin/clang++", LDFLAGS = "-fuse-ld=lld" } + +[tool.entry-points.pkg_config] +scipy-openblas = scipy_openblas64/lib/pkgconfig diff --git a/tools/build_prepare.sh b/tools/build_prepare_wheel.sh similarity index 86% rename from tools/build_prepare.sh rename to tools/build_prepare_wheel.sh index dbfc303d..844bc171 100644 --- a/tools/build_prepare.sh +++ b/tools/build_prepare_wheel.sh @@ -11,7 +11,6 @@ PYTHON=${PYTHON:-python3.9} mkdir -p local/openblas mkdir -p dist -$PYTHON -m pip install wheel auditwheel tar -C local/scipy_openblas64 --strip-components=2 -xf libs/openblas.tar.gz @@ -40,6 +39,7 @@ if [ $(uname) == "Darwin" ]; then fi rm -rf local/scipy_openblas64/lib/pkgconfig +mkdir local/scipy_openblas64/lib/pkgconfig echo "" >> LICENSE.txt echo "----" >> LICENSE.txt echo "" >> LICENSE.txt @@ -63,6 +63,9 @@ if [ "${INTERFACE64}" != "1" ]; then sed -e "s/openblas64/openblas32/" -i.bak local/scipy_openblas32/__main__.py sed -e "s/openblas64/openblas32/" -i.bak local/scipy_openblas32/__init__.py rm local/scipy_openblas32/*.bak + PYTHONPATH=$PWD/local python -c "import scipy_openblas32 as s; print(s.get_pkg_config(use_prefix=True))" > local/scipy_openblas32/lib/pkgconfig/scipy-openblas.pc +else + PYTHONPATH=$PWD/local python -c "import scipy_openblas64 as s; print(s.get_pkg_config(use_prefix=True))" > local/scipy_openblas64/lib/pkgconfig/scipy-openblas.pc fi rm -rf dist/* diff --git a/tools/build_steps_win_arm64.bat b/tools/build_steps_win_arm64.bat index 21c997c4..2d84f6fe 100755 --- a/tools/build_steps_win_arm64.bat +++ b/tools/build_steps_win_arm64.bat @@ -123,10 +123,18 @@ if "%if_bits%"=="32" ( cd ../.. set out_pyproject=pyproject_64_32.toml powershell -Command "(Get-Content 'pyproject.toml') -replace 'openblas64', 'openblas32' | Set-Content !out_pyproject!" - powershell -Command "(Get-Content 'local\scipy_openblas32\__main__.py') -replace 'openblas64', 'openblas32' | Out-File 'local\scipy_openblas32\__main__.py' -Encoding utf8" - powershell -Command "(Get-Content 'local\scipy_openblas32\__init__.py') -replace 'openblas64', 'openblas32' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8" - powershell -Command "(Get-Content 'local\scipy_openblas32\__init__.py') -replace 'openblas_get_config64_', 'openblas_get_config' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8" - powershell -Command "(Get-Content 'local\scipy_openblas32\__init__.py') -replace 'cflags =.*', 'cflags = \"-DBLAS_SYMBOL_PREFIX=scipy_\"' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8" + cd local + move scipy_openblas64 scipy_openblas32 + powershell -Command "(Get-Content 'scipy_openblas32\__main__.py') -replace 'openblas64', 'openblas32' | Out-File 'scipy_openblas32\__main__.py' -Encoding utf8" + powershell -Command "(Get-Content 'scipy_openblas32\__init__.py') -replace 'openblas64', 'openblas32' | Out-File 'scipy_openblas32\__init__.py' -Encoding utf8" + powershell -Command "(Get-Content 'scipy_openblas32\__init__.py') -replace 'openblas_get_config64_', 'openblas_get_config' | Out-File 'scipy_openblas32\__init__.py' -Encoding utf8" + powershell -Command "(Get-Content 'scipy_openblas32\__init__.py') -replace 'cflags =.*', 'cflags = \"-DBLAS_SYMBOL_PREFIX=scipy_\"' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8" + mkdir scipy_openblas32\lib\pkgconfig + python -c "import scipy_openblas32 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas32/lib/pkgconfig/scipy-openblas.pc +) else ( + cd local + mkdir scipy_openblas64\lib\pkgconfig + python -c "import scipy_openblas64 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas64/lib/pkgconfig/scipy-openblas.pc ) :: Prepare destination directory @@ -208,5 +216,10 @@ echo Installing wheel: %WHEEL_FILE% pip install "%WHEEL_FILE%" if errorlevel 1 exit /b 1 +echo Testing +python -m pip install pkgconf +python -m pkgconf scipy-openblas --cflags +if errorlevel 1 exit /b 1 + echo Done. exit /b 0 diff --git a/tools/build_wheel.sh b/tools/build_wheel.sh deleted file mode 100644 index cb3aa921..00000000 --- a/tools/build_wheel.sh +++ /dev/null @@ -1,52 +0,0 @@ -#! /bin/bash -# Needs: -# $INTERFACE64 ("1" or "0") -# $PLAT (x86_64, i686, arm64, aarch64, s390x, ppc64le) - -set -xe - -if [[ ! -e tools/build_prepare.sh ]];then - cd /openblas -fi - -source tools/build_prepare.sh - -$PYTHON -m pip wheel -w dist -v . - -echo "Repairing wheel with auditwheel" -auditwheel repair -w dist --lib-sdir /lib dist/*.whl -echo "Wheel repaired." - -rm dist/*none-linux*.whl - -ls -l dist/ - -# Add an RPATH to libgfortran: -# https://github.com/pypa/auditwheel/issues/451 -if [ "$MB_ML_LIBC" == "musllinux" ]; then - apk add zip -else - yum install -y zip -fi -unzip dist/*.whl "*libgfortran*" -patchelf --force-rpath --set-rpath '$ORIGIN' */lib/libgfortran* -zip dist/*.whl */lib/libgfortran* - -echo "Final wheel contents:" - -ls -l dist/ - -echo "Testing the wheel" - -# Test that the wheel works with a different python -PYTHON=python3.11 - -if [ "${INTERFACE64}" != "1" ]; then - $PYTHON -m pip install --no-index --find-links dist scipy_openblas32 - $PYTHON -m scipy_openblas32 -else - $PYTHON -m pip install --no-index --find-links dist scipy_openblas64 - $PYTHON -m scipy_openblas64 -fi - -echo "Wheel test successful." From ae9012dc28423f4c04f7f37dcb4238f38d6cc395 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 18 Dec 2025 13:44:16 +0200 Subject: [PATCH 02/11] typo --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a1f01f0e..d1cd7c27 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "scipy-openblas64" # v0.3.30-359-g29fab2b9 -version = "0.3.30.359.1" +version = "0.3.30.359.2" requires-python = ">=3.7" description = "Provides OpenBLAS for python packaging" readme = "README.md" @@ -59,4 +59,4 @@ environment-pass = [ environment = { CC = "/opt/clang/bin/clang", CXX = "/opt/clang/bin/clang++", LDFLAGS = "-fuse-ld=lld" } [tool.entry-points.pkg_config] -scipy-openblas = scipy_openblas64/lib/pkgconfig +scipy-openblas = 'scipy_openblas64.lib.pkgconfig' From beb25a61b12a11acffcb028eb91914da4ac38cda Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 18 Dec 2025 15:02:05 +0200 Subject: [PATCH 03/11] typos --- local/scipy_openblas64/__init__.py | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/local/scipy_openblas64/__init__.py b/local/scipy_openblas64/__init__.py index 5811416f..70706f49 100644 --- a/local/scipy_openblas64/__init__.py +++ b/local/scipy_openblas64/__init__.py @@ -82,8 +82,8 @@ def get_pkg_config(use_preloading=False, use_prefix=False): libs_flags = f"${{libdir}}/{get_library(fullname=True)} -Wl,-rpath,${{libdir}}" cflags = "-DBLAS_SYMBOL_PREFIX=scipy_ -DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64 -DOPENBLAS_ILP64_NAMING_SCHEME" if use_prefix: - libdir = "${pcfiledir}/../../lib - incdir = "${pcfiledir}/../../include + libdir = "${pcfiledir}/../../lib" + incdir = "${pcfiledir}/../../include" else: # Don't use `$prefix` since the file may be located outside the package tree libdir = get_lib_dir() diff --git a/pyproject.toml b/pyproject.toml index d1cd7c27..9922c2c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,5 +58,5 @@ environment-pass = [ [tool.cibuildwheel.linux] environment = { CC = "/opt/clang/bin/clang", CXX = "/opt/clang/bin/clang++", LDFLAGS = "-fuse-ld=lld" } -[tool.entry-points.pkg_config] +[project.entry-points.pkg_config] scipy-openblas = 'scipy_openblas64.lib.pkgconfig' From e4ed8ce21264fe7228670598859a53c764cd751c Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 18 Dec 2025 21:02:04 +0200 Subject: [PATCH 04/11] fix running python to get scipy-openblas.pc --- local/scipy_openblas64/__init__.py | 5 ++++- tools/build_prepare_wheel.sh | 9 +++++++-- tools/build_steps_win_arm64.bat | 27 +++++++++++++++------------ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/local/scipy_openblas64/__init__.py b/local/scipy_openblas64/__init__.py index 70706f49..59e7214a 100644 --- a/local/scipy_openblas64/__init__.py +++ b/local/scipy_openblas64/__init__.py @@ -67,10 +67,13 @@ def get_pkg_config(use_preloading=False, use_prefix=False): If use_preloading is True then on posix the ``Libs:`` directive will not add ``f"-L{get_library()}" so that at runtime this module must be imported before the target module + + If use_prefix is True, then `pcfiledir` will be used and the file should be + stored in `dirname(__file__)/lib/pkgconfig` for use with pkgconf-pypi """ - machine = platform.machine().lower() extralib = "" if sys.platform == "win32": + machine = platform.machine().lower() if machine != "arm64": extralib = "-defaultlib:advapi32 -lgfortran -lquadmath" libs_flags = f"-L${{libdir}} -l{get_library()}" diff --git a/tools/build_prepare_wheel.sh b/tools/build_prepare_wheel.sh index 844bc171..7a883c59 100644 --- a/tools/build_prepare_wheel.sh +++ b/tools/build_prepare_wheel.sh @@ -49,6 +49,11 @@ else cat tools/LICENSE_linux.txt >> LICENSE.txt fi +if [ "$(uname)" == "Darwin" -a "${PLAT}" == "x86_64" ]; then + local PYTHON="arch -x86_64 python3" +else + local PYTHON=python3 +fi if [ "${INTERFACE64}" != "1" ]; then # rewrite the name of the project to scipy-openblas32 # this is a hack, but apparently there is no other way to change the name @@ -63,9 +68,9 @@ if [ "${INTERFACE64}" != "1" ]; then sed -e "s/openblas64/openblas32/" -i.bak local/scipy_openblas32/__main__.py sed -e "s/openblas64/openblas32/" -i.bak local/scipy_openblas32/__init__.py rm local/scipy_openblas32/*.bak - PYTHONPATH=$PWD/local python -c "import scipy_openblas32 as s; print(s.get_pkg_config(use_prefix=True))" > local/scipy_openblas32/lib/pkgconfig/scipy-openblas.pc + PYTHONPATH=$PWD/local $PYTHON -c "import scipy_openblas32 as s; print(s.get_pkg_config(use_prefix=True))" > local/scipy_openblas32/lib/pkgconfig/scipy-openblas.pc else - PYTHONPATH=$PWD/local python -c "import scipy_openblas64 as s; print(s.get_pkg_config(use_prefix=True))" > local/scipy_openblas64/lib/pkgconfig/scipy-openblas.pc + PYTHONPATH=$PWD/local $PYTHON -c "import scipy_openblas64 as s; print(s.get_pkg_config(use_prefix=True))" > local/scipy_openblas64/lib/pkgconfig/scipy-openblas.pc fi rm -rf dist/* diff --git a/tools/build_steps_win_arm64.bat b/tools/build_steps_win_arm64.bat index 2d84f6fe..19ee23a1 100755 --- a/tools/build_steps_win_arm64.bat +++ b/tools/build_steps_win_arm64.bat @@ -118,28 +118,21 @@ if errorlevel 1 exit /b 1 echo Build complete. Returning to Batch. +cd ../../local if "%if_bits%"=="32" ( echo Rewrite to scipy_openblas32 - cd ../.. set out_pyproject=pyproject_64_32.toml powershell -Command "(Get-Content 'pyproject.toml') -replace 'openblas64', 'openblas32' | Set-Content !out_pyproject!" - cd local move scipy_openblas64 scipy_openblas32 powershell -Command "(Get-Content 'scipy_openblas32\__main__.py') -replace 'openblas64', 'openblas32' | Out-File 'scipy_openblas32\__main__.py' -Encoding utf8" powershell -Command "(Get-Content 'scipy_openblas32\__init__.py') -replace 'openblas64', 'openblas32' | Out-File 'scipy_openblas32\__init__.py' -Encoding utf8" powershell -Command "(Get-Content 'scipy_openblas32\__init__.py') -replace 'openblas_get_config64_', 'openblas_get_config' | Out-File 'scipy_openblas32\__init__.py' -Encoding utf8" powershell -Command "(Get-Content 'scipy_openblas32\__init__.py') -replace 'cflags =.*', 'cflags = \"-DBLAS_SYMBOL_PREFIX=scipy_\"' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8" - mkdir scipy_openblas32\lib\pkgconfig - python -c "import scipy_openblas32 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas32/lib/pkgconfig/scipy-openblas.pc -) else ( - cd local - mkdir scipy_openblas64\lib\pkgconfig - python -c "import scipy_openblas64 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas64/lib/pkgconfig/scipy-openblas.pc ) :: Prepare destination directory -cd OpenBLAS/build -echo Preparing destination directory at %DEST_DIR%... +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" @@ -175,9 +168,19 @@ if exist openblas_config.h copy /Y openblas_config.h "%DEST_DIR%\include\" echo Copying LAPACKE header files... xcopy /Y "..\lapack-netlib\lapacke\include\*.h" "%DEST_DIR%\include\" if errorlevel 1 exit /b 1 - + +:: Create pkgconfig scipy-openblas.pc +cd ../../local +if "%if_bits%"=="32" ( + mkdir scipy_openblas32\lib\pkgconfig + python -c "import scipy_openblas32 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas32/lib/pkgconfig/scipy-openblas.pc +) else ( + mkdir scipy_openblas64\lib\pkgconfig + python -c "import scipy_openblas64 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas64/lib/pkgconfig/scipy-openblas.pc +) + :: Move back to the root directory -cd ../.. +cd /.. :: Build the Wheel & Install It echo Running 'python -m build' to build the wheel... From 42548cd7848419435b69a54b83b7d8b918a9e052 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 18 Dec 2025 22:52:03 +0200 Subject: [PATCH 05/11] debugging, fix script --- tools/build_prepare_wheel.sh | 4 ++-- tools/build_steps_win_arm64.bat | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/build_prepare_wheel.sh b/tools/build_prepare_wheel.sh index 7a883c59..a6ef2604 100644 --- a/tools/build_prepare_wheel.sh +++ b/tools/build_prepare_wheel.sh @@ -50,9 +50,9 @@ else fi if [ "$(uname)" == "Darwin" -a "${PLAT}" == "x86_64" ]; then - local PYTHON="arch -x86_64 python3" + PYTHON="arch -x86_64 python3" else - local PYTHON=python3 + PYTHON=python3 fi if [ "${INTERFACE64}" != "1" ]; then # rewrite the name of the project to scipy-openblas32 diff --git a/tools/build_steps_win_arm64.bat b/tools/build_steps_win_arm64.bat index 19ee23a1..3e269df4 100755 --- a/tools/build_steps_win_arm64.bat +++ b/tools/build_steps_win_arm64.bat @@ -171,6 +171,10 @@ if errorlevel 1 exit /b 1 :: Create pkgconfig scipy-openblas.pc cd ../../local +if errorlevel 1 ( + echo Current directory %CD%, cannot cd ../../local + exit /b 1 +) if "%if_bits%"=="32" ( mkdir scipy_openblas32\lib\pkgconfig python -c "import scipy_openblas32 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas32/lib/pkgconfig/scipy-openblas.pc @@ -178,9 +182,17 @@ if "%if_bits%"=="32" ( mkdir scipy_openblas64\lib\pkgconfig python -c "import scipy_openblas64 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas64/lib/pkgconfig/scipy-openblas.pc ) +if errorlevel 1 ( + echo could not construct scipy-openblas.pc + exit /b 1 +) :: Move back to the root directory cd /.. +if errorlevel 1 ( + echo Current directory %CD%, cannot cd ../../local + exit /b 1 +) :: Build the Wheel & Install It echo Running 'python -m build' to build the wheel... From 3c892ced7fed97c2859ac14105779f88a152830b Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 19 Dec 2025 09:12:38 +0200 Subject: [PATCH 06/11] typo --- tools/build_steps_win_arm64.bat | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/build_steps_win_arm64.bat b/tools/build_steps_win_arm64.bat index 3e269df4..1e421164 100755 --- a/tools/build_steps_win_arm64.bat +++ b/tools/build_steps_win_arm64.bat @@ -169,7 +169,7 @@ echo Copying LAPACKE header files... xcopy /Y "..\lapack-netlib\lapacke\include\*.h" "%DEST_DIR%\include\" if errorlevel 1 exit /b 1 -:: Create pkgconfig scipy-openblas.pc +echo Create pkgconfig scipy-openblas.pc cd ../../local if errorlevel 1 ( echo Current directory %CD%, cannot cd ../../local @@ -188,14 +188,14 @@ if errorlevel 1 ( ) :: Move back to the root directory -cd /.. +cd .. if errorlevel 1 ( - echo Current directory %CD%, cannot cd ../../local + echo Current directory %CD%, cannot cd .. exit /b 1 ) :: Build the Wheel & Install It -echo Running 'python -m build' to build the wheel... +echo Running 'python -m build' to build the wheel in %CD% python -c "import build" 2>NUL || pip install build if "%if_bits%"=="64" ( python -m build From 3a6fa6e01b8855066e58e2e43c82b03dcefa679a Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 19 Dec 2025 10:34:39 +0200 Subject: [PATCH 07/11] consolidate windows builds --- .github/workflows/windows-arm.yml | 98 ------------ .github/workflows/windows.yml | 30 +++- tools/build_steps_win_arm64.bat | 240 ------------------------------ tools/build_steps_windows.sh | 6 + 4 files changed, 30 insertions(+), 344 deletions(-) delete mode 100644 .github/workflows/windows-arm.yml delete mode 100755 tools/build_steps_win_arm64.bat diff --git a/.github/workflows/windows-arm.yml b/.github/workflows/windows-arm.yml deleted file mode 100644 index 01c66e21..00000000 --- a/.github/workflows/windows-arm.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: Windows-on-ARM - -on: - push: - branches: [ main ] - pull_request: - branches: - - main - - maintenance/** - -env: - OPENBLAS_ROOT: "c:\\opt" - # Preserve working directory for calls into bash - # Without this, invoking bash will cd to the home directory - CHERE_INVOKING: "yes" - BASH_PATH: "C:\\Program Files\\Git\\bin\\bash.exe" - PLAT: arm64 - -jobs: - build: - runs-on: windows-11-arm - timeout-minutes: 90 - - strategy: - matrix: - INTERFACE64: ['1', '0'] - - env: - INTERFACE64: ${{ matrix.INTERFACE64 }} - - steps: - - - uses: actions/checkout@v4.1.1 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: 3.12 - architecture: arm64 - - - name: Download and install LLVM installer - run: | - Invoke-WebRequest https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.8/LLVM-20.1.8-woa64.exe -UseBasicParsing -OutFile LLVM-woa64.exe - Start-Process -FilePath ".\LLVM-woa64.exe" -ArgumentList "/S" -Wait - echo "C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - - name: Install CMake and Ninja for Win-ARM64 - shell: pwsh - run: | - Invoke-WebRequest https://github.com/Kitware/CMake/releases/download/v3.29.4/cmake-3.29.4-windows-arm64.msi -OutFile cmake-arm64.msi - Start-Process msiexec.exe -ArgumentList "/i cmake-arm64.msi /quiet /norestart" -Wait - echo "C:\Program Files\CMake\bin" >> $env:GITHUB_PATH - - Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.13.1/ninja-winarm64.zip -OutFile ninja-winarm64.zip - Expand-Archive ninja-winarm64.zip -DestinationPath ninja - Copy-Item ninja\ninja.exe -Destination "C:\Windows\System32" - - - name: Set env variables - run: | - if ( ${{ matrix.INTERFACE64 }} -eq "1" ) { - echo "INTERFACE_BITS=64" >> $env:GITHUB_ENV - } else { - echo "INTERFACE_BITS=32" >> $env:GITHUB_ENV - } - - - name: Build - run: | - git submodule update --init --recursive - .\tools\build_steps_win_arm64.bat 64 ${env:INTERFACE_BITS} - - - name: Test ${{ matrix.INTERFACE_BITS }}-bit interface wheel - run: | - python -m pip install --no-index --find-links dist scipy_openblas${env:INTERFACE_BITS} - python -m scipy_openblas${env:INTERFACE_BITS} - python -c "import scipy_openblas${env:INTERFACE_BITS}; print(scipy_openblas${env:INTERFACE_BITS}.get_pkg_config())" - - - uses: actions/upload-artifact@v4.3.0 - with: - name: wheels-${{ env.PLAT }}-${{ env.INTERFACE64 }} - path: dist/scipy_openblas*.whl - - - name: Install Anaconda client - run: | - # Rust installation needed for rpds-py. - Invoke-WebRequest https://static.rust-lang.org/rustup/dist/aarch64-pc-windows-msvc/rustup-init.exe -UseBasicParsing -Outfile rustup-init.exe - .\rustup-init.exe -y - $env:PATH="$env:PATH;$env:USERPROFILE\.cargo\bin" - pip install anaconda-client - - - name: Upload - # see https://github.com/marketplace/actions/setup-miniconda for why - # `-el {0}` is required. - shell: bash -el {0} - env: - ANACONDA_SCIENTIFIC_PYTHON_UPLOAD: ${{ secrets.ANACONDA_SCIENTIFIC_PYTHON_UPLOAD }} - run: | - source tools/upload_to_anaconda_staging.sh - upload_wheels diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index c2b34608..b7f4f172 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -20,23 +20,33 @@ jobs: build: strategy: matrix: - plat: ['x64', 'x86'] - INTERFACE64: ['1', '0'] - os: [windows-latest] - exclude: - - plat: x86 - INTERFACE64: '1' + include: + - { os: windows-latest, PLAT: x86, INTERFACE64: '0'} + - { os: windows-latest, PLAT: x64, INTERFACE64: '0'} + - { os: windows-latest, PLAT: x64, INTERFACE64: '1'} + - { os: windows-11-arm, PLAT: arm64, INTERFACE64: '0'} + - { os: windows-11-arm, PLAT: arm64, INTERFACE64: '1'} fail-fast: false runs-on: ${{ matrix.os }} timeout-minutes: 90 steps: - uses: actions/checkout@v4.1.1 + - name: install-rtools + if: matrix.os == 'windows-latest' run: | # rtools 42+ does not support 32 bits builds. choco install -y rtools --no-progress --force --version=4.0.0.20220206 + - name: Download and install LLVM installer + if: matrix.os == 'windows-11-arm' + run: | + Invoke-WebRequest https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.8/LLVM-20.1.8-woa64.exe -UseBasicParsing -OutFile LLVM-woa64.exe + Start-Process -FilePath ".\LLVM-woa64.exe" -ArgumentList "/S" -Wait + echo "C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Set env variables run: | echo "START_DIR=$PWD" >> $env:GITHUB_ENV @@ -56,6 +66,9 @@ jobs: echo "LDFLAGS=-lucrt -static -static-libgcc -Wl,--defsym,quadmath_snprintf=snprintf" >> $env:GITHUB_ENV echo "BUILD_BITS=64" >> $env:GITHUB_ENV } + if ( "${{ matrix.plat }}" -eq "arm64") { + echo "PLAT=arm64" >> $env:GITHUB_ENV + } if ( ${{ matrix.INTERFACE64 }} -eq "1" ) { echo "INTERFACE64=1" >> $env:GITHUB_ENV } @@ -69,6 +82,11 @@ jobs: - name: Build run: | + if ( "${{ matrix.plat }}" -eq "arm64") { + echo Setting up ARM64 Developer Command Prompt + CALL "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsarm64.bat" + PATH=C:\Program Files\LLVM\bin;%PATH% + } git submodule update --init --recursive & $env:BASH_PATH -lc tools/build_steps_windows.sh diff --git a/tools/build_steps_win_arm64.bat b/tools/build_steps_win_arm64.bat deleted file mode 100755 index 1e421164..00000000 --- a/tools/build_steps_win_arm64.bat +++ /dev/null @@ -1,240 +0,0 @@ -:: 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. -set first_woa_buildable_commit="de2380e5a6149706a633322a16a0f66faa5591fc" - -@echo off -setlocal enabledelayedexpansion - -if "%1"=="" ( - set build_bits=64 -) else ( - set build_bits=%1 -) -if "%INTERFACE64%"=="1" ( - set "if_default=64" -) else ( - set "if_default=32" -) -if "%2"=="" ( - set "if_bits=%if_default%" -) else ( - set "if_bits=%2" -) -echo Building for %build_bits%-bit binary, %if_bits%-bit interface... - -:: Define destination directory -pushd "%~dp0\.." -set "ob_out_root=%CD%\local\scipy_openblas" -set "ob_64=%ob_out_root%64" -set "ob_32=%ob_out_root%32" -set "local_dir=%CD%\local" -for /d %%D in ("%local_dir%\*") do ( - if /I not "%%~nxD"=="scipy_openblas64" ( - rmdir /S /Q "%%D" - ) -) -if "%if_bits%"=="64" ( - set "DEST_DIR=%ob_64%" -) else ( - if exist "%ob_64%" ( - xcopy /Y /H "%ob_64%\*.py" "%CD%\ob64_backup\" - move "%ob_64%" "%ob_32%" - set "DEST_DIR=%ob_32%" - ) -) - -:: 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 -if errorlevel 1 ( - echo OpenBLAS commit does not contain WoA build fixes. - echo Commit needs to contain %first_woa_buildable_commit%. - exit /b 2 -) - -:: Patch -for /r %%f in (..\patches\*) do git apply %%f -if errorlevel 1 exit /b 1 - -:: 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 -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 -CALL "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsarm64.bat" - -:: Prefer LLVM flang -PATH=C:\Program Files\LLVM\bin;%PATH% - -:: 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 ^ - -DCMAKE_BUILD_TYPE=Release ^ - -DTARGET=ARMV8 ^ - -DBINARY=%build_bits% ^ - -DCMAKE_C_COMPILER=clang-cl ^ - -DCMAKE_Fortran_COMPILER=flang-new ^ - -DBUILD_SHARED_LIBS=ON ^ - -DCMAKE_SYSTEM_PROCESSOR=arm64 ^ - -DCMAKE_SYSTEM_NAME=Windows ^ - -DSYMBOLPREFIX="scipy_" ^ - -DLIBNAMEPREFIX="scipy_" ^ - -DUSE_THREADS=1 ^ - -DNUM_THREADS=24 ^ - %interface_flags% - -if errorlevel 1 exit /b 1 - -ninja -j 16 -if errorlevel 1 exit /b 1 - -echo Build complete. Returning to Batch. - -cd ../../local -if "%if_bits%"=="32" ( - echo Rewrite to scipy_openblas32 - set out_pyproject=pyproject_64_32.toml - powershell -Command "(Get-Content 'pyproject.toml') -replace 'openblas64', 'openblas32' | Set-Content !out_pyproject!" - move scipy_openblas64 scipy_openblas32 - powershell -Command "(Get-Content 'scipy_openblas32\__main__.py') -replace 'openblas64', 'openblas32' | Out-File 'scipy_openblas32\__main__.py' -Encoding utf8" - powershell -Command "(Get-Content 'scipy_openblas32\__init__.py') -replace 'openblas64', 'openblas32' | Out-File 'scipy_openblas32\__init__.py' -Encoding utf8" - powershell -Command "(Get-Content 'scipy_openblas32\__init__.py') -replace 'openblas_get_config64_', 'openblas_get_config' | Out-File 'scipy_openblas32\__init__.py' -Encoding utf8" - powershell -Command "(Get-Content 'scipy_openblas32\__init__.py') -replace 'cflags =.*', 'cflags = \"-DBLAS_SYMBOL_PREFIX=scipy_\"' | Out-File 'local\scipy_openblas32\__init__.py' -Encoding utf8" -) - -:: 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 -echo Moving library files... -if exist lib\release ( - move /Y lib\release\*.dll "%DEST_DIR%\lib\" - if errorlevel 1 exit /b 1 - for %%f in (lib\release\*.dll.a) do ( - set "orig_name=%%~nxf" - call set "base_name=%%orig_name:.dll.a=%%" - move /Y "%%f" "%DEST_DIR%\lib\!base_name!.lib" - ) - if errorlevel 1 exit /b 1 -) else ( - echo Error: lib/release directory not found! - exit /b 1 -) - -:: 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 -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 -echo Copying LAPACKE header files... -xcopy /Y "..\lapack-netlib\lapacke\include\*.h" "%DEST_DIR%\include\" -if errorlevel 1 exit /b 1 - -echo Create pkgconfig scipy-openblas.pc -cd ../../local -if errorlevel 1 ( - echo Current directory %CD%, cannot cd ../../local - exit /b 1 -) -if "%if_bits%"=="32" ( - mkdir scipy_openblas32\lib\pkgconfig - python -c "import scipy_openblas32 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas32/lib/pkgconfig/scipy-openblas.pc -) else ( - mkdir scipy_openblas64\lib\pkgconfig - python -c "import scipy_openblas64 as s; print(s.get_pkg_config(use_prefix=True))" > scipy_openblas64/lib/pkgconfig/scipy-openblas.pc -) -if errorlevel 1 ( - echo could not construct scipy-openblas.pc - exit /b 1 -) - -:: Move back to the root directory -cd .. -if errorlevel 1 ( - echo Current directory %CD%, cannot cd .. - exit /b 1 -) - -:: 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" ( - python -m build - if errorlevel 1 exit /b 1 -) else ( - move /Y pyproject.toml pyproject.toml.bak - move /Y %out_pyproject% pyproject.toml - python -m build - if errorlevel 1 exit /b 1 - move /Y pyproject.toml.bak pyproject.toml -) -if "%if_bits%"=="32" ( - move /Y "%CD%\ob64_backup" "%ob_64%" -) - -:: Rename the wheel -for %%f in (dist\*any.whl) do ( - set WHEEL_FILE=dist\%%f - set "filename=%%~nxf" - set "newname=!filename:any.whl=win_arm64.whl!" - ren "dist\!filename!" "!newname!" -) - -:: 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 ( - echo Error: No wheel file found in dist folder. - exit /b 1 -) - -echo Installing wheel: %WHEEL_FILE% -pip install "%WHEEL_FILE%" -if errorlevel 1 exit /b 1 - -echo Testing -python -m pip install pkgconf -python -m pkgconf scipy-openblas --cflags -if errorlevel 1 exit /b 1 - -echo Done. -exit /b 0 diff --git a/tools/build_steps_windows.sh b/tools/build_steps_windows.sh index 5ae3cc36..515662e5 100644 --- a/tools/build_steps_windows.sh +++ b/tools/build_steps_windows.sh @@ -14,6 +14,7 @@ # This gives the default value if if_bits not specified above). # START_DIR (directory containing OpenBLAS source, unspec -> .. from here) # LDFLAGS (example: "-lucrt -static -static-libgcc") +# PLAT (x86_64 or arm64) # # Expects at leasts these binaries on the PATH: # realpath, cygpath, zip, gcc, make, ar, dlltool @@ -70,6 +71,11 @@ else plat_tag="win32" dynamic_list="PRESCOTT NEHALEM SANDYBRIDGE HASWELL" fi +if [ "$PLAT" == "arm64" ]; then + CC=clangcl + FC=flang-new + extra="-Wno-reserved-macro-identifier -Wno-unsafe-buffer-usage -Wno-unused-macros -Wno-sign-conversion -Wno-reserved-identifier" +fi cflags="-O2 -march=$march -mtune=generic $extra" fflags="$fextra $cflags -frecursive -ffpe-summary=invalid,zero" From d3b57144d1fda39d58423fd1d3fd21f4c1295f3c Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 19 Dec 2025 11:47:11 +0200 Subject: [PATCH 08/11] use cmd shell to setup build --- .github/workflows/windows.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b7f4f172..07b11942 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -81,14 +81,16 @@ jobs: echo CIBW_ENVIRONMENT_WINDOWS=$env:CIBW_ENVIRONMENT_WINDOWS - name: Build + shell: cmd run: | - if ( "${{ matrix.plat }}" -eq "arm64") { + if "${{ matrix.plat }}" == "arm64" ( echo Setting up ARM64 Developer Command Prompt CALL "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsarm64.bat" + if errorlevel 1 exit /b 1 PATH=C:\Program Files\LLVM\bin;%PATH% - } + ) git submodule update --init --recursive - & $env:BASH_PATH -lc tools/build_steps_windows.sh + %BASH_PATH% -lc tools/build_steps_windows.sh - name: Test run: | From bdd632262971705a454de4b9b466c58e3c604783 Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 19 Dec 2025 12:08:21 +0200 Subject: [PATCH 09/11] no need for vcvarsarm --- .github/workflows/windows.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 07b11942..b6d95006 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -81,14 +81,7 @@ jobs: echo CIBW_ENVIRONMENT_WINDOWS=$env:CIBW_ENVIRONMENT_WINDOWS - name: Build - shell: cmd run: | - if "${{ matrix.plat }}" == "arm64" ( - echo Setting up ARM64 Developer Command Prompt - CALL "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsarm64.bat" - if errorlevel 1 exit /b 1 - PATH=C:\Program Files\LLVM\bin;%PATH% - ) git submodule update --init --recursive %BASH_PATH% -lc tools/build_steps_windows.sh From 2b3b9d23a22019fba4139a9c24d98e83c46f317a Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 19 Dec 2025 12:22:55 +0200 Subject: [PATCH 10/11] typo --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b6d95006..a6c5aef3 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -83,7 +83,7 @@ jobs: - name: Build run: | git submodule update --init --recursive - %BASH_PATH% -lc tools/build_steps_windows.sh + & $env:BASH_PATH -lc tools/build_steps_windows.sh - name: Test run: | From ab3b56e6f3dc53d4233feb772203acac92ee9f7d Mon Sep 17 00:00:00 2001 From: mattip Date: Fri, 19 Dec 2025 12:32:27 +0200 Subject: [PATCH 11/11] use bash --- .github/workflows/windows.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index a6c5aef3..0df4dfc9 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -81,17 +81,19 @@ jobs: echo CIBW_ENVIRONMENT_WINDOWS=$env:CIBW_ENVIRONMENT_WINDOWS - name: Build + shell: bash run: | git submodule update --init --recursive - & $env:BASH_PATH -lc tools/build_steps_windows.sh + bash -lc tools/build_steps_windows.sh - name: Test + shell: bash run: | - & $env:BASH_PATH -lc tools/build_gfortran.sh + bash -lc tools/build_gfortran.sh echo "Static test" - .\for_test\test.exe + ./for_test/test.exe echo "Dynamic test" - .\for_test\test_dyn.exe + ./for_test/test_dyn.exe - name: Copy run: |