Skip to content
Snippets Groups Projects
Unverified Commit f830ade9 authored by Tim Kaune's avatar Tim Kaune
Browse files

Attach NEWLAPACK link options to targets

Inject the new targets into the Reference LAPACK build process.
Don't overwrite CMAKE_OSX_SYSROOT in CMake cache.
Improve status reporting.
parent 7f6f2e40
No related branches found
No related tags found
No related merge requests found
......@@ -37,6 +37,10 @@ if (NOT IS_TOP_LEVEL)
message(FATAL_ERROR "This project is meant to be built as a stand-alone project, only.")
endif ()
option(BUILD_INDEX64 "Link to ILP64 version of LAPACK?" OFF)
message(STATUS "Trying to link to ILP64 interface of LAPACK: ${BUILD_NEW_LAPACK}")
if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
# The available binary Accelerate version is determined by the MacOS system
message(STATUS "The Darwin kernel version is: ${CMAKE_HOST_SYSTEM_VERSION}")
......@@ -53,14 +57,21 @@ if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
set(VALID_MACOS_SDK_VERSIONS 14.5 14.4 14.2 14.0 13.3)
set(ACCELERATE_NEW_LAPACK_VERSION 3.9.1)
else ()
# Before Mac OS X 13.3 Ventura
message(FATAL_ERROR "You need at least MacOS 13.3 Ventura for Accelerate with BLAS/LAPACK v3.9.1!")
endif ()
message(STATUS "The BLAS/LAPACK version provided by the Accelerate framework is: ${ACCELERATE_NEW_LAPACK_VERSION}")
message(STATUS "The BLAS/LAPACK version provided by the Accelerate framework should be: ${ACCELERATE_NEW_LAPACK_VERSION}")
else ()
message(FATAL_ERROR "Accelerate is only available on MacOS!")
endif ()
if (NOT DEFINED CMAKE_OSX_SYSROOT OR CMAKE_OSX_SYSROOT STREQUAL "")
message(FATAL_ERROR "Please provide the CMAKE_OSX_SYSROOT location! See <https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_SYSROOT.html>")
endif ()
string(REGEX MATCH [=[SDKs/MacOSX(.*)\.sdk$]=] _REGEX_DUMMY "${CMAKE_OSX_SYSROOT}")
set(DEFAULT_MACOS_SDK_VERSION "${CMAKE_MATCH_1}")
set(MAIN_MACOS_SDK_VERSION "${CMAKE_MATCH_1}")
# The text-based .dylib stubs describing the Accelerate framework are provided
# by the MacOS SDK, which has to match the MacOS system. Otherwise, there might
......@@ -69,16 +80,17 @@ set(DEFAULT_MACOS_SDK_VERSION "${CMAKE_MATCH_1}")
if (NOT DEFINED VALID_MACOS_SDK_VERSIONS)
# MacOS system supports the latest iteration of the new Accelerate
# BLAS/LAPACK. Use the default SDK, if it's recent enough.
if (DEFAULT_MACOS_SDK_VERSION VERSION_LESS MINIMUM_MACOS_SDK_VERSION)
if (MAIN_MACOS_SDK_VERSION VERSION_LESS MINIMUM_MACOS_SDK_VERSION)
message(STATUS "The MacOS SDK is: ${CMAKE_OSX_SYSROOT}")
message(STATUS "The minimum compatible MacOS SDK version is: ${MINIMUM_MACOS_SDK_VERSION}")
message(FATAL_ERROR "Please install a more recent XCode for a compatible MacOS SDK.")
endif ()
elseif (NOT DEFAULT_MACOS_SDK_VERSION IN_LIST VALID_MACOS_SDK_VERSIONS)
elseif (NOT MAIN_MACOS_SDK_VERSION IN_LIST VALID_MACOS_SDK_VERSIONS)
# MacOS system supports one of the past iterations of the new Accelerate
# BLAS/LAPACK. If the latest possible XCode is installed is installed on
# this older system, there might be a mismatch between the SDK and the
# system binary. Find a matching SDK from the Command Line Tools instead.
# BLAS/LAPACK. If the latest possible XCode is installed on this older
# system, there might be a mismatch between the SDK and the system binary.
# Find a matching SDK from the Command Line Tools instead (which must be
# manually installed).
foreach (_MACOS_SDK_VERSION IN LISTS VALID_MACOS_SDK_VERSIONS)
find_path(VALID_MACOS_SDK NAMES "MacOSX${_MACOS_SDK_VERSION}.sdk" HINTS "/Library/Developer/CommandLineTools/SDKs" NO_CACHE)
......@@ -89,7 +101,8 @@ elseif (NOT DEFAULT_MACOS_SDK_VERSION IN_LIST VALID_MACOS_SDK_VERSIONS)
endforeach ()
if (VALID_MACOS_SDK)
set(CMAKE_OSX_SYSROOT "${VALID_MACOS_SDK}" CACHE PATH "" FORCE)
# Override CMAKE_OSX_SYSROOT with a local variable.
set(CMAKE_OSX_SYSROOT "${VALID_MACOS_SDK}")
else ()
message(STATUS "The MacOS SDK is: ${CMAKE_OSX_SYSROOT}")
message(STATUS "The compatible MacOS SDK versions are: ${VALID_MACOS_SDK_VERSIONS}")
......@@ -104,8 +117,10 @@ set(ENV{CMAKE_FRAMEWORK_PATH} "${CMAKE_OSX_SYSROOT}/System/Library/Frameworks")
set(BLA_VENDOR "Apple")
find_package(LAPACK MODULE)
unset(ENV{CMAKE_FRAMEWORK_PATH})
if (NOT LAPACK_FOUND OR NOT LAPACK_Accelerate_LIBRARY)
message(FATAL_ERROR "Couldn't find Accelerate framework!")
message(FATAL_ERROR "Couldn't find Accelerate framework in MacOS SDK!")
endif ()
add_subdirectory(src)
......@@ -13,16 +13,6 @@
"CMAKE_INSTALL_PREFIX": "$env{HOME}/.local"
}
},
{
"name": "cmake4",
"hidden": true,
"cacheVariables": {
"CMAKE_OSX_SYSROOT": "macosx"
},
"environment": {
"CMAKE_POLICY_VERSION_MINIMUM": "3.5"
}
},
{
"name": "make",
"hidden": true,
......
......@@ -27,7 +27,8 @@ SOFTWARE.
Since MacOS 13.3 Ventura, Apple's Accelerate framework comes with a new
[BLAS/LAPACK interface][accelerate-docs] compatible with [Reference LAPACK
v3.9.1][lapack-v3.9.1]. It also provides an ILP64 interface. On Apple Silicon
v3.9.1][lapack-v3.9.1] in addition to the quite outdated [Reference LAPACK
v3.2.1][lapack-v3.2.1]. It also provides an ILP64 interface. On Apple Silicon
M-processors, it utilises the [proprietary AMX co-processor][apple-amx], which
makes it especially interesting. Unfortunately, it comes without the LAPACKE
C-interface library.
......@@ -44,6 +45,7 @@ include the Accelerate C/C++ headers.
[accelerate-docs]: https://developer.apple.com/documentation/accelerate/blas-library
[apple-amx]: https://github.com/corsix/amx
[lapack-v3.2.1]: https://netlib.org/lapack/#_lapack_version_3_2_1
[lapack-v3.9.1]: https://github.com/Reference-LAPACK/lapack/releases/tag/v3.9.1
[lapack-v3.11.0]: https://github.com/Reference-LAPACK/lapack/releases/tag/v3.11.0
[macos15-release-notes]: https://developer.apple.com/documentation/macos-release-notes/macos-15-release-notes
......@@ -102,9 +104,10 @@ 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 linker option is injected into the Reference LAPACK configure process using
the `CMAKE_EXE_LINKER_FLAGS` variable for the test compiles and the
`CMAKE_SHARED_LINKER_FLAGS` variable for the shared LAPACKE library.
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.&nbsp;g. to be used in the `Eigen3` library). Analyzing
......@@ -113,9 +116,9 @@ the resulting `.dylib` with `otool`, you can see:
```shell
$ 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.9.1)
@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 1336.61.1)
/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
......@@ -127,6 +130,8 @@ After the CMake configuration, the alias files can be found in `./build/<32|64>/
```plaintext
./build/<32|64>/src
├── new-blas-ilp64.alias
├── new-blas.alias
├── new-lapack-ilp64.alias
└── new-lapack.alias
```
......@@ -141,7 +146,7 @@ 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.20 with presets, but the CMake
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.
......@@ -178,10 +183,11 @@ or `/opt/local` (used by MacPorts).
#### CMake v4 compatibility ####
To build the project with CMake v4 or higher, there is a `cmake4` preset, that
you can use in your `CMakeUserPresets.json`. Both `user-accelerate-lapacke32`
and `user-accelerate-lapacke64` should additionally inherit from `cmake4`. This
is not included by default.
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 ###
......
......@@ -42,50 +42,137 @@ build_aliases(BLAS_NEWLAPACK_ILP64_SYMBOLS)
build_aliases(LAPACK_NEWLAPACK_SYMBOLS)
build_aliases(LAPACK_NEWLAPACK_ILP64_SYMBOLS)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/new-lapack.alias"
"\
# BLAS
${BLAS_NEWLAPACK_ALIASES}
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/new-blas.alias.in"
"${CMAKE_CURRENT_BINARY_DIR}/new-blas.alias"
@ONLY
)
# LAPACK
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/new-lapack.alias.in"
"${CMAKE_CURRENT_BINARY_DIR}/new-lapack.alias"
@ONLY
)
${LAPACK_NEWLAPACK_ALIASES}
"
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/new-blas-ilp64.alias.in"
"${CMAKE_CURRENT_BINARY_DIR}/new-blas-ilp64.alias"
@ONLY
)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/new-lapack-ilp64.alias"
"\
# BLAS
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/new-lapack-ilp64.alias.in"
"${CMAKE_CURRENT_BINARY_DIR}/new-lapack-ilp64.alias"
@ONLY
)
${BLAS_NEWLAPACK_ILP64_ALIASES}
add_library(NEW_BLAS INTERFACE IMPORTED GLOBAL)
target_link_libraries(NEW_BLAS INTERFACE ${BLAS_LIBRARIES})
# LAPACK
add_library(NEW_LAPACK INTERFACE IMPORTED GLOBAL)
target_link_libraries(NEW_LAPACK INTERFACE ${LAPACK_LIBRARIES} NEW_BLAS)
${LAPACK_NEWLAPACK_ILP64_ALIASES}
"
# Add the $NEWLAPACK symbols to the linker flags of the NEW_BLAS and NEW_LAPACK
# targets
target_link_options(
NEW_BLAS
INTERFACE
${BLAS_LINKER_FLAGS}
"LINKER:-alias_list,${CMAKE_CURRENT_BINARY_DIR}/new-blas.alias"
)
target_link_options(
NEW_LAPACK
INTERFACE
${LAPACK_LINKER_FLAGS}
"LINKER:-alias_list,${CMAKE_CURRENT_BINARY_DIR}/new-lapack.alias"
)
# Set configuration options for Reference LAPACK
set(BUILD_SHARED_LIBS ON CACHE BOOL "")
set(CBLAS OFF CACHE BOOL "")
set(LAPACKE ON CACHE BOOL "")
add_library(NEW_BLAS64 INTERFACE IMPORTED GLOBAL)
target_link_libraries(NEW_BLAS64 INTERFACE ${BLAS_LIBRARIES})
add_library(NEW_LAPACK64 INTERFACE IMPORTED GLOBAL)
target_link_libraries(NEW_LAPACK64 INTERFACE ${LAPACK_LIBRARIES} NEW_BLAS64)
# Add the $NEWLAPACK symbols to the linker flags used in try_compile()
set(CMAKE_EXE_LINKER_FLAGS "-framework Accelerate -Wl,-alias_list,${CMAKE_CURRENT_BINARY_DIR}/new-lapack.alias")
# Add the $NEWLAPACK$ILP64 symbols to the linker flags of the NEW_BLAS64 and
# NEW_LAPACK64 targets
target_link_options(
NEW_BLAS64
INTERFACE
${BLAS_LINKER_FLAGS}
"LINKER:-alias_list,${CMAKE_CURRENT_BINARY_DIR}/new-blas-ilp64.alias"
)
target_link_options(
NEW_LAPACK64
INTERFACE
${LAPACK_LINKER_FLAGS}
"LINKER:-alias_list,${CMAKE_CURRENT_BINARY_DIR}/new-lapack-ilp64.alias"
)
if (BUILD_INDEX64)
# Add the $NEWLAPACK$ILP64 symbols to the linker flags used for shared libraries
set(CMAKE_SHARED_LINKER_FLAGS "-framework Accelerate -Wl,-alias_list,${CMAKE_CURRENT_BINARY_DIR}/new-lapack-ilp64.alias")
# Add the $NEWLAPACK$ILP64 symbols to the BLAS and LAPACK libraries.
set(BLAS_LIBRARIES "NEW_BLAS64")
set(LAPACK_LIBRARIES "NEW_LAPACK64")
set(CHECK_LAPACK_VERSION_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/lapack64_version.c")
else ()
# Add the $NEWLAPACK symbols to the linker flags used for shared libraries
set(CMAKE_SHARED_LINKER_FLAGS "-framework Accelerate -Wl,-alias_list,${CMAKE_CURRENT_BINARY_DIR}/new-lapack.alias")
# Add the $NEWLAPACK symbols to the linker flags of the lapacke target
set(BLAS_LIBRARIES "NEW_BLAS")
set(LAPACK_LIBRARIES "NEW_LAPACK")
set(CHECK_LAPACK_VERSION_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/lapack_version.c")
endif ()
set_target_properties(BLAS::BLAS PROPERTIES INTERFACE_LINK_LIBRARIES "${BLAS_LIBRARIES}")
set_target_properties(LAPACK::LAPACK PROPERTIES INTERFACE_LINK_LIBRARIES "${LAPACK_LIBRARIES}")
try_run(
HAS_RUN_ILAVER HAS_ILAVER
SOURCES ${CHECK_LAPACK_VERSION_SOURCE}
LINK_LIBRARIES ${LAPACK_LIBRARIES}
RUN_OUTPUT_VARIABLE ACCELERATE_LAPACK_ILAVER_VERSION
)
message(STATUS "The BLAS/LAPACK version provided by the Accelerate framework is confirmed to be: ${ACCELERATE_LAPACK_ILAVER_VERSION}")
FetchContent_Declare(
reference-lapack
GIT_REPOSITORY "https://github.com/Reference-LAPACK/lapack.git"
GIT_TAG "v${ACCELERATE_NEW_LAPACK_VERSION}"
)
# Set configuration options for Reference LAPACK
set(BUILD_SHARED_LIBS ON CACHE BOOL "")
set(CBLAS OFF CACHE BOOL "")
set(LAPACKE ON CACHE BOOL "")
if (CMAKE_VERSION VERSION_GREATER_EQUAL 4)
# CMake deprecated all CMake versions prior to v3.5. The relevant Reference
# LAPACK versions still use v3.2, which leads to an error, unless we
# override this:
set(ENV{CMAKE_POLICY_VERSION_MINIMUM} 3.5)
endif ()
set(BLAS_LIBRARIES_BACKUP "${BLAS_LIBRARIES}")
set(LAPACK_LIBRARIES_BACKUP "${LAPACK_LIBRARIES}")
# Set the BLAS and LAPACK libraries to the new 32bit targets. This helps the
# Reference LAPACK CMake script to pass the CheckFortranFunctionExists tests for
# `dgemm` and `dgeqrt`.
set(BLAS_LIBRARIES "NEW_BLAS")
set(LAPACK_LIBRARIES "NEW_LAPACK")
FetchContent_MakeAvailable(reference-lapack)
# Restore BLAS and LAPACK libraries to what they were before (32bit or 64bit)
set(BLAS_LIBRARIES "${BLAS_LIBRARIES_BACKUP}")
set(LAPACK_LIBRARIES "${LAPACK_LIBRARIES_BACKUP}")
if (CMAKE_VERSION VERSION_GREATER_EQUAL 4)
unset(ENV{CMAKE_POLICY_VERSION_MINIMUM})
endif ()
if (BUILD_INDEX64)
# Replace the LINK_LIBRARIES of the lapacke64 target with the ILP64 ones.
# The lapacke64 target was created linking to the NEW_LAPACK target, which
# we had to add to satisfy the Check... tests, that the Reference LAPACK
# build script does.
set_target_properties(lapacke64 PROPERTIES LINK_LIBRARIES "${LAPACK_LIBRARIES}")
endif ()
/*
* MIT License
*
* CMake build script for the Accelerate LAPACKE project
* Copyright (c) 2025 Tim Kaune
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdio.h>
extern void ilaver_(long int* major, long int* minor, long int* patch);
int main()
{
long int major, minor, patch;
ilaver_(&major, &minor, &patch);
printf("LAPACK v%ld.%ld.%ld", major, minor, patch);
return 0;
}
/*
* MIT License
*
* CMake build script for the Accelerate LAPACKE project
* Copyright (c) 2025 Tim Kaune
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdio.h>
extern void ilaver_(int* major, int* minor, int* patch);
int main()
{
int major, minor, patch;
ilaver_(&major, &minor, &patch);
printf("LAPACK v%d.%d.%d", major, minor, patch);
return 0;
}
# BLAS
@BLAS_NEWLAPACK_ILP64_ALIASES@
# BLAS
@BLAS_NEWLAPACK_ALIASES@
# LAPACK
@LAPACK_NEWLAPACK_ILP64_ALIASES@
# LAPACK
@LAPACK_NEWLAPACK_ALIASES@
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment