Skip to content

Add findBLAS support to CMakeLists.txt #844

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,24 @@ jobs:
compiler: ${{ matrix.toolchain.compiler }}
version: ${{ matrix.toolchain.version }}

# Build and test with built-in BLAS and LAPACK
- name: Configure with CMake
if: ${{ contains(matrix.build, 'cmake') }}
run: >-
cmake -Wdev -G Ninja
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_MAXIMUM_RANK:String=4
-DCMAKE_INSTALL_PREFIX=$PWD/_dist
-DFIND_BLAS:STRING=FALSE
-S . -B ${{ env.BUILD_DIR }}

- name: Build and compile
if: ${{ contains(matrix.build, 'cmake') }}
run: cmake --build ${{ env.BUILD_DIR }} --parallel

- name: catch build fail
run: cmake --build ${{ env.BUILD_DIR }} --verbose --parallel 1
if: ${{ failure() && contains(matrix.build, 'cmake') }}
run: cmake --build ${{ env.BUILD_DIR }} --verbose --parallel 1

- name: test
if: ${{ contains(matrix.build, 'cmake') }}
Expand Down
136 changes: 136 additions & 0 deletions .github/workflows/ci_BLAS.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
name: CI_BLAS

on: [push, pull_request]

env:
CTEST_TIME_TIMEOUT: "5" # some failures hang forever
CMAKE_GENERATOR: Ninja

jobs:
msys2-build:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include: [{ msystem: UCRT64, arch: x86_64 }]
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v2

- name: Setup MinGW native environment
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
update: false
install: >-
git
mingw-w64-ucrt-${{ matrix.arch }}-gcc
mingw-w64-ucrt-${{ matrix.arch }}-gcc-fortran
mingw-w64-ucrt-${{ matrix.arch }}-python
mingw-w64-ucrt-${{ matrix.arch }}-python-fypp
mingw-w64-ucrt-${{ matrix.arch }}-cmake
mingw-w64-ucrt-${{ matrix.arch }}-ninja
mingw-w64-ucrt-${{ matrix.arch }}-openblas

# Build and test with external BLAS and LAPACK (OpenBLAS on UCRT64)
- name: Configure with CMake and OpenBLAS
run: >-
PATH=$PATH:/ucrt64/bin/ cmake
-Wdev
-B build
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_Fortran_FLAGS_DEBUG="-Wall -Wextra -Wimplicit-interface -fPIC -g -fcheck=all -fbacktrace"
-DCMAKE_MAXIMUM_RANK:String=4
-DCMAKE_INSTALL_PREFIX=$PWD/_dist
-DFIND_BLAS:STRING=TRUE
env:
FC: gfortran
CC: gcc
CXX: g++

- name: CMake build with OpenBLAS
run: PATH=$PATH:/ucrt64/bin/ cmake --build build --parallel

- name: catch build fail
if: failure()
run: PATH=$PATH:/ucrt64/bin/ cmake --build build --verbose --parallel 1

- name: CTest with OpenBLAS
run: PATH=$PATH:/ucrt64/bin/ ctest --test-dir build --output-on-failure --parallel -V -LE quadruple_precision

- uses: actions/upload-artifact@v4
if: failure()
with:
name: WindowsCMakeTestlog_openblas
path: build/Testing/Temporary/LastTest.log

- name: Install project with OpenBLAS
run: PATH=$PATH:/ucrt64/bin/ cmake --install build

Build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
toolchain:
- { compiler: intel, version: "2024.1" }
build: [cmake]
env:
BUILD_DIR: ${{ matrix.build == 'cmake' && 'build' || '.' }}
APT_PACKAGES: >-
intel-oneapi-mkl
intel-oneapi-mkl-devel
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python 3.x
uses: actions/setup-python@v5 # Use pip to install latest CMake, & FORD/Jin2For, etc.
with:
python-version: 3.x

- name: Install fypp
run: pip install --upgrade fypp ninja

- name: Setup Fortran compiler
uses: fortran-lang/[email protected]
id: setup-fortran
with:
compiler: ${{ matrix.toolchain.compiler }}
version: ${{ matrix.toolchain.version }}

- name: Install Intel oneAPI MKL
run: |
sudo apt-get install ${APT_PACKAGES}
source /opt/intel/oneapi/mkl/latest/env/vars.sh
printenv >> $GITHUB_ENV

