Testing with SciPy and NumPy#
semicolon-lapack ships a Fortran-ABI compatibility layer (libsemilapack_fortran)
that allows projects expecting a standard Fortran LAPACK to use our library as a
drop-in replacement. This page explains how to build SciPy and NumPy against it
and run their test suites.
How the Fortran Shim Works#
Fortran LAPACK symbols follow specific conventions that differ from our C API. The shim library bridges these differences by performing three conversions at the boundary:
Trailing underscore – Fortran compilers append
_to symbol names. The shim exportsdgetrf_which internally calls ourdgetrf.Pass-by-pointer – Fortran passes all arguments by reference. The shim accepts pointer arguments and dereferences them before calling the C function.
Index conversion – Our library uses 0-based indexing; Fortran LAPACK uses 1-based. The shim converts pivot arrays,
ilo/ihiparameters, and other index quantities at the boundary so that callers and the library each see the convention they expect.
The shim is generated by scripts/generate_fortran_shim.py from the public
headers and built as a shared library (libsemilapack_fortran.so). A pkg-config
file semicolon-lapack-fortran.pc is installed alongside it.
Prerequisites#
A conda environment with OpenBLAS, a C compiler, Meson, and Ninja.
Source checkouts of SciPy and/or NumPy.
The
spindeveloper build tool (bundled with both projects).
The examples below assume a conda environment called scipy-dev with OpenBLAS
installed. Adjust paths if your setup differs.
Step 1: Build and Install semicolon-lapack#
meson setup builddir --prefix=/tmp/semilapack -Dfabi_shim=true
ninja -C builddir
meson install -C builddir
The -Dfabi_shim=true option enables the Fortran shim. Without it, only the
native C library is built. After installation, the prefix contains:
/tmp/semilapack/
├── include/semicolon_lapack/...
└── lib64/
├── libsemilapack.a
├── libsemilapack_fortran.so
└── pkgconfig/
├── semicolon-lapack.pc
└── semicolon-lapack-fortran.pc
Note
The library directory may be lib/ or lib64/ depending on the platform.
Check which one your Meson install produces and adjust PKG_CONFIG_PATH
accordingly in the steps below.
Step 2: Build SciPy#
cd /path/to/scipy
spin build --clean \
-S -Dlapack=semicolon-lapack-fortran \
-S -Dpkg_config_path=/tmp/semilapack/lib64/pkgconfig:$CONDA_PREFIX/lib/pkgconfig
-Dlapack=semicolon-lapack-fortran tells SciPy’s Meson build to resolve the
LAPACK dependency using our pkg-config package name instead of the default
auto-detection. BLAS is left on auto and picks up OpenBLAS from conda.
The chained pkg_config_path ensures both our install prefix and conda’s
OpenBLAS are visible to pkg-config.
Note
SciPy’s spin passes Meson setup arguments with the -S flag.
Step 3: Build NumPy#
cd /path/to/numpy
git submodule update --init
spin build --clean -- \
-Dlapack=semicolon-lapack-fortran \
-Dpkg_config_path=/tmp/semilapack/lib64/pkgconfig:$CONDA_PREFIX/lib/pkgconfig
The git submodule update --init step is required on a fresh clone because
NumPy vendors its own copy of Meson as a submodule.
Note
NumPy’s spin uses -- to separate Meson arguments from spin’s own
flags, whereas SciPy uses -S.
Step 4: Run Tests#
SciPy:
cd /path/to/scipy
spin test # full suite
spin test -s linalg # linear algebra
spin test -s sparse.linalg # sparse solvers (includes ARPACK)
spin test -s optimize # optimization
NumPy:
cd /path/to/numpy
spin test # full suite
Troubleshooting#
- pkg-config cannot find ``semicolon-lapack-fortran``
Verify that
PKG_CONFIG_PATHincludes the directory containingsemicolon-lapack-fortran.pc. Runpkg-config --modversion semicolon-lapack-fortranto confirm.- NumPy’s ``spin build`` rejects ``-S``
NumPy and SciPy use different
spinconventions for passing Meson arguments. NumPy expects-- -Dkey=value; SciPy expects-S -Dkey=value.- NumPy fails with “vendored-meson/meson submodule does not exist”
Run
git submodule update --initin the NumPy source directory.- Wrong OpenBLAS picked up at runtime
If tests crash or produce wrong results, the runtime linker may be loading a system OpenBLAS instead of the conda one. Check with
ldd(Linux) orotool -L(macOS) on the built extension modules, and ensure$CONDA_PREFIX/libappears inLD_LIBRARY_PATHor the rpath.