diff --git a/.github/workflows/posix.yml b/.github/workflows/posix.yml index cddbf3b2..c1e0a7ea 100644 --- a/.github/workflows/posix.yml +++ b/.github/workflows/posix.yml @@ -20,6 +20,7 @@ on: jobs: build: + name: ${{ matrix.MB_ML_LIBC }}_${{ matrix.PLAT}}, ${{ matrix.INTERFACE64 == '1' && '64' || '32' }} runs-on: ${{ matrix.os }} defaults: run: @@ -57,12 +58,15 @@ jobs: - { os: ubuntu-24.04-arm, PLAT: riscv64, INTERFACE64: '0', MB_ML_VER: '_2_39', MB_ML_LIBC: manylinux} - { os: ubuntu-24.04-arm, PLAT: riscv64, INTERFACE64: '1', MB_ML_VER: '_2_39', MB_ML_LIBC: manylinux} + - { os: ubuntu-latest, PLAT: x86_64, INTERFACE64: '0', MB_ML_LIBC: android} + - { os: ubuntu-latest, PLAT: x86_64, INTERFACE64: '1', MB_ML_LIBC: android} + + - { os: ubuntu-latest, PLAT: arm64_v8a, INTERFACE64: '0', MB_ML_LIBC: android} + - { os: ubuntu-latest, PLAT: arm64_v8a, INTERFACE64: '1', MB_ML_LIBC: android} + env: NIGHTLY: ${{ inputs.publish == false && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') }} - MB_ML_LIBC: ${{ matrix.MB_ML_LIBC }} - MB_ML_VER: ${{ matrix.MB_ML_VER }} INTERFACE64: ${{ matrix.INTERFACE64 }} - PLAT: ${{ matrix.PLAT }} steps: - uses: actions/checkout@v6.0.1 @@ -82,10 +86,6 @@ jobs: with: platforms: all - - name: Print some Environment variable - run: | - echo "PLAT: ${PLAT}" - # - name: Setup tmate session # if: ${{ failure() }} # uses: mxschmitt/action-tmate@v3 @@ -96,11 +96,12 @@ jobs: uses: pypa/cibuildwheel@v4.1.0 timeout-minutes: 60 with: + # For Android, cibuildwheel has a minimum of Python 3.13, but the exact version + # doesn't matter because setup.py will replace the tag with "py3". + only: "cp313-${{ matrix.MB_ML_LIBC }}_${{matrix.PLAT}}" output-dir: dist env: - CIBW_ARCHS: ${{matrix.PLAT}} CIBW_BUILD_VERBOSITY: 1 - CIBW_BUILD: "cp39-${{ matrix.MB_ML_LIBC }}_${{matrix.PLAT}}" CIBW_MANYLINUX_I686_IMAGE: ${{ matrix.MB_ML_LIBC }}${{matrix.MB_ML_VER}} CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.MB_ML_LIBC }}${{matrix.MB_ML_VER}} diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 62eeecd3..68178609 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -119,7 +119,6 @@ jobs: rm local/scipy_openblas64/lib/*.a rm -f local/scipy_openblas64/lib/*.exp # may not exist? rm local/scipy_openblas64/lib/*.def - rm -rf local/scipy_openblas64/lib/pkgconfig if [[ -d local/scipy_openblas64/64 ]]; then rm -rf local/scipy_openblas64/64 else @@ -127,7 +126,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 @@ -138,10 +137,10 @@ 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 + + source tools/get_pkg_config.sh + echo "" >> LICENSE.txt echo "----" >> LICENSE.txt echo "" >> LICENSE.txt diff --git a/.gitignore b/.gitignore index 6f0c81a0..c10dea46 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ local/scipy_openblas64/*.so local/scipy_openblas64/*.pyd local/scipy_openblas64/*.dylib objconv/ +wheelhouse/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 4131c26d..ca17f277 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## OpenBLAS v0.3.34 (v0.3.34) +### 0.3.34.481.2 (2026-11-01) + +- Add Android wheels + ### 0.3.34.481.1 (2026-10-29) - Add a weekly scheduled run to both Windows workflows against OpenBLAS HEAD. diff --git a/build-openblas.sh b/build-openblas.sh index 20145b33..3c422c88 100755 --- a/build-openblas.sh +++ b/build-openblas.sh @@ -1,6 +1,11 @@ #! /bin/bash set -xeo pipefail + +# Check the required environment variables are set. +: ${MB_ML_LIBC:?} +: ${PLAT:?} + source tools/build_steps.sh echo "------ BEFORE BUILD ---------" before_build diff --git a/ci-before-build.sh b/ci-before-build.sh index f9d7e988..9a7cd67e 100755 --- a/ci-before-build.sh +++ b/ci-before-build.sh @@ -29,6 +29,16 @@ fi export OPENBLAS_VERSION=$version echo "creating wheel from $OPENBLAS_COMMIT (NIGHTLY is $NIGHTLY)" +libc_plat=${CIBUILDWHEEL_BUILD_IDENTIFIER#*-} +MB_ML_LIBC=${libc_plat%%_*} +PLAT=${libc_plat#*_} + +BUILD_PREFIX="$(pwd)/build/prefix/$libc_plat" +rm -rf "$BUILD_PREFIX" +mkdir -p "$BUILD_PREFIX" + +# On emulated architectures, RUNNER_ARCH makes manylinux-install-clang install a +# compiler for the native architecture, which will be much faster. case "$PLAT" in loongarch64|ppc64le|s390x|riscv64) manylinux-install-clang -v 21.1.6.0 diff --git a/ci-repair-wheel.sh b/ci-repair-wheel.sh index 0758ee1a..05f3bce2 100755 --- a/ci-repair-wheel.sh +++ b/ci-repair-wheel.sh @@ -1,10 +1,8 @@ #! /bin/bash set -xe -PYTHON=${PYTHON:-python3.9} - if [ $(uname) == "Darwin" ]; then - $PYTHON -m pip install delocate + python3 -m pip install delocate # move the mis-named scipy_openblas64-none-any.whl to a platform-specific name # if [ "${PLAT}" == "arm64" ]; then # for f in $2/*.whl; do mv $f "${f/%any.whl/macosx_11_0_$PLAT.whl}"; done diff --git a/ci-test.sh b/ci-test.sh index 8330f6fb..3b58d565 100755 --- a/ci-test.sh +++ b/ci-test.sh @@ -1,16 +1,9 @@ #!/bin/bash -# Test that the wheel works with a different python set -xe -if [ "${PLAT}" == "arm64" ]; then - # Cannot test - exit 0 -fi - -PYTHON=python3.9 -if [ "$(uname)" == "Darwin" -a "${PLAT}" == "x86_64" ]; then - which python3.9 - PYTHON="arch -x86_64 python3.9" +PYTHON=python3 +if [ "$CIBUILDWHEEL_BUILD_IDENTIFIER" = "macosx_x86_64" ]; then + PYTHON="arch -x86_64 python3" fi # Make sure the module works and that the version strings match diff --git a/local/scipy_openblas64/__init__.py b/local/scipy_openblas64/__init__.py index 59e7214a..06bb744e 100644 --- a/local/scipy_openblas64/__init__.py +++ b/local/scipy_openblas64/__init__.py @@ -5,6 +5,7 @@ import ctypes import os from pathlib import Path +import re import sys from textwrap import dedent import platform @@ -91,11 +92,20 @@ def get_pkg_config(use_preloading=False, use_prefix=False): # Don't use `$prefix` since the file may be located outside the package tree libdir = get_lib_dir() incdir = get_include_dir() + + variables = {} + with open(f"{get_lib_dir()}/pkgconfig/scipy-openblas.pc") as pc_file: + for line in pc_file: + # The CMake build used by Windows ARM64 produces a Version: keyword but not + # a version= variable, so parse both kinds of line. + if match := re.fullmatch(r"(.+?)[:=](.*)", line.strip()): + variables[match[1].strip()] = match[2].strip() + return dedent(f"""\ libdir={libdir} includedir={incdir} - openblas_config= {get_openblas_config()} - version={get_openblas_config().split(" ")[1]} + openblas_config= {variables["openblas_config"]} + version={variables.get("version") or variables["Version"]} extralib={extralib} Name: openblas Description: OpenBLAS is an optimized BLAS library based on GotoBLAS2 1.13 BSD version @@ -146,5 +156,10 @@ def get_openblas_config(): bytes = openblas_config() return bytes.decode("utf8") -# Import the DLL which will make the namespace available to NumPy/SciPy -get_openblas_config() + +if "CIBUILDWHEEL" in os.environ and sys.platform == "android": + # We're cross-compiling, so we can't load the library. + pass +else: + # Import the DLL which will make the namespace available to NumPy/SciPy + get_openblas_config() diff --git a/pyproject.toml b/pyproject.toml index 1a9d4830..c15e9b18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "scipy-openblas64" # 0.3.34-481-g5137bb62 -version = "0.3.34.481.1" +version = "0.3.34.481.2" requires-python = ">=3.7" description = "Provides OpenBLAS for python packaging" readme = "README.md" @@ -45,15 +45,31 @@ before-build = "bash ci-before-build.sh" repair-wheel-command = "bash ci-repair-wheel.sh {dest_dir} {wheel}" test-command = "cd {package} && bash ci-test.sh" environment-pass = [ - "OPENBLAS_COMMIT", "NIGHTLY", - "MB_ML_LIBC", - "MB_ML_VER", "INTERFACE64", - "BUILD_DIR", - "PLAT", - "OS-NAME", + + # On emulated architectures, RUNNER_ARCH makes manylinux-install-clang install a + # compiler for the native architecture, which will be much faster. "RUNNER_ARCH", ] + +[tool.cibuildwheel.android] +# The Linux code in ci-repair-wheel.sh isn't relevant to Android, so use the default +# repair command from the cibuildwheel documentation. +repair-wheel-command = "auditwheel repair --ldpaths {ldpaths} -w {dest_dir} {wheel}" + +# Mobile platforms only support Python test-commands, not shell scripts. +test-command = """python -c ' +import runpy + +def run_module(mod_name): + runpy.run_module(mod_name, run_name="__main__", alter_sys=True) + +try: + run_module("scipy_openblas32") +except ImportError: + run_module("scipy_openblas64") +'""" + [project.entry-points.pkg_config] scipy-openblas = 'scipy_openblas64.lib.pkgconfig' diff --git a/tools/build_prepare_wheel.sh b/tools/build_prepare_wheel.sh index ca5a5002..93e39448 100644 --- a/tools/build_prepare_wheel.sh +++ b/tools/build_prepare_wheel.sh @@ -7,12 +7,12 @@ if [ "$?" != "0" ]; then # inside docker cd /project fi -PYTHON=${PYTHON:-python3.9} mkdir -p local/openblas mkdir -p dist -tar -C local/scipy_openblas64 --strip-components=2 -xf libs/openblas.tar.gz +rm -rf local/scipy_openblas64/{include,lib} +tar -C local/scipy_openblas64 -xf libs/openblas.tar.gz # do not package the static libs and symlinks, only take the shared object find local/scipy_openblas64/lib -maxdepth 1 -type l -delete @@ -32,7 +32,7 @@ if [[ $py_version != $pkg_version* ]]; then exit 1 fi -if [ $(uname) == "Darwin" ]; then +if [ "$MB_ML_LIBC" == "macosx" ]; then soname=$(cd local/scipy_openblas64/lib; ls libscipy_openblas*.dylib) echo otool -D local/scipy_openblas64/lib/$soname otool -D local/scipy_openblas64/lib/$soname @@ -41,18 +41,11 @@ if [ $(uname) == "Darwin" ]; then install_name_tool -id @rpath/$soname local/scipy_openblas64/lib/$soname fi -rm -rf local/scipy_openblas64/lib/pkgconfig -mkdir local/scipy_openblas64/lib/pkgconfig echo "" >> LICENSE.txt echo "----" >> LICENSE.txt echo "" >> LICENSE.txt cat tools/LICENSE_posix.txt >> LICENSE.txt -if [ "$(uname)" == "Darwin" -a "${PLAT}" == "x86_64" ]; then - PYTHON="arch -x86_64 python3" -else - 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 @@ -67,11 +60,10 @@ 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 +source tools/get_pkg_config.sh + rm -rf dist/* diff --git a/tools/build_steps.sh b/tools/build_steps.sh index 3758253d..60ca84a7 100644 --- a/tools/build_steps.sh +++ b/tools/build_steps.sh @@ -1,17 +1,15 @@ #!bash -# Build script for manylinux and OSX +# Build script for posix platforms BUILD_PREFIX=${BUILD_PREFIX:-/usr/local} -ROOT_DIR=$(dirname $(dirname "${BASH_SOURCE[0]}")) - -MB_PYTHON_VERSION=3.9 +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) source $(dirname "${BASH_SOURCE[0]}")/gfortran_compat.sh function before_build { # install gfortran, objconv on macOS - if [ "$(uname -s)" == "Darwin" ]; then + if [ "$MB_ML_LIBC" == "macosx" ]; then if [ ! -e /usr/local/lib ]; then sudo mkdir -p /usr/local/lib sudo chmod 777 /usr/local/lib @@ -22,9 +20,6 @@ function before_build { sudo chmod 777 /usr/local/include touch /usr/local/include/.dir_exists fi - # get_macpython_environment ${MB_PYTHON_VERSION} venv - python3.9 -m venv venv - source venv/bin/activate unalias gfortran 2>/dev/null || true source tools/gfortran_utils.sh @@ -55,7 +50,7 @@ function before_build { if [[ ! -x objconv/objconv ]]; then (cd ${ROOT_DIR}/objconv && bash ../tools/build_objconv.sh) fi - else + elif [[ "$MB_ML_LIBC" == *linux ]]; then # Red Hat keeps static libraries in separate *-static subpackages, so # the images on a system gcc rather than a gcc-toolset (manylinux_2_39, # i.e. riscv64) have no libgfortran.a. The archive is in the CRB repo, @@ -76,38 +71,12 @@ function clean_code { pushd OpenBLAS git fetch origin --tags git checkout $build_commit - git clean -fxd + git checkout . + git clean -fxdq git submodule update --init --recursive popd } -function get_plat_tag { - # Copied from gfortran-install/gfortran_utils.sh, modified for MB_ML_LIBC - - # Modify fat architecture tags on macOS to reflect compiled architecture - # For non-darwin, report manylinux version - local plat=$1 - local mb_ml_ver=${MB_ML_VER:-1} - local mb_ml_libc=${MB_ML_LIBC:-manylinux} - case $plat in - i686|x86_64|arm64|universal2|intel|aarch64|s390x|ppc64le|loongarch64|riscv64) ;; - *) echo Did not recognize plat $plat; return 1 ;; - esac - local uname=${2:-$(uname)} - if [ "$uname" != "Darwin" ]; then - if [ "$plat" == "intel" ]; then - echo plat=intel not allowed for Manylinux - return 1 - fi - echo "${mb_ml_libc}${mb_ml_ver}_${plat}" - return - fi - # macOS 32-bit arch is i386 - [ "$plat" == "i686" ] && plat="i386" - local target=$(echo $MACOSX_DEPLOYMENT_TARGET | tr .- _) - echo "macosx_${target}_${plat}" -} - function patch_source { # Runs inside OpenBLAS directory # Make the patches by git format-patch @@ -119,27 +88,26 @@ function patch_source { } function build_lib { - # OSX or manylinux build - # # Input arg # plat - one of i686, x86_64, arm64 # interface64 - 1 if build with INTERFACE64 and SYMBOLSUFFIX # # Depends on globals # BUILD_PREFIX - install suffix e.g. "/usr/local" - # MB_ML_VER + # MB_ML_LIBC set -x local plat=${1:-$PLAT} local interface64=${2:-$INTERFACE64} - case $(uname -s)-$plat in - Linux-x86_64) + local libc_plat=${MB_ML_LIBC}_$plat + case $libc_plat in + *linux_x86_64) local bitness=64 local target="PRESCOTT" local dynamic_list="PRESCOTT NEHALEM SANDYBRIDGE HASWELL SKYLAKEX" ;; - Darwin-x86_64) + macosx_x86_64) local bitness=64 local target="CORE2" CFLAGS="$CFLAGS -arch x86_64" @@ -147,39 +115,45 @@ function build_lib { export SDKROOT=${SDKROOT:-$(xcrun --show-sdk-path)} local dynamic_list="CORE2 NEHALEM SANDYBRIDGE HASWELL SKYLAKEX" ;; - *-i686) + android_x86_64) + # This target corresponds to the instruction set extensions listed at + # https://developer.android.com/ndk/guides/abis#86-64. + local bitness=64 + local target="NEHALEM" + ;; + *_i686) local bitness=32 local target="PRESCOTT" local dynamic_list="PRESCOTT NEHALEM SANDYBRIDGE HASWELL" ;; - Linux-aarch64) + *linux_aarch64 | android_arm64_v8a) local bitness=64 local target="ARMV8" ;; - Darwin-arm64) + macosx_arm64) local bitness=64 local target="VORTEX" CFLAGS="$CFLAGS -ftrapping-math -mmacos-version-min=11.0" MACOSX_DEPLOYMENT_TARGET="11.0" export SDKROOT=${SDKROOT:-$(xcrun --show-sdk-path)} ;; - *-s390x) + *_s390x) # The TargetList.txt has only ZARCH_GENERIC, Z13, Z14. Not worth # messing with dynamic lists. local bitness=64 local target="ZARCH_GENERIC" ;; - *-ppc64le) + *_ppc64le) local bitness=64 local target="POWER8" ;; - Linux-loongarch64) + *linux_loongarch64) local target="GENERIC" ;; - Linux-riscv64) + *linux_riscv64) local target="GENERIC" ;; - *) echo "Strange plat value $plat"; exit 1 ;; + *) echo "Strange libc_plat value '$libc_plat'"; exit 1 ;; esac case $interface64 in 1) @@ -193,17 +167,32 @@ function build_lib { esac interface_flags="$interface_flags SYMBOLPREFIX=scipy_ LIBNAMEPREFIX=scipy_ FIXED_LIBNAME=1" - # Replace the libgfortran/libquadmath runtime dependency with the compat - # archive; a toolchain that cannot supply it fails the build. TIMER=NONE - # selects LAPACK's second_NONE.f/dsecnd_NONE.f, removing the only - # reference to _gfortran_etime. See tools/gfortran_compat.sh. - local compat_lib - if ! compat_lib=$(build_gfortran_compat "$PWD/build/gfortran_compat" "$interface64"); then - echo "ERROR: cannot build the libgfortran compat archive for" \ - "${MB_ML_LIBC:-manylinux}-$plat" >&2 - exit 1 + if [ "$MB_ML_LIBC" = "android" ]; then + # It's difficult to install a Fortran compiler for this platform. + interface_flags+=" NOFORTRAN=1" + + # This is the compiler for the build machine, which is used to generate some + # build files. + interface_flags+=" HOSTCC=cc" + + # OpenBLAS assumes objcopy has the same filename prefix as CC. + interface_flags+=" OBJCOPY=$(dirname "$CC")/llvm-objcopy" + else + # DYNAMIC_ARCH isn't enabled on Android because library size is more important + # on that platform. + interface_flags+=" DYNAMIC_ARCH=1" + + # Replace the libgfortran/libquadmath runtime dependency with the compat + # archive; a toolchain that cannot supply it fails the build. TIMER=NONE + # selects LAPACK's second_NONE.f/dsecnd_NONE.f, removing the only + # reference to _gfortran_etime. See tools/gfortran_compat.sh. + local compat_lib + if ! compat_lib=$(build_gfortran_compat "$PWD/build/gfortran_compat" "$interface64"); then + echo "ERROR: cannot build the libgfortran compat archive for $libc_plat" >&2 + exit 1 + fi + interface_flags="$interface_flags NO_LIBGFORTRAN=1 LIBGFORTRAN_COMPAT=$compat_lib TIMER=NONE" fi - interface_flags="$interface_flags NO_LIBGFORTRAN=1 LIBGFORTRAN_COMPAT=$compat_lib TIMER=NONE" mkdir -p libs set -x @@ -226,14 +215,14 @@ function build_lib { fi if [ -n "$dynamic_list" ]; then CFLAGS="$CFLAGS -fvisibility=protected -Wno-uninitialized" \ - make BUFFERSIZE=20 DYNAMIC_ARCH=1 QUIET_MAKE=1 \ + make BUFFERSIZE=20 QUIET_MAKE=1 \ USE_OPENMP=0 NUM_THREADS=64 \ DYNAMIC_LIST="$dynamic_list" \ BINARY="$bitness" $interface_flags \ TARGET="$target" else CFLAGS="$CFLAGS -fvisibility=protected -Wno-uninitialized" \ - make BUFFERSIZE=20 DYNAMIC_ARCH=1 QUIET_MAKE=1 \ + make BUFFERSIZE=20 QUIET_MAKE=1 \ USE_OPENMP=0 NUM_THREADS=64 \ BINARY="$bitness" $interface_flags \ TARGET="$target" @@ -241,7 +230,6 @@ function build_lib { make PREFIX=$BUILD_PREFIX $interface_flags install popd mv $BUILD_PREFIX/lib/pkgconfig/openblas*.pc $BUILD_PREFIX/lib/pkgconfig/scipy-openblas.pc - local plat_tag=$(get_plat_tag $plat) if [ "$interface64" = "1" ]; then # OpenBLAS does not install the symbol suffixed static library, # do it ourselves @@ -251,29 +239,33 @@ function build_lib { sed -e "s/\(^Cflags.*\)/\1 -DBLAS_SYMBOL_PREFIX=scipy_ -DBLAS_SYMBOL_SUFFIX=64_/" -i.bak $BUILD_PREFIX/lib/pkgconfig/scipy-openblas.pc else sed -e "s/\(^Cflags.*\)/\1 -DBLAS_SYMBOL_PREFIX=scipy_/" -i.bak $BUILD_PREFIX/lib/pkgconfig/scipy-openblas.pc - rm $BUILD_PREFIX/lib/pkgconfig/scipy-openblas.pc.bak fi + rm $BUILD_PREFIX/lib/pkgconfig/scipy-openblas.pc.bak - # The shared library picked these up from the link line (see - # LIBGFORTRAN_COMPAT_LINK in the patch), but the static one is assembled - # from OpenBLAS's own objects only; add them there too, so that linking - # libscipy_openblas*.a does not need libgfortran either. Must come after - # the INTERFACE64 branch above, which overwrites the installed archive. - local compat_dir=$(dirname "$compat_lib") - for static_lib in $BUILD_PREFIX/lib/libscipy_openblas*.a; do - # An unmatched glob arrives as a literal, and `ar crs` would happily - # create an archive at that bogus path. - [ -f "$static_lib" ] || continue - ar crs "$static_lib" "$compat_dir"/*.o - done - assert_no_fortran_runtime $BUILD_PREFIX/lib/libscipy_openblas*.so \ - $BUILD_PREFIX/lib/libscipy_openblas*.dylib + if [ -n "$compat_lib" ]; then + # The shared library picked these up from the link line (see + # LIBGFORTRAN_COMPAT_LINK in the patch), but the static one is assembled + # from OpenBLAS's own objects only; add them there too, so that linking + # libscipy_openblas*.a does not need libgfortran either. Must come after + # the INTERFACE64 branch above, which overwrites the installed archive. + local compat_dir=$(dirname "$compat_lib") + for static_lib in $BUILD_PREFIX/lib/libscipy_openblas*.a; do + # An unmatched glob arrives as a literal, and `ar crs` would happily + # create an archive at that bogus path. + [ -f "$static_lib" ] || continue + ar crs "$static_lib" "$compat_dir"/*.o + done + assert_no_fortran_runtime $BUILD_PREFIX/lib/libscipy_openblas*.so \ + $BUILD_PREFIX/lib/libscipy_openblas*.dylib + fi local out_name="openblas.tar.gz" - tar zcvf libs/$out_name \ - $BUILD_PREFIX/include/*blas* \ - $BUILD_PREFIX/include/*lapack* \ - $BUILD_PREFIX/lib/libscipy_openblas* \ - $BUILD_PREFIX/lib/pkgconfig/scipy-openblas* \ - $BUILD_PREFIX/lib/cmake/openblas + pushd $BUILD_PREFIX + tar zcvf $ROOT_DIR/libs/$out_name \ + include/*blas* \ + include/*lapack* \ + lib/libscipy_openblas* \ + lib/pkgconfig/scipy-openblas* \ + lib/cmake/openblas + popd } diff --git a/tools/build_steps_win_arm64.bat b/tools/build_steps_win_arm64.bat index 94b1c0f3..6446b3ca 100755 --- a/tools/build_steps_win_arm64.bat +++ b/tools/build_steps_win_arm64.bat @@ -238,30 +238,16 @@ 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 not exist "%DEST_DIR%\lib\pkgconfig" mkdir "%DEST_DIR%\lib\pkgconfig" +copy /Y openblas*.pc "%DEST_DIR%\lib\pkgconfig\scipy-openblas.pc" +if errorlevel 1 exit /b 1 +cd ../.. +bash -e tools\get_pkg_config.sh if errorlevel 1 ( echo could not construct scipy-openblas.pc exit /b 1 ) -REM Move back to the root directory -cd .. -if errorlevel 1 ( - echo Current directory %CD%, cannot cd .. - exit /b 1 -) - 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 diff --git a/tools/get_pkg_config.sh b/tools/get_pkg_config.sh new file mode 100644 index 00000000..d15e4735 --- /dev/null +++ b/tools/get_pkg_config.sh @@ -0,0 +1,19 @@ +if [ "$(uname)" == "Darwin" -a "${PLAT}" == "x86_64" ]; then + PYTHON="arch -x86_64 python" +else + PYTHON=python +fi + +if [ "${INTERFACE64}" != "1" ]; then + module="scipy_openblas32" +else + module="scipy_openblas64" +fi + +# get_pkg_config reads from the original pc_file generated by the OpenBLAS build, so +# redirect the output to a temporary file and then rename it over the original. +pc_file="local/$module/lib/pkgconfig/scipy-openblas.pc" +PYTHONPATH=$PWD/local $PYTHON -c \ + "import $module as s; print(s.get_pkg_config(use_prefix=True))" \ + > "$pc_file.tmp" +mv "$pc_file.tmp" "$pc_file"