# git header
# the commit's SHA1, and whether the building workspace was dirty or not

FIND_PACKAGE(Git)

SET(GITINFO_SOURCE_DIR "${CMAKE_SOURCE_DIR}")
SET(GITINFO_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/GitInfo.cpp.in")
SET(GITINFO_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/GitInfo.cpp")
SET(JFJOCH_BUILD_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# The compiler, and the CUDA toolkit where the build uses one, for the line each program logs at start.
SET(JFJOCH_BUILD_COMPILER "${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
IF (JFJOCH_CUDA_AVAILABLE)
    SET(JFJOCH_BUILD_CUDA "${CMAKE_CUDA_COMPILER_VERSION}")
ELSE()
    SET(JFJOCH_BUILD_CUDA "")
ENDIF()
INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/GitInfoStamp.cmake")

set (THREADS_PREFER_PTHREAD_FLAG ON)
find_package (Threads REQUIRED)

MESSAGE(STATUS "Jungfraujoch git SHA1: ${GIT_SHA1}")
MESSAGE(STATUS "Jungfraujoch git date: ${GIT_DATE}")
MESSAGE(STATUS "Jungfraujoch version: ${JFJOCH_VERSION}")

# Re-stamped on every build, so RUGNUX_GIT in the rugnux report (and every other consumer of
# jfjoch_git_sha1) names the commit that was actually compiled.
ADD_CUSTOM_TARGET(JFJochGitInfo
        COMMAND "${CMAKE_COMMAND}"
            "-DGIT_EXECUTABLE=${GIT_EXECUTABLE}"
            "-DGITINFO_SOURCE_DIR=${CMAKE_SOURCE_DIR}"
            "-DGITINFO_TEMPLATE=${CMAKE_CURRENT_SOURCE_DIR}/GitInfo.cpp.in"
            "-DGITINFO_OUTPUT=${CMAKE_CURRENT_BINARY_DIR}/GitInfo.cpp"
            "-DJFJOCH_VERSION=${JFJOCH_VERSION}"
            "-DJFJOCH_BUILD_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
            "-DJFJOCH_BUILD_COMPILER=${JFJOCH_BUILD_COMPILER}"
            "-DJFJOCH_BUILD_CUDA=${JFJOCH_BUILD_CUDA}"
            -P "${CMAKE_CURRENT_SOURCE_DIR}/GitInfoStamp.cmake"
        BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/GitInfo.cpp"
        COMMENT "Stamping GitInfo.cpp from git HEAD"
        VERBATIM)

ADD_LIBRARY(JFJochVersion STATIC
        ${CMAKE_CURRENT_BINARY_DIR}/GitInfo.cpp GitInfo.h)
ADD_DEPENDENCIES(JFJochVersion JFJochGitInfo)
set_target_properties(JFJochVersion PROPERTIES
        POSITION_INDEPENDENT_CODE ON
)

ADD_LIBRARY(JFJochLogger STATIC
        Logger.cpp Logger.h
)

TARGET_LINK_LIBRARIES(JFJochLogger PUBLIC spdlog::spdlog JFJochVersion)
# NVTX v3 is header-only and architecture-neutral. CUDA::nvtx3 is no help here: it only points at
# CUDAToolkit_INCLUDE_DIRS, which in a cross build is the target tree (targets/sbsa-linux/include),
# and NVIDIA's cross-sbsa packages do not put nvtx3 there. So look in the target tree first and then
# in the toolkit's own include dir next to nvcc; where neither has it, the ranges compile out.
IF (JFJOCH_CUDA_AVAILABLE)
    FIND_PATH(JFJOCH_NVTX3_INCLUDE_DIR nvtx3/nvToolsExt.h
            HINTS ${CUDAToolkit_INCLUDE_DIRS} "${CUDAToolkit_BIN_DIR}/../include"
            NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
    IF (JFJOCH_NVTX3_INCLUDE_DIR)
        TARGET_INCLUDE_DIRECTORIES(JFJochLogger SYSTEM PRIVATE "${JFJOCH_NVTX3_INCLUDE_DIR}")
        TARGET_LINK_LIBRARIES(JFJochLogger PRIVATE ${CMAKE_DL_LIBS})   # NVTX loads its injection library with dlopen
        TARGET_COMPILE_DEFINITIONS(JFJochLogger PRIVATE JFJOCH_USE_NVTX)
    ELSE()
        MESSAGE(STATUS "NVTX3 headers not found - NVTX ranges compiled out")
    ENDIF()
ENDIF()

ADD_LIBRARY(JFJochZMQ STATIC ZMQWrappers.cpp ZMQWrappers.h)

ADD_LIBRARY(JFJochCommon STATIC
        Coord.cpp Coord.h
        DiffractionExperiment.cpp DiffractionExperiment.h
        RawToConvertedGeometry.h
        JFJochException.h
        Definitions.h
        ThreadSafeFIFO.h
        DiffractionSpot.cpp DiffractionSpot.h
        StatusVector.cpp StatusVector.h
        SpotToSave.h
        NetworkAddressConvert.h NetworkAddressConvert.cpp
        DetectorGeometry.h
        DetectorModuleGeometry.cpp DetectorModuleGeometry.h
        DetectorSetup.h DetectorSetup.cpp ZeroCopyReturnValue.h Histogram.h DiffractionGeometry.h
        CUDAWrapper.cpp CUDAWrapper.h
        CudaJitCache.cpp CudaJitCache.h
        HostMemory.cpp HostMemory.h
        ThreadAffinity.cpp ThreadAffinity.h
        ADUHistogram.cpp ADUHistogram.h
        RawToConvertedGeometryCore.h
        Plot.h
        ../fpga/pcie_driver/jfjoch_fpga.h
        DatasetSettings.cpp DatasetSettings.h
        ROIMap.cpp ROIMap.h
        ROIElement.cpp ROIElement.h
        ROICircle.cpp ROICircle.h
        ROIBox.cpp ROIBox.h
        ImageBuffer.cpp ImageBuffer.h
        time_utc.h
        PixelMask.cpp PixelMask.h
        InstrumentMetadata.cpp InstrumentMetadata.h
        ImageFormatSettings.cpp
        ImageFormatSettings.h
        DetectorSettings.cpp
        DetectorSettings.h
        AzimuthalIntegrationSettings.cpp
        AzimuthalIntegrationSettings.h
        AzimuthalIntegrationProfile.h
        AzimuthalIntegrationProfile.cpp
        AzimuthalIntegrationMapping.h
        AzimuthalIntegrationMapping.cpp
        CheckPath.h
        AutoIncrVector.h
        ModuleSummation.cpp
        ModuleSummation.h
        ROIDefinition.cpp
        ROIDefinition.h
        ZeroCopyReturnValue.cpp
        ColorScale.cpp ColorScale.h
        FileWriterSettings.cpp
        FileWriterSettings.h
        MovingAverage.cpp
        MovingAverage.h
        DiffractionGeometry.cpp
        ROIAzimuthal.cpp
        ROIAzimuthal.h
        print_license.h
        DetectorGeometryModular.cpp
        DetectorGeometryModular.h
        DetectorModules.cpp
        DetectorModules.h
        PanelRows.h
        PanelBoxes.cpp
        PanelBoxes.h
        AssembleToPlane.cpp
        AssembleToPlane.h
        ModuleShift.h
        DetectorGeometryFixed.cpp
        DetectorGeometryFixed.h
        GridScanSettings.cpp
        GridScanSettings.h
        JFJochMessages.h
        GoniometerAxis.cpp
        GoniometerAxis.h
        DetectorTransformation.cpp
        DetectorTransformation.h
        DetectorOrientation.cpp
        DetectorOrientation.h
        CompressedImage.cpp
        CompressedImage.h
        Reflection.h
        MultiLinePlot.cpp
        MultiLinePlot.h
        IndexingSettings.cpp
        IndexingSettings.h
        CrystalLattice.cpp
        CrystalLattice.h
        ScanResult.cpp
        ScanResult.h
        ScanResultGenerator.cpp
        ScanResultGenerator.h
        BraggIntegrationSettings.cpp
        BraggIntegrationSettings.h
        SpotToSave.cpp
        XrayFluorescenceSpectrum.cpp
        XrayFluorescenceSpectrum.h
        ResolutionShells.cpp
        ResolutionShells.h
        DarkMaskSettings.cpp
        DarkMaskSettings.h
        TopPixels.cpp
        TopPixels.h
        hkl_key.h
        JfjochTCP.h
        BrokerStatus.h
        ScalingSettings.cpp
        ScalingSettings.h
        UnitCell.cpp
        UnitCell.h
        MtzTable.h
        CorrelationCoefficient.cpp
        CorrelationCoefficient.h
        JFJochReceiverPlots.cpp
        JFJochReceiverPlots.h
)

# librt is Linux/glibc-only (older glibc keeps clock_gettime/timer_*/sem_* there, and some
# distros are picky about it for pthreads); it does not exist on macOS/Windows.
TARGET_LINK_LIBRARIES(JFJochCommon JFJochLogger Compression JFCalibration gemmi Threads::Threads
        $<$<PLATFORM_ID:Linux>:rt>)

TARGET_LINK_LIBRARIES(JFJochZMQ "$<BUILD_INTERFACE:libzmq-static>")

IF (JFJOCH_CUDA_AVAILABLE)
    TARGET_SOURCES(JFJochCommon PRIVATE CUDAWrapper.cu )
    TARGET_LINK_LIBRARIES(JFJochCommon CUDA::cudart_static
            ${CMAKE_DL_LIBS} $<$<PLATFORM_ID:Linux>:rt>)
ENDIF()
