Howto link against system-wide BLAS library using numpy.distutils

If your numpy installation uses system-wide BLAS libraries (this will most likely be the case unless you installed it through prebuilt windows binaries), you can retrieve this information at compile time to link python modules to BLAS.

The function get_info in numpy.distutils.system_info will return a dictionary that contains the needed information to link against BLAS or an empty dict if no system-wide BLAS could be found. For example, MacOSX ships with it’s own optimized BLAS routines, and get_info correctly reports that:

In [1]: from numpy.distutils.system_info import get_info

In [2]: get_info('blas_opt')
Out[2]:
{'define_macros': [('NO_ATLAS_INFO', 3)],
 'extra_compile_args': ['-msse3',
      '-I/System/Library/Frameworks/vecLib.framework/Headers'],
 'extra_link_args': ['-Wl,-framework', '-Wl,Accelerate']}

The following example shows a setup.py that links against system-wide BLAS if possible. If no appropriate BLAS routine could be found, it will print a warning message, but will compile it’s own BLAS routine and embed it in the python extension.

from os.path import join

def configuration(parent_package='', top_path=None):
    import warnings
    from numpy.distutils.misc_util import Configuration
    from numpy.distutils.system_info import get_info, BlasNotFoundError
    config = Configuration('foo', parent_package, top_path)

    libfoo_files = ['foo.c']
    blas_sources = [join('blas', 'daxpy.c'),
                    join('blas', 'dscal.c')]

    blas_info = get_info('blas_opt')
    if not blas_info:
        warnings.warn(BlasNotFoundError.__doc__)
        libfoo_files.append(blas_sources)

    libraries = blas_info.pop('libraries', [])
    include_dirs = blas_info.pop('include_dirs', [])
    config.add_extension('foo',
        sources=sources,
        libraries=libraries,
        include_dirs=include_dirs,
        **blas_info
    )

    return config

if __name__ == '__main__':
    from numpy.distutils.core import setup
    setup(**configuration(top_path='').todict())

A real-word example of this can be found in scipy.odr module and in scikits.learn’s liblinear bindings.

One Response to “Howto link against system-wide BLAS library using numpy.distutils”

  1. Gael Varoquaux
    April 24th, 2010 17:02
    1

    Hey Fabian,

    This is a very useful blog post. Thanks for posting it.