Skip to content

Commit

Permalink
reuse parts of scipy's scripts for windows includding delvewheel; fix…
Browse files Browse the repository at this point in the history
… non-wheel build
  • Loading branch information
mattip authored and rgommers committed Jun 18, 2023
1 parent aabacc7 commit 2e84e21
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 31 deletions.
4 changes: 2 additions & 2 deletions azure-pipelines.yml
Expand Up @@ -261,13 +261,13 @@ stages:
PYTHON_ARCH: 'x64'
TEST_MODE: full
BITS: 64
NPY_USE_BLAS_ILP64: '1'
# NPY_USE_BLAS_ILP64: '1'
PyPy39-64bit-fast:
PYTHON_VERSION: 'pypy3.9'
PYTHON_ARCH: 'x64'
TEST_MODE: fast
BITS: 64
NPY_USE_BLAS_ILP64: '1'
# NPY_USE_BLAS_ILP64: '1'

steps:
- template: azure-steps-windows.yml
Expand Down
35 changes: 19 additions & 16 deletions azure-steps-windows.yml
Expand Up @@ -17,35 +17,38 @@ steps:
# Note that rtools 42+ does not support 32 bits builds. We dropped testing
# those, but if there's a need to go back on that, use version 4.0.0.20220206
choco install --confirm --no-progress --side-by-side rtools --version=4.3.5550
choco install unzip -y
choco install -y --checksum 6004DF17818F5A6DBF19CB335CC92702 pkgconfiglite
echo "##vso[task.setvariable variable=RTOOLS43_HOME]c:\rtools43"
displayName: 'Install rtools'
displayName: 'Install utilities'

