1cmake_minimum_required(VERSION 3.28)2project(raid VERSION 0.1.0 LANGUAGES CXX)34# ---------------------------------------------------------------------------5# RAID — Research Architecture for Intraday Data (UQO WP 40)6# C++20 core + CPU backend (portable) + optional Metal backend (macOS arm64).7# ---------------------------------------------------------------------------8set(CMAKE_CXX_STANDARD 20)9set(CMAKE_CXX_STANDARD_REQUIRED ON)10set(CMAKE_CXX_EXTENSIONS OFF)11set(CMAKE_POSITION_INDEPENDENT_CODE ON)12set(CMAKE_EXPORT_COMPILE_COMMANDS ON)13if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)14 set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)15endif()1617option(RAID_ENABLE_METAL "Build the Metal backend (macOS only)" ${APPLE})18option(RAID_WITH_ARROW "Build the Arrow/Parquet reader (requires Apache Arrow C++)" ON)19option(RAID_WITH_ACCELERATE "Use Apple Accelerate BLAS/LAPACK through Eigen (macOS only)" ${APPLE})20option(RAID_BUILD_TESTS "Build Catch2 tests" ON)21option(RAID_BUILD_BENCH "Build benchmark executables" ON)22option(RAID_BUILD_CLI "Build the raid command-line tool" ON)23option(RAID_BUILD_PYTHON "Build the nanobind Python extension" OFF)24option(RAID_NATIVE_ARCH "Tune for the host CPU (-mcpu=native)" ON)25option(RAID_WERROR "Treat warnings as errors" OFF)2627list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")28include(GNUInstallDirs)2930# ---- dependencies ----------------------------------------------------------31find_package(Eigen3 REQUIRED CONFIG)32find_package(nlohmann_json 3.11 REQUIRED CONFIG)33find_package(CURL REQUIRED) # system libcurl (macOS SDK / Linux)34find_package(Threads REQUIRED)35if(RAID_WITH_ARROW)36 find_package(Arrow CONFIG QUIET)37 find_package(Parquet CONFIG QUIET)38 if(NOT Arrow_FOUND OR NOT Parquet_FOUND)39 message(WARNING "RAID_WITH_ARROW=ON but Arrow/Parquet not found; building without Arrow")40 set(RAID_WITH_ARROW OFF)41 endif()42endif()4344# ---- compile options -------------------------------------------------------45add_library(raid_options INTERFACE)46target_compile_options(raid_options INTERFACE47 $<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wno-sign-conversion>48 $<$<AND:$<CXX_COMPILER_ID:Clang,AppleClang,GNU>,$<BOOL:${RAID_WERROR}>>:-Werror>49 $<$<AND:$<CXX_COMPILER_ID:Clang,AppleClang,GNU>,$<CONFIG:Release>>:-O3>50)51if(RAID_NATIVE_ARCH AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")52 target_compile_options(raid_options INTERFACE -mcpu=native)53endif()54# Floating-point semantics: strict IEEE (no -ffast-math) so that CPU FP64 is a true reference.55target_compile_options(raid_options INTERFACE $<$<CXX_COMPILER_ID:Clang,AppleClang>:-ffp-model=precise>)5657# ---- core library ----------------------------------------------------------58file(GLOB_RECURSE RAID_CORE_SOURCES CONFIGURE_DEPENDS59 src/core/*.cpp src/data/*.cpp src/statistics/*.cpp src/estimators/*.cpp src/models/*.cpp backends/cpu/*.cpp)60if(NOT RAID_WITH_ARROW)61 list(FILTER RAID_CORE_SOURCES EXCLUDE REGEX ".*parquet_arrow\\.cpp$")62endif()63add_library(raid ${RAID_CORE_SOURCES})64add_library(raid::raid ALIAS raid)65target_include_directories(raid PUBLIC66 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>67 $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)68target_link_libraries(raid PUBLIC Eigen3::Eigen nlohmann_json::nlohmann_json Threads::Threads CURL::libcurl raid_options)69target_compile_definitions(raid PUBLIC RAID_VERSION="${PROJECT_VERSION}" RAID_WITH_FINDATA=1)70if(RAID_WITH_ARROW)71 target_link_libraries(raid PUBLIC Arrow::arrow_shared Parquet::parquet_shared)72 target_compile_definitions(raid PUBLIC RAID_WITH_ARROW=1)73endif()74if(APPLE AND RAID_WITH_ACCELERATE)75 target_compile_definitions(raid PUBLIC RAID_WITH_ACCELERATE=1 EIGEN_USE_BLAS=1 ACCELERATE_NEW_LAPACK=1 ACCELERATE_LAPACK_ILP64=0)76 target_link_libraries(raid PUBLIC "-framework Accelerate")77endif()7879# ---- Metal backend ---------------------------------------------------------80if(RAID_ENABLE_METAL)81 if(NOT APPLE)82 message(FATAL_ERROR "RAID_ENABLE_METAL requires macOS")83 endif()84 file(GLOB _raid_metal_probe CONFIGURE_DEPENDS backends/metal/host/*.mm)85 if(NOT _raid_metal_probe)86 message(STATUS "Metal backend sources not present yet (Phase 3): building without Metal")87 set(RAID_ENABLE_METAL OFF)88 endif()89endif()90if(RAID_ENABLE_METAL)91 enable_language(OBJCXX)92 set(CMAKE_OBJCXX_STANDARD 20)93 file(GLOB RAID_METAL_HOST CONFIGURE_DEPENDS backends/metal/host/*.mm backends/metal/host/*.cpp)94 file(GLOB RAID_METAL_SHADERS CONFIGURE_DEPENDS backends/metal/shaders/*.metal)95 add_library(raid_metal ${RAID_METAL_HOST})96 target_link_libraries(raid_metal PUBLIC raid "-framework Metal" "-framework Foundation")97 target_compile_options(raid_metal PRIVATE -fobjc-arc)98 target_compile_definitions(raid PUBLIC RAID_ENABLE_METAL=1)99 # Embed the MSL sources as a string (runtime compilation fallback / cold-compile benchmark)100 set(RAID_MSL_BUNDLE "${CMAKE_CURRENT_BINARY_DIR}/raid_msl_bundle.cpp")101 add_custom_command(OUTPUT ${RAID_MSL_BUNDLE}102 COMMAND ${CMAKE_COMMAND} -DOUT=${RAID_MSL_BUNDLE} "-DSHADERS=${RAID_METAL_SHADERS}" -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/EmbedMSL.cmake103 DEPENDS ${RAID_METAL_SHADERS} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/EmbedMSL.cmake COMMENT "Embedding MSL sources")104 target_sources(raid_metal PRIVATE ${RAID_MSL_BUNDLE})105 # Optional offline metallib (requires the Metal Toolchain). Missing toolchain => runtime compile only.106 find_program(RAID_XCRUN xcrun)107 if(RAID_XCRUN AND RAID_METAL_SHADERS)108 execute_process(COMMAND ${RAID_XCRUN} -sdk macosx metal --version RESULT_VARIABLE _mt_rc OUTPUT_QUIET ERROR_QUIET)109 if(_mt_rc EQUAL 0)110 set(RAID_METALLIB "${CMAKE_CURRENT_BINARY_DIR}/raid.metallib")111 set(_airs)112 foreach(s ${RAID_METAL_SHADERS})113 get_filename_component(n ${s} NAME_WE)114 add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${n}.air115 COMMAND ${RAID_XCRUN} -sdk macosx metal -O2 -fno-fast-math -c ${s} -o ${CMAKE_CURRENT_BINARY_DIR}/${n}.air116 DEPENDS ${s} COMMENT "metal ${n}")117 list(APPEND _airs ${CMAKE_CURRENT_BINARY_DIR}/${n}.air)118 endforeach()119 add_custom_command(OUTPUT ${RAID_METALLIB} COMMAND ${RAID_XCRUN} -sdk macosx metallib ${_airs} -o ${RAID_METALLIB} DEPENDS ${_airs} COMMENT "metallib")120 add_custom_target(raid_metallib ALL DEPENDS ${RAID_METALLIB})121 add_dependencies(raid_metal raid_metallib)122 target_compile_definitions(raid_metal PRIVATE RAID_METALLIB_PATH="${RAID_METALLIB}")123 message(STATUS "Metal toolchain found: building raid.metallib")124 else()125 message(STATUS "Metal toolchain not found: runtime MSL compilation only")126 endif()127 endif()128endif()129130# ---- CLI --------------------------------------------------------------------131if(RAID_BUILD_CLI)132 add_executable(raid_cli cli/raid.cpp)133 set_target_properties(raid_cli PROPERTIES OUTPUT_NAME raid)134 target_link_libraries(raid_cli PRIVATE raid)135 if(RAID_ENABLE_METAL)136 target_link_libraries(raid_cli PRIVATE raid_metal)137 endif()138endif()139140# ---- examples -----------------------------------------------------------------141add_executable(example_minimal examples/cpp/minimal.cpp)142target_link_libraries(example_minimal PRIVATE raid)143if(RAID_ENABLE_METAL)144 target_link_libraries(example_minimal PRIVATE raid_metal)145endif()146147# ---- tests ------------------------------------------------------------------148if(RAID_BUILD_TESTS)149 find_package(Catch2 3 CONFIG REQUIRED)150 include(CTest)151 include(Catch)152 file(GLOB_RECURSE RAID_TEST_SOURCES CONFIGURE_DEPENDS tests/unit/*.cpp tests/property/*.cpp tests/reference/*.cpp tests/simulation/*.cpp tests/stress/*.cpp tests/integration/*.cpp)153 add_executable(raid_tests ${RAID_TEST_SOURCES})154 target_link_libraries(raid_tests PRIVATE raid Catch2::Catch2WithMain)155 target_compile_definitions(raid_tests PRIVATE RAID_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")156 if(RAID_ENABLE_METAL)157 target_link_libraries(raid_tests PRIVATE raid_metal)158 endif()159 catch_discover_tests(raid_tests)160endif()161162# ---- benchmarks ---------------------------------------------------------------163if(RAID_BUILD_BENCH)164 file(GLOB RAID_BENCH_SOURCES CONFIGURE_DEPENDS benchmarks/micro/*.cpp benchmarks/end_to_end/*.cpp benchmarks/accuracy/*.cpp benchmarks/scalability/*.cpp)165 foreach(b ${RAID_BENCH_SOURCES})166 get_filename_component(n ${b} NAME_WE)167 add_executable(bench_${n} ${b})168 target_link_libraries(bench_${n} PRIVATE raid)169 if(RAID_ENABLE_METAL)170 target_link_libraries(bench_${n} PRIVATE raid_metal)171 endif()172 endforeach()173endif()174175# ---- Python -------------------------------------------------------------------176if(RAID_BUILD_PYTHON)177 add_subdirectory(bindings/python)178endif()179180# ---- install -----------------------------------------------------------------181install(TARGETS raid raid_options EXPORT raidTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})182if(RAID_ENABLE_METAL)183 install(TARGETS raid_metal EXPORT raidTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})184endif()185if(RAID_BUILD_CLI)186 install(TARGETS raid_cli RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})187endif()188install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})189install(EXPORT raidTargets NAMESPACE raid:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/raid)190