# CMakeLists.txt

# Ensure to pick up the default triplet from the environment if any. This helps driving the vcpkg triplet in the same
# way either when starting vcpkg directly, or when letting CMake start vcpkg at configure/generate time. Note: this
# logic must happen before PROJECT command.
if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
  set(VCPKG_TARGET_TRIPLET
      "$ENV{VCPKG_DEFAULT_TRIPLET}"
      CACHE STRING "The vcpkg triplet")
endif()

cmake_minimum_required(VERSION 3.21)

# Enforce c++14 standard.
set(CMAKE_CXX_STANDARD 14)

# Get project version from the header file
file(READ "src/khiops_driver_azure/version.hpp" H_FILE)
string(REGEX MATCH "#define DRIVER_VERSION \"([^\"]+)\"" _ ${H_FILE})
set(DRIVER_VERSION ${CMAKE_MATCH_1})
string(REGEX REPLACE "-.*" "" VERSION ${DRIVER_VERSION})
message(STATUS "Building Khiops driver version: ${DRIVER_VERSION} (CMake version : ${VERSION})")

project(
  khiops-azure
  LANGUAGES CXX
  VERSION ${DRIVER_VERSION})

# CMake policy for MSVC runtime selection
if(POLICY CMP0091)
  cmake_policy(SET CMP0091 NEW)
endif()

# Automatic choice of MSVC runtime to match VCPKG triplet.
if(MSVC)
  if(DEFINED VCPKG_TARGET_TRIPLET)
    string(TOLOWER "${VCPKG_TARGET_TRIPLET}" _vcpkg_triplet_lc)
    # vcpkg convention:
    # - triplets *-static      => static CRT (/MT, /MTd)
    # - triplets sans -static  => dynamic CRT (/MD, /MDd)
    if(_vcpkg_triplet_lc MATCHES "-static$")
      set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
      message(STATUS "MSVC runtime: /MT (derived from VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET})")
    else()
      set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
      message(STATUS "MSVC runtime: /MD (derived from VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET})")
    endif()
  else()
    message(WARNING
      "VCPKG_TARGET_TRIPLET undefined; runtime MSVC not forced. "
      "To avoid LNK2038 conflicts, pass -DVCPKG_TARGET_TRIPLET=..."
    )
  endif()
endif()

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules/)

# Exclude googletest from the installation and packages
set(INSTALL_GTEST OFF)
set(INSTALL_GMOCK OFF)

if(BUILD_TESTS)
  include(GoogleTest)
  enable_testing()
endif()

# Find dependencies
find_package(azure-core-cpp CONFIG REQUIRED)
find_package(azure-identity-cpp CONFIG REQUIRED)
find_package(azure-storage-blobs-cpp CONFIG REQUIRED)
find_package(azure-storage-files-shares-cpp CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
if(BUILD_TESTS)
  find_package(fmt CONFIG REQUIRED)
  find_package(Boost REQUIRED)
endif()

# Hide symbols in the shared libraries
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)

# Set the location of the built artifacts:
#
# - Shared and static library target directory: lib
# - Executable target directory: bin
# - We must use these weird generator expressions to avoid the Debug and Release directories in VS
# - More info: https://stackoverflow.com/q/47175912
#
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY $<1:${CMAKE_BINARY_DIR}/lib/>)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY $<1:${CMAKE_BINARY_DIR}/lib/>)
if(WIN32)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
  message(STATUS "Executables will be stored in ${CMAKE_BINARY_DIR}/bin/")
else()
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
  message(STATUS "Executables will be stored in ${CMAKE_BINARY_DIR}/lib/")
endif()
message(STATUS "Libraries will be stored in ${CMAKE_BINARY_DIR}/lib/")

# Avoid generating shared libs with version number in the filename
set(CMAKE_PLATFORM_NO_VERSIONED_SONAME 1)