- powershell: |
$ErrorActionPreference = "Stop"
# Download and get the path to "openblas". We cannot copy it
# to $PYTHON_EXE's directory since that is on a different drive which
# mingw does not like. Instead copy it to a directory and set OPENBLAS,
# since OPENBLAS will be picked up by the openblas discovery
$target = $(python tools/openblas_support.py)
mkdir openblas
echo "Copying $target to openblas/"
cp -r $target/* openblas/
$env:OPENBLAS = $target
mkdir C:/opt/openblas/openblas_dll
mkdir C:/opt/32/lib/pkgconfig
mkdir C:/opt/64/lib/pkgconfig
# TBD: support 32 bit testing
$target=$(python -c "import tools.openblas_support as obs; plat=obs.get_plat(); ilp64=obs.get_ilp64(); target=f'openblas_{plat}.zip'; obs.download_openblas(target, plat, ilp64);print(target)")
unzip -o -d c:/opt/ $target
echo "##vso[task.setvariable variable=PKG_CONFIG_PATH]c:/opt/64/lib/pkgconfig"
copy C:/opt/64/bin/*.dll C:/opt/openblas/openblas_dll
displayName: 'Download / Install OpenBLAS'

- powershell: |
ls openblas
# Not strictly needed since we are forcing use of vsenv
$env:PATH = "$env:RTOOLS43_HOME\\x86_64-w64-mingw32.static.posix\\bin;$env:PATH"
python -c"import os, pprint; pprint.pprint(os.environ['PATH'])"
gcc --version
If ( Test-Path env:NPY_USE_BLAS_ILP64 ) {
$env:OPENBLAS64_ = "openblas"
$env:OPENBLAS64_="openblas"
# This does not work, the flags are passed together and not separately
$env:CFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64"
$env:CXXFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64"
} else {
$env:OPENBLAS = "openblas"
}
python -c "from tools import openblas_support; openblas_support.make_init('numpy')"
python -m pip install . --config-settings=setup-args="--vsenv"
# copy from c:/opt/openblas/openblas_dll to numpy/.libs
$target = $(python -c "import sysconfig; print(sysconfig.get_path('platlib'))")
mkdir $target/numpy/.libs
copy C:/opt/openblas/openblas_dll/*.dll $target/numpy/.libs
displayName: 'Build NumPy'

- script: |
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Expand Up @@ -166,12 +166,13 @@ test-skip = "*_universal2:arm64"
environment = { CFLAGS="-std=c99 -fno-strict-aliasing -DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", CXXFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", OPENBLAS64_="/usr/local", NPY_USE_BLAS_ILP64="1", CC="clang", CXX = "clang++", RUNNER_OS="macOS"}

[tool.cibuildwheel.windows]
environment = { OPENBLAS64_="openblas", OPENBLAS="", NPY_USE_BLAS_ILP64="1", CFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", CXXFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", LDFLAGS="", PKG_CONFIG_PATH=D:/a/numpy/numpy/openblas/lib/pkgconfig}
environment = { OPENBLAS64_="openblas", OPENBLAS="", NPY_USE_BLAS_ILP64="1", CFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", CXXFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", LDFLAGS="", PKG_CONFIG_PATH="C:/opt/64/lib/pkgconfig"}
config-settings = "setup-args=--vsenv"
repair-wheel-command = "bash ./tools/wheels/repair_windows.sh {wheel} {dest_dir}"

[[tool.cibuildwheel.overrides]]
select = "*-win32"
environment = { OPENBLAS64_="", OPENBLAS="openblas", NPY_USE_BLAS_ILP64="0", CFLAGS="-m32", LDFLAGS="-m32"}
environment = { OPENBLAS64_="", OPENBLAS="openblas", NPY_USE_BLAS_ILP64="0", CFLAGS="-m32", LDFLAGS="-m32", PKG_CONFIG_PATH="/opt/32/lib/pkgconfig"}

[tool.meson-python.args]
# These should be the defaults for a normal NumPy build
Expand Down
9 changes: 5 additions & 4 deletions tools/openblas_support.py
Expand Up @@ -182,10 +182,11 @@ def unpack_windows_zip(fname, plat):
# Copy the lib to openblas.lib. Once we can properly use pkg-config
# this will not be needed
lib = glob.glob(os.path.join(target, 'lib', '*.lib'))
assert len(lib) == 1
for f in lib:
shutil.copy(f, os.path.join(target, 'lib', 'openblas.lib'))
shutil.copy(f, os.path.join(target, 'lib', 'openblas64_.lib'))
if len(lib) == 1:
# The 64-bit tarball already has these copied, no need to do it
for f in lib:
shutil.copy(f, os.path.join(target, 'lib', 'openblas.lib'))
shutil.copy(f, os.path.join(target, 'lib', 'openblas64_.lib'))
# Copy the dll from bin to lib so system_info can pick it up
dll = glob.glob(os.path.join(target, 'bin', '*.dll'))
for f in dll:
Expand Down
32 changes: 25 additions & 7 deletions tools/wheels/cibw_before_build.sh
Expand Up @@ -29,14 +29,32 @@ if [[ $RUNNER_OS == "Linux" || $RUNNER_OS == "macOS" ]] ; then
cp $basedir/include/* /usr/local/include
fi
elif [[ $RUNNER_OS == "Windows" ]]; then
# delvewheel is the equivalent of delocate/auditwheel for windows.
python -m pip install delvewheel

# make the DLL available for tools/wheels/repair_windows.sh. If you change
# this location you need to alter that script.
mkdir -p /c/opt/openblas/openblas_dll

PYTHONPATH=tools python -c "import openblas_support; openblas_support.make_init('numpy')"
target=$(python tools/openblas_support.py)
mkdir -p openblas
# bash on windows does not like cp -r $target/* openblas
for f in $(ls $target); do
cp -r $target/$f openblas
done
ls openblas
mkdir -p /c/opt/32/lib/pkgconfig
mkdir -p /c/opt/64/lib/pkgconfig
target=$(python -c "import tools.openblas_support as obs; plat=obs.get_plat(); ilp64=obs.get_ilp64(); target=f'openblas_{plat}.zip'; obs.download_openblas(target, plat, ilp64);print(target)")
if [[ $PLATFORM == 'win-32' ]]; then
# 32-bit openBLAS
# Download 32 bit openBLAS and put it into c/opt/32/lib
unzip -o -d /c/opt/ $target
cp /c/opt/32/bin/*.dll /c/opt/openblas/openblas_dll
else
# 64-bit openBLAS
unzip -o -d /c/opt/ $target
if [[ -f /c/opt/64/lib/pkgconfig/openblas64.pc ]]; then
# As of v0.3.23, the 64-bit interface has a openblas64.pc file,
# but this is wrong. It should be openblas.pc
cp /c/opt/64/lib/pkgconfig/openblas{64,}.pc
fi
cp /c/opt/64/bin/*.dll /c/opt/openblas/openblas_dll
fi
fi

if [[ $RUNNER_OS == "macOS" ]]; then
Expand Down
32 changes: 32 additions & 0 deletions tools/wheels/repair_windows.sh
@@ -0,0 +1,32 @@
set -xe

WHEEL="$1"
DEST_DIR="$2"

# create a temporary directory in the destination folder and unpack the wheel
# into there
pushd $DEST_DIR
mkdir -p tmp
pushd tmp
wheel unpack $WHEEL
pushd numpy*

# To avoid DLL hell, the file name of libopenblas that's being vendored with
# the wheel has to be name-mangled. delvewheel is unable to name-mangle PYD
# containing extra data at the end of the binary, which frequently occurs when
# building with mingw.
# We therefore find each PYD in the directory structure and strip them.

for f in $(find ./scipy* -name '*.pyd'); do strip $f; done


# now repack the wheel and overwrite the original
wheel pack .
mv -fv *.whl $WHEEL

cd $DEST_DIR
rm -rf tmp

# the libopenblas.dll is placed into this directory in the cibw_before_build
# script.
delvewheel repair --add-path /c/opt/openblas/openblas_dll -w $DEST_DIR $WHEEL

0 comments on commit 2e84e21

Please sign in to comment.