# Build and test with external BLAS and LAPACK (MKL on Ubuntu with Intel compilers)
- name: Configure with CMake and MKL
run: >-
cmake -Wdev -G Ninja
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_MAXIMUM_RANK:String=4
-DCMAKE_INSTALL_PREFIX=$PWD/_dist
-DFIND_BLAS:STRING=TRUE
-S . -B ${{ env.BUILD_DIR }}

- name: Build and compile with MKL
run: cmake --build ${{ env.BUILD_DIR }} --parallel

- name: catch build fail with MKL
if: failure()
run: cmake --build ${{ env.BUILD_DIR }} --verbose --parallel 1

- name: test with MKL
run: >-
ctest
--test-dir ${{ env.BUILD_DIR }}
--parallel
--output-on-failure
--no-tests=error

- name: Install project with MKL
run: cmake --install ${{ env.BUILD_DIR }}
1 change: 1 addition & 0 deletions .github/workflows/ci_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
-DCMAKE_Fortran_FLAGS_DEBUG="-Wall -Wextra -Wimplicit-interface -fPIC -g -fcheck=all -fbacktrace"
-DCMAKE_MAXIMUM_RANK:String=4
-DCMAKE_INSTALL_PREFIX=$PWD/_dist
-DFIND_BLAS:STRING=FALSE
env:
FC: gfortran
CC: gcc
Expand Down
26 changes: 26 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,32 @@ if(NOT DEFINED CMAKE_MAXIMUM_RANK)
set(CMAKE_MAXIMUM_RANK 4 CACHE STRING "Maximum array rank for generated procedures")
endif()

option(FIND_BLAS "Find external BLAS and LAPACK" ON)

# --- find BLAS and LAPACK
if(FIND_BLAS)
if(NOT BLAS_FOUND)
#Required for MKL
if(DEFINED ENV{MKLROOT} OR "${BLA_VENDOR}" MATCHES "^Intel")
enable_language("C")
endif()
find_package("BLAS")
endif()
if(BLAS_FOUND)
add_compile_definitions(STDLIB_EXTERNAL_BLAS)
endif()
if(NOT LAPACK_FOUND)
#Required for MKL
if(DEFINED ENV{MKLROOT} OR "${BLA_VENDOR}" MATCHES "^Intel")
enable_language("C")
endif()
find_package("LAPACK")
endif()
if(LAPACK_FOUND)
add_compile_definitions(STDLIB_EXTERNAL_LAPACK)
endif()
endif()

# --- find preprocessor
find_program(FYPP fypp)
if(NOT FYPP)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ Important options are
- `-DBUILD_TESTING` set to `off` in case you want to disable the stdlib tests (default: `on`).
- `-DCMAKE_VERBOSE_MAKEFILE` is by default set to `Off`, but if set to `On` will show commands used to compile the code.
- `-DCMAKE_BUILD_TYPE` is by default set to `RelWithDebInfo`, which uses compiler flags suitable for code development (but with only `-O2` optimization). Beware the compiler flags set this way will override any compiler flags specified via `FFLAGS`. To prevent this, use `-DCMAKE_BUILD_TYPE=NoConfig` in conjunction with `FFLAGS`.
- `-DFIND_BLAS` set to `off` in case you want to disable finding the external BLAS/LAPACK dependency (default: `on`).

For example, to configure a build using the Ninja backend while specifying compiler optimization via `FFLAGS`, generating procedures up to rank 7, installing to your home directory, using the `NoConfig` compiler flags, and printing the compiler commands, use

Expand Down
17 changes: 2 additions & 15 deletions config/fypp_deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,8 @@
C_PREPROCESSED = (
"stdlib_linalg_constants" ,
"stdlib_linalg_blas" ,
"stdlib_linalg_blas_aux",
"stdlib_linalg_blas_s",
"stdlib_linalg_blas_d",
"stdlib_linalg_blas_q",
"stdlib_linalg_blas_c",
"stdlib_linalg_blas_z",
"stdlib_linalg_blas_w",
"stdlib_linalg_lapack",
"stdlib_linalg_lapack_aux",
"stdlib_linalg_lapack_s",
"stdlib_linalg_lapack_d",
"stdlib_linalg_lapack_q",
"stdlib_linalg_lapack_c",
"stdlib_linalg_lapack_z",
"stdlib_linalg_lapack_w"
"test_blas_lapack"
)