if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_BUILD_TYPE STREQUAL "Release")
  message("Build system == Linux and build type != Release  ==>  build with sanitizer tools")
  add_compile_options(-fsanitize=undefined -fsanitize=address -fno-sanitize-recover=all)
  add_link_options(-fsanitize=undefined -fsanitize=address -fno-sanitize-recover=all)
  if(BUILD_TESTS)
    include(CodeCoverage)
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_COVERAGE} ${CMAKE_CXX_FLAGS_DEBUG}")
    setup_target_for_coverage(${PROJECT_NAME}_coverage basic_test coverage)
    setup_target_for_coverage_cobertura(${PROJECT_NAME}_cobertura basic_test coverage
                                        --gtest_output=xml:coverage.junit.xml)
  endif()
endif()

set(KhiopsDriverAzureSources
  auth.hpp
  blobpathresolve.hpp
  blobpathresolve.cpp
  connstr.hpp
  connstr.cpp
  core.hpp
  core.cpp
  driver.cpp
  filestream.hpp
  filestream.cpp
  globalstate.hpp
  sharepathresolve.hpp
  sharepathresolve.cpp
  specific_impl.cpp
  util.hpp
  util.cpp
  version.hpp
)
list(TRANSFORM KhiopsDriverAzureSources PREPEND src/khiops_driver_azure/)

include("${CMAKE_CURRENT_SOURCE_DIR}/shared/import_khiops_driver_common.cmake")
list(TRANSFORM KhiopsDriverCommonSources PREPEND shared/)

add_library(khiopsdriver_file_azure SHARED ${KhiopsDriverAzureSources} ${KhiopsDriverCommonSources})
target_include_directories(khiopsdriver_file_azure PRIVATE src shared/src)
target_link_options(khiopsdriver_file_azure PRIVATE $<$<CONFIG:RELEASE>:-s>) # stripping
set_target_properties(khiopsdriver_file_azure PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} VERSION ${PROJECT_VERSION})
if(WIN32)
  set_target_properties(khiopsdriver_file_azure PROPERTIES RUNTIME_OUTPUT_NAME "libkhiopsdriver_file_azure"
                                                           ARCHIVE_OUTPUT_NAME "libkhiopsdriver_file_azure")
endif()
if(WIN32)
  target_link_libraries(khiopsdriver_file_azure PRIVATE Azure::azure-core Azure::azure-identity Azure::azure-storage-blobs
                                                        Azure::azure-storage-files-shares spdlog::spdlog bcrypt)
else()
  target_link_libraries(khiopsdriver_file_azure PRIVATE Azure::azure-core Azure::azure-identity Azure::azure-storage-blobs
                                                        Azure::azure-storage-files-shares spdlog::spdlog)
endif()
target_compile_options(
  khiopsdriver_file_azure
  PRIVATE $<$<CXX_COMPILER_ID:MSVC>:-Wall;/wd4582;/wd4583;/wd4625;/wd4626;/wd4710;/wd4711;/wd4820;/wd4868;/permissive->
  PRIVATE $<$<CXX_COMPILER_ID:AppleClang,Clang,GNU>:-Wall;-Wextra;-pedantic>)

option(BUILD_TESTS "Build test programs" OFF)
if(BUILD_TESTS)
  add_library(khiopsdriver_file_azure_testing STATIC ${KhiopsDriverAzureSources} ${KhiopsDriverCommonSources})

  target_include_directories(khiopsdriver_file_azure_testing PRIVATE src shared/src)
  target_link_options(khiopsdriver_file_azure_testing PRIVATE $<$<CONFIG:RELEASE>:-s>) # stripping
  if(WIN32)
    target_link_libraries(
      khiopsdriver_file_azure_testing PRIVATE Azure::azure-identity Azure::azure-storage-blobs
                                              Azure::azure-storage-files-shares spdlog::spdlog bcrypt)
  else()
    target_link_libraries(khiopsdriver_file_azure_testing PRIVATE Azure::azure-identity Azure::azure-storage-blobs
                                                                  Azure::azure-storage-files-shares spdlog::spdlog)
  endif()
  target_compile_options(
    khiopsdriver_file_azure_testing
    PRIVATE
      $<$<CXX_COMPILER_ID:MSVC>:-Wall;/wd4582;/wd4583;/wd4625;/wd4626;/wd4710;/wd4711;/wd4820;/wd4868;/permissive->
    PRIVATE $<$<CXX_COMPILER_ID:AppleClang,Clang,GNU>:-Wall;-Wextra;-pedantic>)

  add_subdirectory(test)
  set(storage_driver_target_name khiopsdriver_file_azure)
  add_subdirectory("shared/integrationtests")
