# SPDX-FileCopyrightText: 2024 Hiredict Contributors
# SPDX-FileCopyrightText: 2024 Salvatore Sanfilippo <antirez at gmail dot com>
#
# SPDX-License-Identifier: BSD-3-Clause
# SPDX-License-Identifier: LGPL-3.0-or-later

CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0)

MACRO(getVersionBit name)
  SET(VERSION_REGEX "^#define ${name} (.+)$")
  FILE(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/hiredict.h"
    VERSION_BIT REGEX ${VERSION_REGEX})
  STRING(REGEX REPLACE ${VERSION_REGEX} "\\1" ${name} "${VERSION_BIT}")
ENDMACRO(getVersionBit)

getVersionBit(HIREDICT_MAJOR)
getVersionBit(HIREDICT_MINOR)
getVersionBit(HIREDICT_PATCH)
getVersionBit(HIREDICT_SONAME)
SET(VERSION "${HIREDICT_MAJOR}.${HIREDICT_MINOR}.${HIREDICT_PATCH}")
MESSAGE("Detected version: ${VERSION}")

PROJECT(hiredict LANGUAGES "C" VERSION "${VERSION}")
INCLUDE(GNUInstallDirs)

OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON)
OPTION(ENABLE_SSL "Build hiredict_ssl for SSL support" OFF)
OPTION(DISABLE_TESTS "If tests should be compiled or not" OFF)
OPTION(ENABLE_SSL_TESTS "Should we test SSL connections" OFF)
OPTION(ENABLE_EXAMPLES "Enable building hiredict examples" OFF)
OPTION(ENABLE_ASYNC_TESTS "Should we run all asynchronous API tests" OFF)
# Historically, the NuGet file was always install; default
# to ON for those who rely on that historical behaviour.
OPTION(ENABLE_NUGET "Install NuGET packaging details" ON)

# Hiredict requires C99
SET(CMAKE_C_STANDARD 99)
SET(CMAKE_DEBUG_POSTFIX d)

SET(hiredict_sources
    alloc.c
    async.c
    hiredict.c
    net.c
    read.c
    sds.c
    sockcompat.c)

SET(hiredict_sources ${hiredict_sources})

IF(WIN32)
    ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -DWIN32_LEAN_AND_MEAN)
ENDIF()

ADD_LIBRARY(hiredict ${hiredict_sources})
ADD_LIBRARY(hiredict::hiredict ALIAS hiredict)
set(hiredict_export_name hiredict CACHE STRING "Name of the exported target")
set(PREFIX "${CMAKE_INSTALL_PREFIX}")
set(LIBDIR "${CMAKE_INSTALL_LIBDIR}")
set_target_properties(hiredict PROPERTIES EXPORT_NAME ${hiredict_export_name})

SET_TARGET_PROPERTIES(hiredict
    PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE
	VERSION "${HIREDICT_SONAME}")
IF(MSVC)
	SET_TARGET_PROPERTIES(hiredict
        PROPERTIES COMPILE_FLAGS /Z7)
ENDIF()
IF(WIN32)
    TARGET_LINK_LIBRARIES(hiredict PUBLIC ws2_32 crypt32)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
    TARGET_LINK_LIBRARIES(hiredict PUBLIC m)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
    TARGET_LINK_LIBRARIES(hiredict PUBLIC socket)
ENDIF()

TARGET_INCLUDE_DIRECTORIES(hiredict PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)

CONFIGURE_FILE(hiredict.pc.in hiredict.pc @ONLY)
CONFIGURE_FILE(shim/hiredis.pc.in hiredis.pc @ONLY)

set(CPACK_PACKAGE_VENDOR "Redict")
set(CPACK_PACKAGE_DESCRIPTION "\
Hiredict is a minimalistic C client library for the Redict database.

It is minimalistic because it just adds minimal support for the protocol, \
but at the same time it uses a high level printf-alike API in order to make \
it much higher level than otherwise suggested by its minimal code base and the \
lack of explicit bindings for every Redict command.

Apart from supporting sending commands and receiving replies, it comes with a \
reply parser that is decoupled from the I/O layer. It is a stream parser designed \
for easy reusability, which can for instance be used in higher level language bindings \
for efficient reply parsing.

Hiredict only supports the binary-safe Redis protocol.

The library comes with multiple APIs. There is the synchronous API, the asynchronous API \
and the reply parsing API.")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://codeberg.org/redict/hiredict")
set(CPACK_PACKAGE_CONTACT "navi@vlhl.dev")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_RPM_PACKAGE_AUTOREQPROV ON)

include(CPack)

INSTALL(TARGETS hiredict
    EXPORT hiredict-targets
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

if (MSVC AND BUILD_SHARED_LIBS)
    INSTALL(FILES $<TARGET_PDB_FILE:hiredict>
        DESTINATION ${CMAKE_INSTALL_BINDIR}
        CONFIGURATIONS Debug RelWithDebInfo)
endif()

if (ENABLE_NUGET)
    # For NuGet packages
    INSTALL(FILES hiredict.targets
        DESTINATION build/native)
endif()

INSTALL(FILES hiredict.h read.h sds.h async.h alloc.h sockcompat.h
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredict)

INSTALL(FILES shim/hiredis.h shim/read.h shim/sds.h
	shim/async.h shim/alloc.h shim/sockcompat.h
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis)

INSTALL(DIRECTORY adapters
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredict)

INSTALL(DIRECTORY shim/adapters
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis)

INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredict.pc
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredis.pc
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

export(EXPORT hiredict-targets
    FILE "${CMAKE_CURRENT_BINARY_DIR}/hiredict-targets.cmake"
    NAMESPACE hiredict::)

if(WIN32)
    SET(CMAKE_CONF_INSTALL_DIR share/hiredict)
else()
    SET(CMAKE_CONF_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/hiredict)
endif()
SET(INCLUDE_INSTALL_DIR include)
include(CMakePackageConfigHelpers)
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/hiredict-config-version.cmake"
                                 COMPATIBILITY SameMajorVersion)
