#
# Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#

cmake_minimum_required(VERSION 3.8...3.22)

# Boost version
if (DEFINED BOOST_SUPERPROJECT_VERSION)
    set(BOOST_MYSQL_VERSION ${BOOST_SUPERPROJECT_VERSION})
else()
    set(BOOST_MYSQL_VERSION 1.80.0)
endif()

# Project
project(boost_mysql VERSION ${BOOST_MYSQL_VERSION} LANGUAGES CXX)

# Determine if we're the top-level project 
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
    set(_IS_ROOT ON)
else()
    set(_IS_ROOT OFF)
endif()

# Determine what to do with Boost dependencies.
# We've got the following use cases:
#  1. We're building the superproject, and it has called add_subdirectory() on us. BOOST_SUPERPROJECT_VERSION defined.
#  2. Someone's calling add_subdirectory() on us and doesn't want us to find_package Boost, e.g. the cmake subdir test.
#  3. We're the main project and we want to use an installed version of Boost (e.g. normal development)
set(BOOST_MYSQL_USE_FIND_PACKAGE ${_IS_ROOT})

# If we are the top-level project, enable testing
if(_IS_ROOT)
    include(CTest)

    # Don't run integration testing unless explicitly requested
    option(BOOST_MYSQL_INTEGRATION_TESTS OFF "Whether to build and run integration tests or not")
    mark_as_advanced(BOOST_MYSQL_INTEGRATION_TESTS)

    # Valgrind tests and Valgrind-friendly code (e.g. mark SSL buffers as initialized)
    option(BOOST_MYSQL_VALGRIND_TESTS OFF "Whether to run Valgrind tests or not (requires Valgrind)")
    mark_as_advanced(BOOST_MYSQL_VALGRIND_TESTS)
    
    # Build with coverage
    option(BOOST_MYSQL_COVERAGE OFF "Whether to build using coverage")
    mark_as_advanced(BOOST_MYSQL_COVERAGE)
endif()

# Includes
include(GNUInstallDirs)

# Dependencies
if (BOOST_MYSQL_USE_FIND_PACKAGE)
    find_package(Boost ${BOOST_MYSQL_VERSION} REQUIRED COMPONENTS headers system)
    set(_BOOST_LINK_LIBRARIES Boost::headers Boost::system)
else()
    # Generated by boostdep. These should be already available (e.g. by calling add_subdirectory())
    set(_BOOST_LINK_LIBRARIES
        Boost::asio
        Boost::assert
        Boost::config
        Boost::core
        Boost::endian
        Boost::lexical_cast
        Boost::mp11
        Boost::system
        Boost::throw_exception
        Boost::variant2
    )
endif()

if(_IS_ROOT)
    find_package(Threads REQUIRED)
    find_package(OpenSSL REQUIRED)
else()
    find_package(Threads)
    if(NOT Threads_FOUND)
        message(STATUS "Boost.MySQL has been disabled, because the required package Threads hasn't been found")
        return()
    endif()
    find_package(OpenSSL)
    if(NOT OpenSSL_FOUND)
        message(STATUS "Boost.MySQL has been disabled, because the required package OpenSSL hasn't been found")
        return()
    endif()
endif()

#
# Interface library (header-only)
#
add_library(boost_mysql INTERFACE)
add_library(Boost::mysql ALIAS boost_mysql)

if (BOOST_SUPERPROJECT_VERSION)
    target_include_directories(boost_mysql INTERFACE "${PROJECT_SOURCE_DIR}/include")
else()
    target_include_directories(
        boost_mysql
        SYSTEM
        INTERFACE
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
        "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
    )
endif()

target_compile_features(boost_mysql INTERFACE cxx_std_11)

target_link_libraries(
    boost_mysql
    INTERFACE
    ${_BOOST_LINK_LIBRARIES}
    Threads::Threads
    OpenSSL::Crypto
    OpenSSL::SSL
)

# Asio bases C++ feature detection on __cplusplus. Make MSVC
# define it correctly
if (MSVC)
    target_compile_options(boost_mysql INTERFACE /Zc:__cplusplus)
endif()

# Examples and tests
if(BUILD_TESTING)
    include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/test_utils.cmake)
    
    # Asio static library to speed up compilation
    if (BOOST_MYSQL_USE_FIND_PACKAGE)
        set(_ASIO_HEADERS Boost::headers)
    else()
        set(_ASIO_HEADERS Boost::asio)
    endif()

    find_package(OpenSSL REQUIRED)
    add_library(
        boost_mysql_asio
        STATIC
        ${CMAKE_CURRENT_SOURCE_DIR}/tools/asio.cpp
    )
    set_windows_version(boost_mysql_asio)
    target_link_libraries(
        boost_mysql_asio
        PUBLIC
        ${_ASIO_HEADERS}
        OpenSSL::Crypto
        OpenSSL::SSL
    )
    target_compile_definitions(
        boost_mysql_asio
        PUBLIC
        BOOST_ASIO_SEPARATE_COMPILATION
    )

    # All examples require a real server to run
    if (BOOST_MYSQL_INTEGRATION_TESTS)
        add_subdirectory(example)
    endif()

    add_subdirectory(test)
endif()
