cmake_minimum_required(VERSION 3.18)

project(otf2
    LANGUAGES C
    HOMEPAGE_URL https://score-p.org
)
set(otf2_VERSION 3.1.1)
set(otf2_MAJOR_VERSION 3)
set(otf2_SOVERSION 10)

include(GNUInstallDirs)

option(WITH_SIONLIB "Build with SIONlib; sionconfig must be in $PATH" ON)

add_library(otf2)
target_include_directories(otf2
PUBLIC
    "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/../include>"
    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
PRIVATE
    ${CMAKE_CURRENT_LIST_DIR}/../build-config/common
    ${CMAKE_CURRENT_LIST_DIR}
    ${CMAKE_CURRENT_LIST_DIR}/../src
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/include
    ${CMAKE_CURRENT_LIST_DIR}/../common/hash
)

target_compile_definitions(otf2 PRIVATE NOCROSS_BUILD BACKEND_BUILD NDEBUG OTF2_IGNORE_ATTRIBUTE_DEPRECATED)
if(WIN32)
    target_compile_definitions(otf2 PRIVATE WIN32 HAVE_IO_H=1)
endif()

set(otf2_PUBLIC_HEADERS
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_Archive.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_AttributeList.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_AttributeValue.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_Callbacks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/otf2_compiler.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_Definitions.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_DefReaderCallbacks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_DefReader.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_DefWriter.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_Events.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_EventSizeEstimator.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_EvtReaderCallbacks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_EvtReader.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_EvtWriter.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_GeneralDefinitions.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_GlobalDefReaderCallbacks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_GlobalDefReader.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_GlobalDefWriter.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_GlobalEvtReaderCallbacks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_GlobalEvtReader.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_GlobalSnapReaderCallbacks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_GlobalSnapReader.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/otf2.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_IdMap.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_Marker.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_MarkerReaderCallbacks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_MarkerReader.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_MarkerWriter.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_MPI_Collectives.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_OpenMP_Locks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_Pthread_Locks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_Reader.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_SnapReaderCallbacks.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_SnapReader.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_SnapWriter.h
    ${CMAKE_CURRENT_LIST_DIR}/../include/otf2/OTF2_Thumbnail.h
)

target_sources(otf2
    # Headers
PRIVATE
    "${otf2_PUBLIC_HEADERS}"
    ${CMAKE_CURRENT_LIST_DIR}/otf2/OTF2_ErrorCodes.h
    ${CMAKE_CURRENT_LIST_DIR}/config-backend.h
    ${CMAKE_CURRENT_LIST_DIR}/otf2_error_decls.gen.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/config-custom.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/config.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_AnchorFile.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_archive.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_archive_location.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_attic.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_attic_types.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_attribute_list.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_attribute_value.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_Buffer.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_collectives.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_collectives_serial.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_def_reader.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_def_writer.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_events_int.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_evt_reader.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_evt_writer.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_File.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_int.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_none.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_posix.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate_none.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate_posix.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_types.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_global_definitions.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_global_def_reader.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_global_def_writer.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_global_evt_reader.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_global_snap_reader.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_id_map.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_internal.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_local_definitions.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_lock.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_marker_int.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_reader.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_snaps.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_snap_reader.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_snap_writer.h
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_thumbnail.h
    ${CMAKE_CURRENT_LIST_DIR}/../build-config/common/config-common.h
    ${CMAKE_CURRENT_LIST_DIR}/../common/hash/jenkins_hash.h
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/src/exception/normalize_file.h
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/include/UTILS_CStr.h
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/include/UTILS_Debug.h
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/include/UTILS_Error.h
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/include/UTILS_IO.h
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/include/utils_package.h
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/include/UTILS_Portability.h
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/include/UTILS_DebugStream.hpp

    # Sources
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_AnchorFile.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_anchor_file_hostid.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_anchor_file_sysinfo.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_anchor_file_timestamp.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_Archive.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_archive_int.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_archive_location.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_attic.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_AttributeList.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_AttributeValue.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_Buffer.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_collectives.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_collectives_serial.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_DefReader.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_DefWriter.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_events.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_EventSizeEstimator.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_EvtReader.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_EvtWriter.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_File.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_none.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_posix.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate_none.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate_posix.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_GlobalDefReader.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_GlobalDefWriter.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_GlobalEvtReader.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_GlobalSnapReader.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_IdMap.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_id_map.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_lock.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_MarkerReader.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_MarkerWriter.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_Reader.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_SnapReader.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_SnapWriter.c
    ${CMAKE_CURRENT_LIST_DIR}/../src/OTF2_Thumbnail.c
    ${CMAKE_CURRENT_LIST_DIR}/../common/hash/jenkins_hash.c
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/src/cstr/UTILS_CStr.c
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/src/exception/UTILS_Error.c
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/src/io/UTILS_IO_GetExe.c
    ${CMAKE_CURRENT_LIST_DIR}/../common/utils/src/io/UTILS_IO_Tools.c
)