configure_package_config_file(hiredict-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/hiredict-config.cmake
                              INSTALL_DESTINATION ${CMAKE_CONF_INSTALL_DIR}
                              PATH_VARS INCLUDE_INSTALL_DIR)

INSTALL(EXPORT hiredict-targets
        FILE hiredict-targets.cmake
        NAMESPACE hiredict::
        DESTINATION ${CMAKE_CONF_INSTALL_DIR})

INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredict-config.cmake
              ${CMAKE_CURRENT_BINARY_DIR}/hiredict-config-version.cmake
        DESTINATION ${CMAKE_CONF_INSTALL_DIR})


IF(ENABLE_SSL)
    IF (NOT OPENSSL_ROOT_DIR)
        IF (APPLE)
            SET(OPENSSL_ROOT_DIR "/usr/local/opt/openssl")
        ENDIF()
    ENDIF()
    FIND_PACKAGE(OpenSSL REQUIRED)
    SET(hiredict_ssl_sources
        ssl.c)
    ADD_LIBRARY(hiredict_ssl ${hiredict_ssl_sources})
    ADD_LIBRARY(hiredict::hiredict_ssl ALIAS hiredict_ssl)

    IF (APPLE AND BUILD_SHARED_LIBS)
        SET_PROPERTY(TARGET hiredict_ssl PROPERTY LINK_FLAGS "-Wl,-undefined -Wl,dynamic_lookup")
    ENDIF()

    SET_TARGET_PROPERTIES(hiredict_ssl
        PROPERTIES
        WINDOWS_EXPORT_ALL_SYMBOLS TRUE
		VERSION "${HIREDICT_SONAME}")
    IF(MSVC)
        SET_TARGET_PROPERTIES(hiredict_ssl
            PROPERTIES COMPILE_FLAGS /Z7)
    ENDIF()
    TARGET_LINK_LIBRARIES(hiredict_ssl PRIVATE OpenSSL::SSL)
    IF(WIN32)
        TARGET_LINK_LIBRARIES(hiredict_ssl PRIVATE hiredict)
    ENDIF()
    CONFIGURE_FILE(hiredict_ssl.pc.in hiredict_ssl.pc @ONLY)
    CONFIGURE_FILE(shim/hiredis_ssl.pc.in hiredis_ssl.pc @ONLY)

    INSTALL(TARGETS hiredict_ssl
        EXPORT hiredict_ssl-targets
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

    if (MSVC AND BUILD_SHARED_LIBS)
        INSTALL(FILES $<TARGET_PDB_FILE:hiredict_ssl>
            DESTINATION ${CMAKE_INSTALL_BINDIR}
            CONFIGURATIONS Debug RelWithDebInfo)
    endif()

    INSTALL(FILES hiredict_ssl.h
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredict)

    INSTALL(FILES shim/hiredis_ssl.h
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis)

    INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredict_ssl.pc
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

    INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredis_ssl.pc
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

    export(EXPORT hiredict_ssl-targets
           FILE "${CMAKE_CURRENT_BINARY_DIR}/hiredict_ssl-targets.cmake"
           NAMESPACE hiredict::)

    if(WIN32)
        SET(CMAKE_CONF_INSTALL_DIR share/hiredict_ssl)
    else()
        SET(CMAKE_CONF_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/hiredict_ssl)
    endif()
    configure_package_config_file(hiredict_ssl-config.cmake.in
                                  ${CMAKE_CURRENT_BINARY_DIR}/hiredict_ssl-config.cmake
                                  INSTALL_DESTINATION ${CMAKE_CONF_INSTALL_DIR}
                                  PATH_VARS INCLUDE_INSTALL_DIR)

    INSTALL(EXPORT hiredict_ssl-targets
        FILE hiredict_ssl-targets.cmake
        NAMESPACE hiredict::
        DESTINATION ${CMAKE_CONF_INSTALL_DIR})

    INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/hiredict_ssl-config.cmake
        DESTINATION ${CMAKE_CONF_INSTALL_DIR})
ENDIF()

IF(NOT DISABLE_TESTS)
    ENABLE_TESTING()
    ADD_EXECUTABLE(hiredict-test test.c)
    TARGET_LINK_LIBRARIES(hiredict-test hiredict)
    IF(ENABLE_SSL_TESTS)
		ADD_DEFINITIONS(-DHIREDICT_TEST_SSL=1)
        TARGET_LINK_LIBRARIES(hiredict-test hiredict_ssl)
    ENDIF()
    IF(ENABLE_ASYNC_TESTS)
		ADD_DEFINITIONS(-DHIREDICT_TEST_ASYNC=1)
        TARGET_LINK_LIBRARIES(hiredict-test event)
    ENDIF()
    ADD_TEST(NAME hiredict-test
        COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test.sh)
ENDIF()

# Add examples
IF(ENABLE_EXAMPLES)
    ADD_SUBDIRECTORY(examples)
ENDIF(ENABLE_EXAMPLES)
