##*************************************************************************##
##  CUBE        http://www.scalasca.org/                                   ##
##*************************************************************************##
##  Copyright (c) 2023-2025                                                ##
##  Forschungszentrum Juelich GmbH, Juelich Supercomputing Centre          ##
##                                                                         ##
##  This software may be modified and distributed under the terms of       ##
##  a BSD-style license.  See the COPYING file in the package base         ##
##  directory for details.                                                 ##
##*************************************************************************##


cmake_minimum_required(VERSION 3.16)
include(CheckIncludeFile)
#####################################################################################
# get version info from build-config/VERSION or git
#####################################################################################
include(./cmake-modules/CubeLibVersion.cmake)
message(STATUS "CubeLib version: ${CUBELIB_VERSION} revision ${CUBELIB_REVISION} ${CUBELIB_FULL_NAME}" )

#####################################################################################
# project settings
#####################################################################################
project(CubeLib VERSION ${CUBELIB_VERSION_MAJOR}.${CUBELIB_VERSION_MINOR}.${CUBELIB_VERSION_PATCH} LANGUAGES C CXX)

include(GNUInstallDirs)
set(CMAKE_CXX_STANDARD 11)

# release build type is about 8 times faster than debug build type -> set as default for every cmake run
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
if(NOT CMAKE_BUILD_TYPE)
     set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
endif()
set(CMAKE_CXX_FLAGS_RELEASE "-O2")

if (WIN32)
  add_definitions( -D__MINGW32__ )
endif()

# find pthreads
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

# Check if dlopen exists
if (NOT WIN32)
    include(CheckSymbolExists)
    check_symbol_exists(dlopen "dlfcn.h" HAVE_DLOPEN)
else()
     message(STATUS "Looking for dlopen: checking if dlfcn-win32 is available")
     find_package(dlfcn-win32)
     if (dlfcn-win32_FOUND)
         set(HAVE_DLOPEN 1 CACHE INTERNAL "Have symbol dlopen")
     else()
         set(HAVE_DLOPEN 0 CACHE INTERNAL "Have symbol dlopen")
     endif()
endif()

if (NOT ${HAVE_DLOPEN})
     message("dlopen is not available, plugins are disabled")
endif()

#####################################################################################
# set options for emscription builds
#####################################################################################

if(EMSCRIPTEN)
   SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
   add_compile_options(-fexceptions -sDISABLE_EXCEPTION_CATCHING=0)  # allow exceptions
   add_compile_options(-pthread)
endif()

#####################################################################################
# generate header files with version info
#####################################################################################
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/cmake-include/cubelib-version.h.in ${CMAKE_BINARY_DIR}/src/cubelib-version.h @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/cmake-include/cubelib-config.h.in ${CMAKE_BINARY_DIR}/src/cubelib-config.h @ONLY)
file(CREATE_LINK ${CMAKE_BINARY_DIR}/src/cubelib-config.h ${CMAKE_BINARY_DIR}/src/config.h COPY_ON_ERROR SYMBOLIC)

#################################################################################
# build subdirectories
##################################################################################

# parts of the cubelib library
add_subdirectory(common/utils)
add_subdirectory(src)
add_subdirectory(src/tools/tools/0001.library)
add_subdirectory(src/tools/tools/0001.library/popx)

# external libraries
add_subdirectory(vendor/json-cpp)

if(NOT EMSCRIPTEN)
  # additional binaries
  add_subdirectory(src/tools/tools)
endif()

# todo: generate documentation
# PKGDATADIR which contains summary file (todo)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/share/cubelib)

#################################################################################
# cubelib
##################################################################################

list(APPEND CUBELIB_HEADERS_PUBLIC ${CMAKE_BINARY_DIR}/src/cubelib-version.h) # add generated file

# build shared cubelib library from object libraries in subdirectories
add_library(CubeLib SHARED)
target_link_libraries( CubeLib PRIVATE
    libcube_library_tools
    cube_popx_library
    cube-base
    utils
    Threads::Threads
    $<$<BOOL:${dlfcn-win32_FOUND}>:dlfcn-win32::dl> # optional package provides dlopen on windows: dlfcn-win32::dl
)

# set library version
# SOVERSION = the oldest interface that the library is compatible with.
math(EXPR SOVERSION "${CUBELIB_LIBRARY_CURRENT} - ${CUBELIB_LIBRARY_AGE}")
set_target_properties(CubeLib
    PROPERTIES
    OUTPUT_NAME cube4
    SOVERSION ${SOVERSION}
    VERSION ${SOVERSION}.${CUBELIB_LIBRARY_AGE}.${CUBELIB_LIBRARY_REVISION}
)

# include directory, which is used by external projects
target_include_directories(CubeLib
                           INTERFACE
                            $<INSTALL_INTERFACE:include/cubelib> # cubelib headers are installed into subdirectory cubelib
                           )

##################################################################################
# install cubelib
##################################################################################

install(TARGETS CubeLib
    EXPORT CubeLibTargets # target CubeLibTargets will be used for export configuration
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(FILES
    ${CUBELIB_HEADERS_PUBLIC}
    DESTINATION include/cubelib
)

##################################################################################
# create cubelib export configuration (required for other packages to find cubelib)
##################################################################################

include(CMakePackageConfigHelpers)

# install the configuration targets for find_package()
install(EXPORT CubeLibTargets
  FILE CubeLibTargets.cmake
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CubeLib
)
# provide version information for find_package()
write_basic_package_version_file(
  "${CMAKE_CURRENT_BINARY_DIR}/CubeLibConfigVersion.cmake"
  VERSION ${CUBELIB_VERSION_MAJOR}.${CUBELIB_VERSION_MINOR}.${CUBELIB_VERSION_PATCH}
  COMPATIBILITY AnyNewerVersion
)
# create the configuration file for find_package()
configure_package_config_file(
  "${CMAKE_CURRENT_SOURCE_DIR}/src/cmake-include/CubeLibConfig.cmake.in"
  "${CMAKE_CURRENT_BINARY_DIR}/CubeLibConfig.cmake"
  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CubeLib
)
install( FILES
    "${CMAKE_CURRENT_BINARY_DIR}/CubeLibConfig.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/CubeLibConfigVersion.cmake"
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CubeLib
)
install( DIRECTORY share DESTINATION ${CMAKE_INSTALL_PREFIX})

export( EXPORT CubeLibTargets
  FILE "${CMAKE_BINARY_DIR}/CubeLibTargets.cmake"
)
