# SPDX-License-Identifier: MPL-2.0 cmake_minimum_required(VERSION 3.15) project( aare DESCRIPTION "Data processing library for PSI detectors" HOMEPAGE_URL "https://github.com/slsdetectorgroup/aare" LANGUAGES C CXX) # Read VERSION file into project version set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION") file(READ "${VERSION_FILE}" VERSION_CONTENT) string(STRIP "${VERSION_CONTENT}" PROJECT_VERSION_STRING) set(PROJECT_VERSION ${PROJECT_VERSION_STRING}) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) execute_process( COMMAND git log -1 --format=%h WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} OUTPUT_VARIABLE GIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE) message(STATUS "Building from git hash: ${GIT_HASH}") if(${CMAKE_VERSION} VERSION_GREATER "3.24") cmake_policy(SET CMP0135 NEW) # Fetch content download timestamp endif() cmake_policy(SET CMP0079 NEW) include(GNUInstallDirs) include(FetchContent) # Set default build type if none was specified include(cmake/helpers.cmake) default_build_type("Release") set_std_fs_lib() message(STATUS "Extra linking to fs lib:${STD_FS_LIB}") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) # General options option(AARE_PYTHON_BINDINGS "Build python bindings" OFF) option(AARE_TESTS "Build tests" OFF) option(AARE_BENCHMARKS "Build benchmarks" OFF) option(AARE_EXAMPLES "Build examples" OFF) option(AARE_IN_GITHUB_ACTIONS "Running in Github Actions" OFF) option(AARE_DOCS "Build documentation" OFF) option(AARE_VERBOSE "Verbose output" OFF) option(AARE_CUSTOM_ASSERT "Use custom assert" OFF) option( AARE_INSTALL_PYTHONEXT "Install the python extension in the install tree under CMAKE_INSTALL_PREFIX/aare/" OFF) option(AARE_ASAN "Enable AddressSanitizer" OFF) # Configure which of the dependencies to use FetchContent for option(AARE_FETCH_FMT "Use FetchContent to download fmt" ON) option(AARE_FETCH_PYBIND11 "Use FetchContent to download pybind11" ON) option(AARE_FETCH_CATCH "Use FetchContent to download catch2" ON) option(AARE_FETCH_JSON "Use FetchContent to download nlohmann::json" ON) option(AARE_FETCH_ZMQ "Use FetchContent to download libzmq" ON) option(AARE_FETCH_LMFIT "Use FetchContent to download lmfit" ON) option(AARE_FETCH_MINUIT2 "Use FetchContent to download Minuit2" ON) # Convenience option to use system libraries only (no FetchContent) option(AARE_SYSTEM_LIBRARIES "Use system libraries" OFF) if(AARE_SYSTEM_LIBRARIES) message(STATUS "Build using system libraries") set(AARE_FETCH_FMT OFF CACHE BOOL "Disabled FetchContent for FMT" FORCE) set(AARE_FETCH_PYBIND11 OFF CACHE BOOL "Disabled FetchContent for pybind11" FORCE) set(AARE_FETCH_CATCH OFF CACHE BOOL "Disabled FetchContent for catch2" FORCE) set(AARE_FETCH_JSON OFF CACHE BOOL "Disabled FetchContent for nlohmann::json" FORCE) set(AARE_FETCH_ZMQ OFF CACHE BOOL "Disabled FetchContent for libzmq" FORCE) # Still fetch lmfit and Minuit2 when setting AARE_SYSTEM_LIBRARIES since these # are not available on conda-forge endif() if(AARE_BENCHMARKS) add_subdirectory(benchmarks) endif() set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if(AARE_FETCH_LMFIT) # TODO! Should we fetch lmfit from the web or inlcude a tar.gz in the repo? set(LMFIT_PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/patches/lmfit.patch) # For cmake < 3.28 we can't supply EXCLUDE_FROM_ALL to FetchContent_Declare so # we need this workaround if(${CMAKE_VERSION} VERSION_LESS "3.28") FetchContent_Declare( lmfit GIT_REPOSITORY https://jugit.fz-juelich.de/mlz/lmfit.git GIT_TAG main PATCH_COMMAND ${LMFIT_PATCH_COMMAND} UPDATE_DISCONNECTED 1) else() FetchContent_Declare( lmfit GIT_REPOSITORY https://jugit.fz-juelich.de/mlz/lmfit.git GIT_TAG main PATCH_COMMAND ${LMFIT_PATCH_COMMAND} UPDATE_DISCONNECTED 1 EXCLUDE_FROM_ALL 1) endif() # Disable what we don't need from lmfit set(BUILD_TESTING OFF CACHE BOOL "") set(LMFIT_CPPTEST OFF CACHE BOOL "") set(LIB_MAN OFF CACHE BOOL "") set(LMFIT_CPPTEST OFF CACHE BOOL "") set(BUILD_SHARED_LIBS OFF CACHE BOOL "") if(${CMAKE_VERSION} VERSION_LESS "3.28") if(NOT lmfit_POPULATED) FetchContent_Populate(lmfit) add_subdirectory(${lmfit_SOURCE_DIR} ${lmfit_BINARY_DIR} EXCLUDE_FROM_ALL) endif() else() FetchContent_MakeAvailable(lmfit) endif() set_property(TARGET lmfit PROPERTY POSITION_INDEPENDENT_CODE ON) else() find_package(lmfit REQUIRED) endif() if(AARE_FETCH_MINUIT2) # Patch minuit2 to avoid messing with cmake policies set(MINUIT2_PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/patches/minuit2.patch) FetchContent_Declare( Minuit2 GIT_REPOSITORY https://github.com/GooFit/Minuit2.git GIT_TAG master PATCH_COMMAND ${MINUIT2_PATCH_COMMAND} UPDATE_DISCONNECTED 1) # Disable Minuit2 extras we don't need set(minuit2_mpi OFF CACHE BOOL "") set(minuit2_omp OFF CACHE BOOL "") set(BUILD_TESTING OFF CACHE BOOL "") set(MINUIT2_INSTALL ON CACHE BOOL "") FetchContent_MakeAvailable(Minuit2) set_property(TARGET Minuit2Math PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET Minuit2 PROPERTY POSITION_INDEPENDENT_CODE ON) else() find_package(Minuit2 REQUIRED) endif() if(AARE_FETCH_ZMQ) # Fetchcontent_Declare is deprecated need to find a way to update this for now # setting the policy to old is enough if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.30") cmake_policy(SET CMP0169 OLD) endif() set(ZMQ_PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/patches/libzmq_cmake_version.patch) FetchContent_Declare( libzmq GIT_REPOSITORY https://github.com/zeromq/libzmq.git GIT_TAG v4.3.4 PATCH_COMMAND ${ZMQ_PATCH_COMMAND} UPDATE_DISCONNECTED 1) # Disable unwanted options from libzmq set(BUILD_TESTS OFF CACHE BOOL "Switch off libzmq test build") set(BUILD_SHARED OFF CACHE BOOL "Switch off libzmq shared libs") set(WITH_PERF_TOOL OFF CACHE BOOL "") set(ENABLE_CPACK OFF CACHE BOOL "") set(ENABLE_CLANG OFF CACHE BOOL "") set(ENABLE_CURVE OFF CACHE BOOL "") set(ENABLE_DRAFTS OFF CACHE BOOL "") # TODO! Verify that this is what we want to do in aare Using GetProperties and # Populate to be able to exclude zmq from install (not possible with # FetchContent_MakeAvailable(libzmq)) FetchContent_GetProperties(libzmq) if(NOT libzmq_POPULATED) FetchContent_Populate(libzmq) add_subdirectory(${libzmq_SOURCE_DIR} ${libzmq_BINARY_DIR} EXCLUDE_FROM_ALL) endif() else() find_package(ZeroMQ 4 REQUIRED) endif() if(AARE_FETCH_FMT) set(FMT_TEST OFF CACHE INTERNAL "disabling fmt tests") FetchContent_Declare( fmt GIT_REPOSITORY https://github.com/fmtlib/fmt.git GIT_TAG 12.1.0 GIT_PROGRESS TRUE USES_TERMINAL_DOWNLOAD TRUE) set(FMT_INSTALL ON CACHE BOOL "") FetchContent_MakeAvailable(fmt) set_property(TARGET fmt PROPERTY POSITION_INDEPENDENT_CODE ON) else() find_package(fmt 6 REQUIRED) endif() if(AARE_FETCH_JSON) FetchContent_Declare( json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) set(JSON_Install ON CACHE BOOL "") FetchContent_MakeAvailable(json) else() find_package(nlohmann_json 3.11.3 REQUIRED) endif() include(GNUInstallDirs) # If conda build, always set lib dir to 'lib' if($ENV{CONDA_BUILD}) set(CMAKE_INSTALL_LIBDIR "lib") endif() # Set lower / upper case project names string(TOUPPER "${PROJECT_NAME}" PROJECT_NAME_UPPER) string(TOLOWER "${PROJECT_NAME}" PROJECT_NAME_LOWER) # Set targets export name (used by slsDetectorPackage and dependencies) set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWER}-targets") set(namespace "aare::") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) # Check if project is being used directly or via add_subdirectory set(AARE_MASTER_PROJECT OFF) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(AARE_MASTER_PROJECT ON) endif() add_library(aare_compiler_flags INTERFACE) target_compile_features(aare_compiler_flags INTERFACE cxx_std_17) # ############################################################################## # MSVC specific # # ############################################################################## if(MSVC) add_compile_definitions(AARE_MSVC) if(CMAKE_BUILD_TYPE STREQUAL "Release") message(STATUS "Release build") target_compile_options(aare_compiler_flags INTERFACE /O2) else() message(STATUS "Debug build") target_compile_options(aare_compiler_flags INTERFACE /Od /Zi /MDd /D_ITERATOR_DEBUG_LEVEL=2) target_link_options(aare_compiler_flags INTERFACE /DEBUG:FULL) endif() target_compile_options(aare_compiler_flags INTERFACE /w # disable warnings ) else() # ############################################################################ # GCC/Clang specific # # ############################################################################ if(CMAKE_BUILD_TYPE STREQUAL "Release") message(STATUS "Release build") target_compile_options(aare_compiler_flags INTERFACE -O3) else() message(STATUS "Debug build") endif() # Common flags for GCC and Clang target_compile_options( aare_compiler_flags INTERFACE -Wall -Wextra -pedantic -Wshadow -Wold-style-cast -Wnon-virtual-dtor -Woverloaded-virtual -Wdouble-promotion -Wformat=2 -Wredundant-decls -Wvla -Wdouble-promotion -Werror=return-type # important can cause segfault in optimzed # builds ) endif() # GCC/Clang specific if(AARE_PYTHON_BINDINGS) add_subdirectory(python) endif() if(AARE_ASAN) message(STATUS "AddressSanitizer enabled") target_compile_options( aare_compiler_flags INTERFACE -fsanitize=address,undefined,pointer-compare -fno-omit-frame-pointer) target_link_libraries( aare_compiler_flags INTERFACE -fsanitize=address,undefined,pointer-compare -fno-omit-frame-pointer) endif() if(AARE_TESTS) enable_testing() add_subdirectory(tests) target_compile_definitions(tests PRIVATE AARE_TESTS) endif() # ------------------------------------------------------------------------------MAIN # LIBRARY # ------------------------------------------------------------------------------------------ set(PUBLICHEADERS include/aare/ArrayExpr.hpp include/aare/CalculateEta.hpp include/aare/Cluster.hpp include/aare/ClusterFinder.hpp include/aare/ClusterFile.hpp include/aare/CtbRawFile.hpp include/aare/ClusterVector.hpp include/aare/decode.hpp include/aare/defs.hpp include/aare/Dtype.hpp include/aare/File.hpp include/aare/Fit.hpp include/aare/Chi2.hpp include/aare/FitModel.hpp include/aare/Models.hpp include/aare/FileInterface.hpp include/aare/FilePtr.hpp include/aare/Frame.hpp include/aare/hist/PixelHistogram.hpp include/aare/hist/PixelHistogramImpl.hpp include/aare/hist/PedestalTrackingPixelHistogram.hpp include/aare/GainMap.hpp include/aare/ROIGeometry.hpp include/aare/DetectorGeometry.hpp include/aare/JungfrauDataFile.hpp include/aare/logger.hpp include/aare/NDArray.hpp include/aare/NDView.hpp include/aare/NumpyFile.hpp include/aare/NumpyHelpers.hpp include/aare/Pedestal.hpp include/aare/PixelMap.hpp include/aare/RawFile.hpp include/aare/RawMasterFile.hpp include/aare/RawSubFile.hpp include/aare/VarClusterFinder.hpp include/aare/utils/task.hpp) set(SourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/src/calibration.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/CtbRawFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/decode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ROIGeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/DetectorGeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/hist/PixelHistogram.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/hist/PedestalTrackingPixelHistogram.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/File.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/FilePtr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Fit.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Interpolator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/JungfrauDataFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/PixelMap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawMasterFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/ifstream_helpers.cpp) add_library(aare_core STATIC ${SourceFiles} ${PUBLICHEADERS}) target_include_directories( aare_core PUBLIC "$" "$") set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) target_link_libraries( aare_core PUBLIC fmt::fmt nlohmann_json::nlohmann_json ${STD_FS_LIB} # from # helpers.cmake Minuit2::Minuit2 PRIVATE aare_compiler_flags Threads::Threads $) target_include_directories( aare_core SYSTEM PRIVATE $) set_property(TARGET aare_core PROPERTY POSITION_INDEPENDENT_CODE ON) if(AARE_TESTS) target_compile_definitions(aare_core PRIVATE AARE_TESTS) endif() if(AARE_VERBOSE) target_compile_definitions(aare_core PUBLIC AARE_VERBOSE) target_compile_definitions(aare_core PUBLIC AARE_LOG_LEVEL=aare::logDEBUG5) else() target_compile_definitions(aare_core PUBLIC AARE_LOG_LEVEL=aare::logERROR) endif() if(AARE_CUSTOM_ASSERT) target_compile_definitions(aare_core PUBLIC AARE_CUSTOM_ASSERT) endif() set_target_properties(aare_core PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) if(AARE_TESTS) set(TestSources ${CMAKE_CURRENT_SOURCE_DIR}/src/algorithm.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/calibration.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/decode.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/DetectorGeometry.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Interpolation.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawMasterFile.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NDArray.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NDView.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFinder.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterVector.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Cluster.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/CalculateEta.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFile.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFinderMT.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Pedestal.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/hist/PixelHistogramImpl.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/hist/PixelHistogram.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/JungfrauDataFile.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.test.cpp) target_sources(tests PRIVATE ${TestSources}) endif() if(AARE_MASTER_PROJECT) install( TARGETS aare_core aare_compiler_flags EXPORT "${TARGETS_EXPORT_NAME}" LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/aare/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/aare FILES_MATCHING PATTERN "*.hpp") endif() set(CMAKE_INSTALL_RPATH $ORIGIN) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) # #Overall target to link to when using the library add_library(aare INTERFACE) # target_link_libraries(aare INTERFACE aare_core aare_compiler_flags) # target_include_directories(aare INTERFACE # $ # $ ) # add_subdirectory(examples) if(AARE_DOCS) add_subdirectory(docs) endif() # custom target to run check formatting with clang-format add_custom_target( check-format COMMAND find \\ (-name "*.cpp" -o -name "*.hpp" \\) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -Werror -style=\"file:.clang-format\" {} | diff {} -" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Checking code formatting with clang-format" VERBATIM) add_custom_target( format-files COMMAND find \\ (-name "*.cpp" -o -name "*.hpp" \\) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -i -style=\"file:.clang-format\" {}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Formatting with clang-format" VERBATIM) if(AARE_IN_GITHUB_ACTIONS) message(STATUS "Running in Github Actions") set(CLANG_TIDY_COMMAND "clang-tidy-17") else() set(CLANG_TIDY_COMMAND "clang-tidy") endif() add_custom_target( clang-tidy COMMAND find \\ (-path "./src/*" -a -not -path "./src/python/*" -a \\ (-name "*.cpp" -not -name "*.test.cpp" \\) \\) -not -name "CircularFifo.hpp" -not -name "ProducerConsumerQueue.hpp" -not -name "VariableSizeClusterFinder.hpp" | xargs -I {} -n 1 -P 10 bash -c "${CLANG_TIDY_COMMAND} --config-file=.clang-tidy -p build {}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "linting with clang-tidy" VERBATIM) if(AARE_MASTER_PROJECT) set(CMAKE_INSTALL_DIR "share/cmake/${PROJECT_NAME}") set(PROJECT_LIBRARIES aare-core aare-compiler-flags) include(cmake/package_config.cmake) endif()