if(WITH_SIONLIB)
    execute_process(
        COMMAND sionconfig --gen --threadsafe --cflags
        RESULT_VARIABLE _SIONCONFIG_CFLAGS_FAIL
        OUTPUT_VARIABLE _SIONLIB_CFLAGS
    )
    execute_process(
        COMMAND sionconfig --gen --threadsafe --64 --libs
        RESULT_VARIABLE _SIONCONFIG_LIBS_FAIL
        OUTPUT_VARIABLE _SIONLIB_LDFLAGS
    )

    if(NOT _SIONCONFIG_CFLAGS_FAIL AND NOT _SIONCONFIG_LIBS_FAIL)

        target_compile_definitions(otf2 PRIVATE HAVE_SIONLIB_SUPPORT=1 HAVE_BACKEND_SIONLIB_SUPPORT=1)

        string(REPLACE "\n" "" _SIONLIB_CFLAGS ${_SIONLIB_CFLAGS})
        string(REPLACE " " ";" _SIONLIB_CFLAGS ${_SIONLIB_CFLAGS})
        foreach(_ARG ${_SIONLIB_CFLAGS})
            if(${_ARG} MATCHES "^-I")
                string(REGEX REPLACE "^-I" "" _ARG ${_ARG})
                string(STRIP "${_ARG}" _ARG)
                target_include_directories(otf2 PRIVATE ${_ARG})
            elseif(${_ARG} MATCHES "^-D")
                string(REGEX REPLACE "^-D" "" _ARG ${_ARG})
                string(STRIP "${_ARG}" _ARG)
                target_compile_definitions(otf2 PRIVATE ${_ARG})
            endif()
        endforeach()

        string(REPLACE "\n" "" _SIONLIB_LDFLAGS ${_SIONLIB_LDFLAGS})
        string(REPLACE " " ";" _SIONLIB_LDFLAGS ${_SIONLIB_LDFLAGS})
        foreach(_ARG ${_SIONLIB_LDFLAGS})
            if(${_ARG} MATCHES "^-L")
                string(REGEX REPLACE "^-L" "" _ARG ${_ARG})
                string(STRIP "${_ARG}" _ARG)
                set(_SIONLIB_LINK_DIRS ${_SIONLIB_LINK_DIRS} ${_ARG})
            elseif(${_ARG} MATCHES "^-l")
                string(REGEX REPLACE "^-l" "" _ARG ${_ARG})
                string(STRIP "${_ARG}" _ARG)
                find_library(_SIONLIB_LIB_FROM_ARG NAMES ${_ARG} HINTS ${_SIONLIB_LINK_DIRS} NO_DEFAULT_PATH)
                if(_SIONLIB_LIB_FROM_ARG)
                    set(SIONLIB_LIBRARIES ${SIONLIB_LIBRARIES} ${_SIONLIB_LIB_FROM_ARG})
                endif()
                unset(_SIONLIB_LIB_FROM_ARG CACHE)
            endif()
        endforeach()

        target_link_libraries(otf2 INTERFACE ${SIONLIB_LIBRARIES})
        target_sources(otf2
        PRIVATE
            ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate_sion.c
            ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate_sion.h
            ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate_sion_int.h
            ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate_sion_collectives.c
            ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_substrate_sion_rank_map.c
            ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_sion.c
            ${CMAKE_CURRENT_LIST_DIR}/../src/otf2_file_sion.h
        )
        set_target_properties(otf2 PROPERTIES FEATURE_SIONLIB_SUPPORT TRUE)
    else()
        target_compile_definitions(otf2 PRIVATE HAVE_SIONLIB_SUPPORT=0 HAVE_BACKEND_SIONLIB_SUPPORT=0)
        set_target_properties(otf2 PROPERTIES FEATURE_SIONLIB_SUPPORT FALSE)
    endif()
else()
    target_compile_definitions(otf2 PRIVATE HAVE_SIONLIB_SUPPORT=0 HAVE_BACKEND_SIONLIB_SUPPORT=0)
    set_target_properties(otf2 PROPERTIES FEATURE_SIONLIB_SUPPORT FALSE)
endif()
set_target_properties(otf2 PROPERTIES EXPORT_PROPERTIES "FEATURE_SIONLIB_SUPPORT")

set(otf2_PUBLIC_HEADERS ${otf2_PUBLIC_HEADERS} ${CMAKE_CURRENT_LIST_DIR}/otf2/OTF2_ErrorCodes.h)
install(FILES ${otf2_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/otf2)

install(TARGETS otf2
    EXPORT otf2-targets
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(EXPORT otf2-targets
    FILE otf2-targets.cmake
    NAMESPACE otf2::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/otf2
)

include(CMakePackageConfigHelpers)
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/config.cmake.in
    "${CMAKE_CURRENT_BINARY_DIR}/otf2-config.cmake"
    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/otf2
)

set_property(TARGET otf2 PROPERTY VERSION ${otf2_VERSION})
set_property(TARGET otf2 PROPERTY SOVERSION ${otf2_SOVERSION})
set_property(TARGET otf2 PROPERTY INTERFACE_otf2_MAJOR_VERSION ${otf2_MAJOR_VERSION})
set_property(TARGET otf2 APPEND PROPERTY COMPATIBLE_INTERFACE_STRING otf2_MAJOR_VERSION)

# generate the version file for the config file
write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/otf2-config-version.cmake"
    VERSION "${otf2_VERSION}"
    COMPATIBILITY SameMajorVersion
)

install(FILES
    "${CMAKE_CURRENT_BINARY_DIR}/otf2-config.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/otf2-config-version.cmake"
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/otf2
)
