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:

  1. Trailing underscore – Fortran compilers append _ to symbol names. The shim exports dgetrf_ which internally calls our dgetrf.

  2. Pass-by-pointer – Fortran passes all arguments by reference. The shim accepts pointer arguments and dereferences them before calling the C function.

  3. Index conversion – Our library uses 0-based indexing; Fortran LAPACK uses 1-based. The shim converts pivot arrays, ilo/ihi parameters, 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 spin developer 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_PATH includes the directory containing semicolon-lapack-fortran.pc. Run pkg-config --modversion semicolon-lapack-fortran to confirm.

NumPy’s ``spin build`` rejects ``-S``

NumPy and SciPy use different spin conventions 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 --init in 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) or otool -L (macOS) on the built extension modules, and ensure $CONDA_PREFIX/lib appears in LD_LIBRARY_PATH or the rpath.