def pre_process_fypp(args):
Expand Down Expand Up @@ -105,7 +92,7 @@ def recursive_copy(folder):
for root, _, files in os.walk(folder):
for file in files:
if file not in prune:
if file.endswith((".f90", ".F90", ".dat", ".npy", ".c")):
if file.endswith((".f90", ".F90", ".dat", ".npy", ".c", ".h")):
shutil.copy2(os.path.join(root, file), base_folder+os.sep+folder+os.sep+file)
recursive_copy('src')
recursive_copy('test')
Expand Down
8 changes: 8 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ set(SRC

add_library(${PROJECT_NAME} ${SRC})

# Link to BLAS and LAPACK
if(BLAS_FOUND)
target_link_libraries(${PROJECT_NAME} "BLAS::BLAS")
endif()
if(LAPACK_FOUND)
target_link_libraries(${PROJECT_NAME} "LAPACK::LAPACK")
endif()

set_target_properties(
${PROJECT_NAME}
PROPERTIES
Expand Down
4 changes: 0 additions & 4 deletions src/blas/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ set(dir "${CMAKE_CURRENT_SOURCE_DIR}")

list(APPEND fppFiles
blas/stdlib_blas_constants.fypp
)

list(APPEND cppFiles
blas/stdlib_blas.fypp
blas/stdlib_blas_level1.fypp
blas/stdlib_blas_level2_ban.fypp
Expand All @@ -21,4 +18,3 @@ list(APPEND cppFiles
)

set(fppFiles "${fppFiles}" PARENT_SCOPE)
set(cppFiles "${cppFiles}" PARENT_SCOPE)
4 changes: 2 additions & 2 deletions src/lapack/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
list(APPEND cppFiles
list(APPEND fppFiles
lapack/stdlib_lapack_base.fypp
lapack/stdlib_lapack_solve.fypp
lapack/stdlib_lapack_others.fypp
Expand Down Expand Up @@ -55,4 +55,4 @@ list(APPEND cppFiles
lapack/stdlib_lapack_svd_comp2.fypp
)

set(cppFiles "${cppFiles}" PARENT_SCOPE)
set(fppFiles "${fppFiles}" PARENT_SCOPE)
11 changes: 10 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ macro(ADDTEST name)
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endmacro(ADDTEST)

macro(ADDTESTPP name)
add_executable(test_${name} test_${name}.F90)
target_link_libraries(test_${name} "${PROJECT_NAME}" "test-drive::test-drive")
add_test(NAME ${name}
COMMAND $<TARGET_FILE:test_${name}> ${CMAKE_CURRENT_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endmacro(ADDTESTPP)


add_subdirectory(array)
add_subdirectory(ascii)
add_subdirectory(bitsets)
Expand All @@ -31,4 +40,4 @@ add_subdirectory(system)
add_subdirectory(quadrature)
add_subdirectory(math)
add_subdirectory(stringlist)
add_subdirectory(terminal)
add_subdirectory(terminal)
13 changes: 10 additions & 3 deletions test/linalg/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
set(
fppFiles
"test_linalg.fypp"
"test_blas_lapack.fypp"
"test_linalg_cholesky.fypp"
"test_linalg_eigenvalues.fypp"
"test_linalg_solve.fypp"
"test_linalg_inverse.fypp"
Expand All @@ -16,8 +14,17 @@ set(
"test_linalg_svd.fypp"
"test_linalg_matrix_property_checks.fypp"
"test_linalg_sparse.fypp"
"test_linalg_cholesky.fypp"
)

# Preprocessed files to contain preprocessor directives -> .F90
set(
cppFiles
"test_blas_lapack.fypp"
)

fypp_f90("${fyppFlags}" "${fppFiles}" outFiles)
fypp_f90pp("${fyppFlags}" "${cppFiles}" outPreprocFiles)

ADDTEST(linalg)
ADDTEST(linalg_cholesky)
Expand All @@ -33,5 +40,5 @@ ADDTEST(linalg_lstsq)
ADDTEST(linalg_qr)
ADDTEST(linalg_schur)
ADDTEST(linalg_svd)
ADDTEST(blas_lapack)
ADDTEST(linalg_sparse)
ADDTESTPP(blas_lapack)
Loading
Loading