2026-08-09 14:13:38 +08:00
|
|
|
cmake_minimum_required(VERSION 3.20)
|
|
|
|
|
|
|
|
|
|
project(
|
|
|
|
|
SpectraREML
|
|
|
|
|
VERSION 0.1.0
|
|
|
|
|
DESCRIPTION "Reusable batched spectral AI-REML engine"
|
|
|
|
|
LANGUAGES CXX
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
include(GNUInstallDirs)
|
|
|
|
|
include(CTest)
|
|
|
|
|
|
|
|
|
|
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|
|
|
|
|
|
|
|
|
set(REML_BLAS "MKL" CACHE STRING "BLAS/LAPACKE backend: MKL or OPENBLAS")
|
|
|
|
|
set_property(CACHE REML_BLAS PROPERTY STRINGS MKL OPENBLAS)
|
|
|
|
|
string(TOUPPER "${REML_BLAS}" REML_BLAS)
|
|
|
|
|
|
|
|
|
|
option(REML_ENABLE_OPENMP "Parallelize independent REML tasks with OpenMP" ON)
|
|
|
|
|
option(REML_ENABLE_NATIVE_ARCH "Enable compiler tuning for the build host" OFF)
|
|
|
|
|
|
|
|
|
|
add_library(reml_blas_lapacke INTERFACE)
|
|
|
|
|
add_library(REML::BLAS_LAPACKE ALIAS reml_blas_lapacke)
|
|
|
|
|
|
|
|
|
|
if(REML_BLAS STREQUAL "MKL")
|
|
|
|
|
# These variables are consumed by Intel's MKLConfig.cmake. Sequential is
|
|
|
|
|
# deliberately the portable default because tasks are parallelized with
|
|
|
|
|
# OpenMP; a threaded BLAS can otherwise create nested thread pools.
|
|
|
|
|
set(MKL_INTERFACE "lp64" CACHE STRING "oneMKL integer interface")
|
|
|
|
|
set(MKL_LINK "dynamic" CACHE STRING "oneMKL link type")
|
|
|
|
|
set(MKL_THREADING "sequential" CACHE STRING "oneMKL threading layer")
|
|
|
|
|
set_property(CACHE MKL_INTERFACE PROPERTY STRINGS lp64 ilp64)
|
|
|
|
|
set_property(CACHE MKL_LINK PROPERTY STRINGS dynamic static)
|
|
|
|
|
set_property(CACHE MKL_THREADING PROPERTY STRINGS sequential intel_thread gnu_thread tbb_thread)
|
|
|
|
|
|
|
|
|
|
find_package(MKL CONFIG REQUIRED)
|
|
|
|
|
if(NOT TARGET MKL::MKL)
|
|
|
|
|
message(FATAL_ERROR "MKL was found, but its MKL::MKL CMake target is missing")
|
|
|
|
|
endif()
|
|
|
|
|
target_link_libraries(reml_blas_lapacke INTERFACE MKL::MKL)
|
|
|
|
|
target_compile_definitions(reml_blas_lapacke INTERFACE REML_BLAS_MKL=1)
|
|
|
|
|
elseif(REML_BLAS STREQUAL "OPENBLAS")
|
|
|
|
|
find_package(REML_OpenBLAS REQUIRED)
|
|
|
|
|
target_link_libraries(reml_blas_lapacke INTERFACE REML::OpenBLASLAPACKE)
|
|
|
|
|
target_compile_definitions(reml_blas_lapacke INTERFACE REML_BLAS_OPENBLAS=1)
|
|
|
|
|
else()
|
|
|
|
|
message(FATAL_ERROR "Unsupported REML_BLAS='${REML_BLAS}'. Choose MKL or OPENBLAS.")
|
|
|
|
|
endif()
|
|
|
|
|
|
|
|
|
|
if(REML_ENABLE_OPENMP)
|
|
|
|
|
find_package(OpenMP REQUIRED COMPONENTS CXX)
|
|
|
|
|
endif()
|
|
|
|
|
|
|
|
|
|
add_library(spectra_reml_core STATIC
|
|
|
|
|
src/linalg.cpp
|
|
|
|
|
src/grm.cpp
|
2026-08-13 07:02:10 +08:00
|
|
|
src/distributions.cpp
|
2026-08-09 14:13:38 +08:00
|
|
|
src/reml_core.cpp
|
2026-08-13 07:02:10 +08:00
|
|
|
src/fixed_effects.cpp
|
2026-08-09 14:13:38 +08:00
|
|
|
src/batch_io.cpp
|
|
|
|
|
)
|
|
|
|
|
add_library(SpectraREML::core ALIAS spectra_reml_core)
|
|
|
|
|
|
|
|
|
|
target_compile_features(spectra_reml_core PUBLIC cxx_std_17)
|
|
|
|
|
target_include_directories(spectra_reml_core
|
|
|
|
|
PUBLIC
|
|
|
|
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
|
|
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
|
|
|
|
)
|
|
|
|
|
target_link_libraries(spectra_reml_core PUBLIC REML::BLAS_LAPACKE)
|
|
|
|
|
|
|
|
|
|
if(REML_ENABLE_OPENMP)
|
|
|
|
|
target_link_libraries(spectra_reml_core PUBLIC OpenMP::OpenMP_CXX)
|
|
|
|
|
target_compile_definitions(spectra_reml_core PUBLIC REML_USE_OPENMP=1)
|
|
|
|
|
endif()
|
|
|
|
|
|
|
|
|
|
if(MSVC)
|
|
|
|
|
target_compile_options(spectra_reml_core PRIVATE /W4 /permissive- /EHsc)
|
|
|
|
|
else()
|
|
|
|
|
target_compile_options(spectra_reml_core PRIVATE -Wall -Wextra -Wpedantic)
|
|
|
|
|
target_compile_definitions(spectra_reml_core PUBLIC _FILE_OFFSET_BITS=64)
|
|
|
|
|
if(REML_ENABLE_NATIVE_ARCH)
|
|
|
|
|
target_compile_options(spectra_reml_core PRIVATE -march=native)
|
|
|
|
|
endif()
|
|
|
|
|
endif()
|
|
|
|
|
|
|
|
|
|
add_executable(spectra_reml src/main.cpp)
|
|
|
|
|
target_link_libraries(spectra_reml PRIVATE SpectraREML::core)
|
|
|
|
|
target_compile_features(spectra_reml PRIVATE cxx_std_17)
|
|
|
|
|
|
|
|
|
|
if(MSVC)
|
|
|
|
|
target_compile_options(spectra_reml PRIVATE /W4 /permissive- /EHsc)
|
|
|
|
|
else()
|
|
|
|
|
target_compile_options(spectra_reml PRIVATE -Wall -Wextra -Wpedantic)
|
|
|
|
|
if(REML_ENABLE_NATIVE_ARCH)
|
|
|
|
|
target_compile_options(spectra_reml PRIVATE -march=native)
|
|
|
|
|
endif()
|
|
|
|
|
endif()
|
|
|
|
|
|
|
|
|
|
if(BUILD_TESTING)
|
|
|
|
|
add_executable(test_reml_synthetic tests/cpp/test_reml_synthetic.cpp)
|
|
|
|
|
target_link_libraries(test_reml_synthetic PRIVATE SpectraREML::core)
|
|
|
|
|
add_test(NAME reml_synthetic COMMAND test_reml_synthetic)
|
|
|
|
|
|
|
|
|
|
add_executable(test_grm_io tests/cpp/test_grm_io.cpp)
|
|
|
|
|
target_link_libraries(test_grm_io PRIVATE SpectraREML::core)
|
|
|
|
|
add_test(NAME grm_io COMMAND test_grm_io)
|
|
|
|
|
endif()
|
|
|
|
|
|
|
|
|
|
install(TARGETS spectra_reml_core spectra_reml
|
|
|
|
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
|
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
|
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
|
|
|
)
|
|
|
|
|
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
|
|
|
|
|
|
|
|
|
message(STATUS "SpectraREML ${PROJECT_VERSION}")
|
|
|
|
|
message(STATUS " BLAS/LAPACKE backend : ${REML_BLAS}")
|
|
|
|
|
message(STATUS " OpenMP : ${REML_ENABLE_OPENMP}")
|
|
|
|
|
message(STATUS " Native architecture : ${REML_ENABLE_NATIVE_ARCH}")
|