endif(BUILD_TESTS)

if (DEFINED SKBUILD)
  # These paths are needed so that Khiops finds the driver.
  install(
    TARGETS khiopsdriver_file_azure
    LIBRARY DESTINATION ${SKBUILD_DATA_DIR}/lib
    ARCHIVE DESTINATION ${SKBUILD_DATA_DIR}/lib # lib on windows
    RUNTIME DESTINATION ${SKBUILD_SCRIPTS_DIR} # dll on windows
  )
else()
  install(
    TARGETS khiopsdriver_file_azure
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib # lib on windows
    RUNTIME DESTINATION bin # dll on windows
  )
endif()

set(CPACK_PACKAGE_VENDOR Orange)
set(CPACK_PACKAGE_HOMEPAGE_URL https://khiops.org)
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VENDOR "Orange")
set(CPACK_PACKAGE_CONTACT "Khiops Team <khiops.team@orange.com>")
set(CPACK_SOURCE_IGNORE_FILES .git)
set(CPACK_PACKAGE_DESCRIPTION "This driver allows Khiops to access the Azure Cloud storage.")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Azure driver for the Khiops tool")
set(CPACK_PACKAGE_NAME "khiops-driver-azure")

set(CPACK_VERBATIM_VARIABLES YES)
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_BINARY_DIR}/packages")
# set(CPACK_PACKAGING_INSTALL_PREFIX "/usr/")

# ########### ARCHIVE Generator #############################

# One package per component
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)

# user friendly archive names
set(CPACK_ARCHIVE_FILE_NAME khiops-driver-azure-${PROJECT_VERSION})

# ########### DEB Generator #############################

# Package release ("This is the numbering of the DEB package itself, i.e. the version of the packaging and not the
# version of the content")
set(CPACK_DEBIAN_PACKAGE_RELEASE 1)

# package name for deb.
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)

# Packages version: the full KHIOPS_VERSION (N.N.N_aN) instead of the PROJECT_VERSION (N.N.N)
# set(CPACK_DEBIAN_PACKAGE_VERSION ${KHIOPS_VERSION})

set(CPACK_DEB_COMPONENT_INSTALL YES)
set(CPACK_DEBIAN_PACKAGE_SECTION "math")

# runtime path setting
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON)
# binaries in deb building will search shared library in the build tree. We should use directly
# CMAKE_LIBRARY_OUTPUT_DIRECTORY but it produces a bug in dpkg-shlibdeps
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS ${CMAKE_BINARY_DIR}/lib/)

# packages recommends
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "khiops")

# packages posinst and triggers set(CPACK_DEBIAN_KNI_PACKAGE_CONTROL_EXTRA
# ${PROJECT_SOURCE_DIR}/packaging/linux/debian/kni/triggers")

# set(CPACK_DEBIAN_PACKAGE_DEBUG ON)
set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)

# ########### RPM Generator #############################

set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_RPM_PACKAGE_LICENSE BSD-3-Clause)
set(CPACK_RPM_PACKAGE_GROUP "Applications/Engineering")
set(CPACK_RPM_PACKAGE_VENDOR Orange)

set(CPACK_RPM_KHIOPS_PACKAGE_AUTOREQ ON)

# Packages version set(CPACK_RPM_PACKAGE_VERSION ${PROJECT_VERSION})

# packages names set(CPACK_RPM_PACKAGE_NAME khiops)

# default file name e.g. khiops-10.0.0-1.x86_64.rpm
set(CPACK_RPM_FILE_NAME RPM-DEFAULT)

# packages summary set(CPACK_RPM_PACKAGE_SUMMARY "Khiops tools")

# packages post/postun install scripts set(CPACK_RPM_KNI_POST_INSTALL_SCRIPT_FILE
# "${PROJECT_SOURCE_DIR}/packaging/linux/redhat/kni.post") set(CPACK_RPM_KNI_POSTUN_INSTALL_SCRIPT_FILE
# "${PROJECT_SOURCE_DIR}/packaging/linux/redhat/kni.postun")

include(CPack)
