cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
cmake_policy(VERSION 3.12)

project(BearSource
        VERSION ${CMAKE_PROJECT_VERSION}
        LANGUAGES C CXX
        )

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSPDLOG_NO_EXCEPTIONS")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGOOGLE_PROTOBUF_NO_RTTI")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")

if (ENABLE_UNIT_TESTS)
    find_program(MEMORYCHECK_COMMAND NAMES valgrind)
    set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full")

    include(CTest)
    enable_testing()

    find_package(PkgConfig REQUIRED)
    pkg_check_modules(GTest REQUIRED IMPORTED_TARGET gtest gtest_main gmock)
endif ()

find_package(Threads REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(gRPC REQUIRED IMPORTED_TARGET protobuf grpc++)

if (fmt_VERSION_MAJOR GREATER_EQUAL 9)
    set(FMT_NEEDS_OSTREAM_FORMATTER 1)
    set(HAVE_FMT_STD_H 1) # FIXME: this should be done with `check_include_file`
endif ()

if (UNIX AND NOT APPLE)
    set(SUPPORT_PRELOAD 1)
endif()
if (ENABLE_MULTILIB)
    set(SUPPORT_MULTILIB 1)
endif()

include(CheckIncludeFile)
check_include_file(spawn.h HAVE_SPAWN_H)
check_include_file(unistd.h HAVE_UNISTD_H)
check_include_file(dlfcn.h HAVE_DLFCN_H)
check_include_file(errno.h HAVE_ERRNO_H)
check_include_file(sys/utsname.h HAVE_SYS_UTSNAME_H)
check_include_file(sys/wait.h HAVE_SYS_WAIT_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(sys/stat.h HAVE_SYS_STAT_H)
check_include_file(gnu/lib-names.h HAVE_GNU_LIB_NAMES_H)
#check_include_file(fmt/std.h HAVE_FMT_STD_H)
include(CheckSymbolExists)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS})
set(CMAKE_REQUIRED_FLAGS -D_GNU_SOURCE)
check_symbol_exists(_NSGetEnviron "crt_externs.h" HAVE_NSGETENVIRON)
check_symbol_exists(dlopen "dlfcn.h" HAVE_DLOPEN)
check_symbol_exists(dlsym "dlfcn.h" HAVE_DLSYM)
check_symbol_exists(dlerror "dlfcn.h" HAVE_DLERROR)
check_symbol_exists(dlclose "dlfcn.h" HAVE_DLCLOSE)
check_symbol_exists(RTLD_NEXT "dlfcn.h" HAVE_RTLD_NEXT)
check_symbol_exists(EACCES "errno.h" HAVE_EACCES)
check_symbol_exists(ENOENT "errno.h" HAVE_ENOENT)
check_symbol_exists(strerror_r "string.h" HAVE_STRERROR_R)
check_symbol_exists(environ "unistd.h" HAVE_ENVIRON)
check_symbol_exists(uname "sys/utsname.h" HAVE_UNAME)
check_symbol_exists(confstr "unistd.h" HAVE_CONFSTR)
check_symbol_exists(_CS_PATH "unistd.h" HAVE_CS_PATH)
check_symbol_exists(_CS_GNU_LIBC_VERSION "unistd.h" HAVE_CS_GNU_LIBC_VERSION)
check_symbol_exists(_CS_GNU_LIBPTHREAD_VERSION "unistd.h" HAVE_CS_GNU_LIBPTHREAD_VERSION)

include(GNUInstallDirs) # The directory names are used in the config file
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})

add_subdirectory(libresult)
add_subdirectory(libflags)
add_subdirectory(libshell)
add_subdirectory(libsys)
add_subdirectory(libmain)
add_subdirectory(intercept)
add_subdirectory(citnames)
add_subdirectory(bear)
