Skip to content
Snippets Groups Projects
Select Git revision
  • fc334bd757927f6abd4d6c1d047b59d4188d254f
  • master default protected
  • v1.6.1 protected
  • v1.6.0 protected
  • v1.5.0 protected
  • v1.4.0 protected
  • v1.3.0 protected
  • v1.2.0 protected
  • v1.1.0 protected
  • v1.0.0 protected
10 results

accelerate-lapacke

user avatar
Tim Kaune authored
fc334bd7
History

Accelerate LAPACKE

Since MacOS 13.3 Ventura, Apple's Accelerate framework comes with a new BLAS/LAPACK interface compatible with Reference LAPACK v3.9.1 in addition to the quite outdated Reference LAPACK v3.2.1. It also provides an ILP64 interface. On Apple Silicon M-processors, it utilises the proprietary AMX co-processor, which makes it especially interesting. Unfortunately, it comes without the LAPACKE C-interface library.

Update: With the release of MacOS 15.0 Sequoia, Apple updated the Accelerate framework to be compatible with Reference LAPACK v3.11.0. Unfortunately, there is no mention of it in the MacOS 15.0 Sequoia Release Notes, but the note in the Accelerate BLAS docs has been updated accordingly.

These new interfaces are hidden behind the preprocessor defines ACCELERATE_NEW_LAPACK and ACCELERATE_LAPACK_ILP64 and they only work, if you include the Accelerate C/C++ headers.

The Problem

But what if you have to or just want to link against the Accelerate framework without including the C/C++ headers, e. g. when compiling Fortran code or a third-party project, that uses the standard BLAS/LAPACK API? Well, you're out of luck. The binary symbols for the new LAPACK version exported by the Accelerate framework do not adhere to the BLAS/LAPACK API. Thus, they cannot be resolved by the linker, when linking any program or library that uses the standard BLAS/LAPACK API.

Take, for example, the dgeqrt LAPACK routine, that is used by the Reference LAPACK CMake script to determine, if the user provided LAPACK version is recent enough. When the Fortran test executable is compiled, the gfortran compiler creates a function call with the binary symbol _dgeqrt_, which results in the following error when linking to Accelerate (ld is the Apple system linker, here):

ld: Undefined symbols:
  _dgeqrt_, referenced from:
      _MAIN__ in testFortranCompiler.f.o

The reason for this is, that the binary symbol provided by the Accelerate framework is called _dgeqrt$NEWLAPACK, literally. This is a symbol, that no Fortran compiler will probably ever emit voluntarily. So, what to do?

The Solution

According to its man page, the Apple system linker ld provides the options -alias and -alias_list, which let you create alias names for existing binary symbols. Calling the linker with -alias '_dgeqrt$NEWLAPACK' _dgeqrt_ makes the linking of the above Fortran test executable finish successfully.

Because BLAS and LAPACK contain quite a number of subroutines and functions, this CMake scipt uses the -alias_list option, which loads a plaintext file listing all the aliases.

To generate the full alias list for the Accelerate NEWLAPACK interface, it parses the symbols listed in the BLAS and LAPACK text-based .dylib stubs. For every symbol that ends in $NEWLAPACK (or $NEWLAPACK$ILP64 for the ILP64 interface), an alias is added to the alias file.

The additional linker options get attached to new interface library targets, which are injected into the Reference LAPACK configure process using the CMAKE_REQUIRED_LIBRARIES variable for the Fortran test compiles and the LINK_LIBRARIES target property for the shared LAPACKE library.

This enables the compilation of the LAPACKE C-interface library for the Accelerate framework (e. g. to be used in the Eigen3 library). Analyzing the resulting .dylib with otool, you can see:

$ otool -L ./build/32/_deps/reference-lapack-build/lib/liblapacke.dylib
./build/32/_deps/reference-lapack-build/lib/liblapacke.dylib:
    @rpath/liblapacke.3.dylib (compatibility version 3.0.0, current version 3.11.0)
    /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate (compatibility version 1.0.0, current version 4.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)

Only the Accelerate framework and the System library are linked into the .dylib. No libgfortran or other libraries are needed.

The alias files (to use in other projects)

After the CMake configuration, the alias files can be found in ./build/<32|64>/src:

./build/<32|64>/src
├── new-blas-ilp64.alias
├── new-blas.alias
├── new-lapack-ilp64.alias
└── new-lapack.alias

These files can be used to link other projects against Accelerate, too, of course!

How to compile

It is recommended to use the Apple System C Compiler /usr/bin/cc. You can also use a more recent Clang compiler provided by Homebrew or MacPorts. If you have other compilers installed on your system, make sure CMake finds the correct one. Otherwise, help CMake by setting the environment variable $ export CC=/usr/bin/cc in your terminal window.

It is also recommended to use at least CMake v3.25 with presets, but the CMake script also works down to CMake v3.12, if you set the required variables on the command line.

Prerequisites

Obviously, your operating system must be Mac OS X >=v13.3 Ventura with XCode installed. Additionally, you'll need the following software (easily obtainable via Homebrew or MacPorts):

  • CMake
  • Fortran compiler (e. g. gfortran contained in the gcc package) to make it through the Reference LAPACK configure script

Workflow with CMake

Use the accelerate-lapacke32 preset (or the accelerate-lapacke64 preset for the ILP64 interface) with CMake:

$ cmake --workflow --preset accelerate-lapacke32

This will configure LAPACKE to be installed in your ~/.local directory by default. If you prefer a different install location (e. g. /opt/custom), you can change it using a CMakeUserPresets.json file, for which a template file is provided:

$ cmake --workflow --preset user-accelerate-lapacke32

I wouldn't recommend installing to /usr/local (used by Homebrew on Intel Macs) or /opt/local (used by MacPorts).

CMake v4 compatibility

To build the project with CMake v4 or higher, you must explicitly provide the CMAKE_OSX_SYSROOT variable in your CMakeUserPresets.json. Both the user-accelerate-lapacke32 and user-accelerate-lapacke64 presets should additionally have the cache variable "CMAKE_OSX_SYSROOT": "macosx". This is not included by default.

Using LAPACKE in another project

You can use your self-compiled LAPACKE library in other projects by importing the CMake package in the other project's CMakeLists.txt file:

find_package(LAPACKE CONFIG)

and providing the above install location via the CMAKE_PREFIX_PATH variable from the command line:

$ cmake -S . -B ./build -D "CMAKE_PREFIX_PATH=~/.local"

This makes the imported lapacke shared library target available in the other project's CMakeLists.txt.