cmake_minimum_required(VERSION 3.1)

file(READ "libclingo/clingo.h" clingoh)
string(REGEX MATCH "#define CLINGO_VERSION \"([^\"]*)\"" clingov ${clingoh})

project(CLINGO VERSION "${CMAKE_MATCH_1}" LANGUAGES C CXX)
if (POLICY CMP0063)
    cmake_policy(SET CMP0063 NEW)
endif()
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
    message(STATUS "No build type selected - using 'Release'")
    set(CMAKE_BUILD_TYPE "Release")
endif()

include(GNUInstallDirs)
include(CMakeDependentOption)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(clingo_functions)

# Enable folders in IDEs like Visual Studio
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

option(CLINGO_BUILD_WEB         "enable web target"             OFF)
option(CLINGO_BUILD_STATIC      "do not build shared libraries" OFF)
option(CLINGO_BUILD_WITH_PYTHON "enable python support"          ON)
option(CLINGO_BUILD_WITH_LUA    "enable lua support"             ON)
option(CLINGO_BUILD_TESTS       "build tests"                   OFF)
option(CLINGO_BUILD_EXAMPLES    "build examples"                OFF)
option(CLINGO_BUILD_APPS        "build applications"             ON)
option(CLINGO_MANAGE_RPATH      "set rpath if not installed into system directory" ON)

CMAKE_DEPENDENT_OPTION(CLINGO_REQUIRE_PYTHON   "fail if python support not found" OFF "CLINGO_BUILD_WITH_PYTHON" OFF)
CMAKE_DEPENDENT_OPTION(CLINGO_REQUIRE_LUA      "fail if lua support not found"    OFF "CLINGO_BUILD_WITH_LUA"    OFF)
CMAKE_DEPENDENT_OPTION(CLINGO_BUILD_SHARED     "build clingo library shared"      ON  "NOT CLINGO_BUILD_STATIC"  OFF)
CMAKE_DEPENDENT_OPTION(CLINGO_BUILD_PY_SHARED  "build pyclingo library shared"    OFF "NOT CLINGO_BUILD_STATIC"  OFF)
CMAKE_DEPENDENT_OPTION(CLINGO_BUILD_LUA_SHARED "build luaclingo library shared"   OFF "NOT CLINGO_BUILD_STATIC"  OFF)

option(PYCLINGO_USER_INSTALL "install the python module in the user's site directory" ON)
option(PYCLINGO_DYNAMIC_LOOKUP "do not link to python library and pass linker option `-undefined link_dynamic`" ${APPLE})
CMAKE_DEPENDENT_OPTION(PYCLINGO_USE_INSTALL_PREFIX "install the python module under the install prefix" OFF "NOT PYCLINGO_USER_INSTALL" OFF)

set(CLINGO_CLINGOPATH "" CACHE STRING "global search directories for clingo's include statement")
set(CLINGO_USE_LIB OFF CACHE BOOL "advanced option to build python and lua modules against an existing libclingo")
set(CLINGO_BUILD_REVISION "" CACHE STRING "revision string to add to version information")

mark_as_advanced(CLINGO_BUILD_WEB)
mark_as_advanced(CLINGO_BUILD_STATIC)
mark_as_advanced(CLINGO_BUILD_SHARED)
mark_as_advanced(CLINGO_BUILD_PY_SHARED)
mark_as_advanced(CLINGO_BUILD_LUA_SHARED)
mark_as_advanced(CLINGO_USE_LIB)
mark_as_advanced(CLINGO_BUILD_REVISION)

# workaround to set custom ar and ranlib
if (CLINGO_CMAKE_AR)
    set(CMAKE_AR "${CLINGO_CMAKE_AR}")
    set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
    set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
endif()
if (CLINGO_CMAKE_RANLIB)
    set(CMAKE_RANLIB "${CLINGO_CMAKE_RANLIB}")
    set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
    set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
endif()

if (CLINGO_MANAGE_RPATH)
    set(CMAKE_SKIP_BUILD_RPATH FALSE)
    set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
    set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
    list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_FULL_LIBDIR}" isSystemDir)
    if ("${isSystemDir}" STREQUAL "-1")
        set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}")
    endif()
endif()

if (CLINGO_BUILD_WEB)
    unset(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES)
    unset(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES)
    unset(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS)
    unset(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS)
    unset(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES)
    unset(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES)
endif()

if (NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endif()
if (NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
if (NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
if (NOT CMAKE_IMPORT_LIBRARY_PREFIX)
    set(CMAKE_IMPORT_LIBRARY_PREFIX import_)
endif()

# NOTE: searching for the interpreter first increases the chance
#       that searching for the python libraries finds the matching libraries for the default python interpreter
#       python is also used to run the tests
find_package(PythonInterp)
add_library(Pyclingo::Pyclingo INTERFACE IMPORTED)
if (CLINGO_BUILD_WITH_PYTHON)
    if (CLINGO_REQUIRE_PYTHON)
        find_package(PythonLibs REQUIRED)
    else()
        find_package(PythonLibs)
    endif()
    if(PYTHONLIBS_FOUND)
        add_library(Python::Python INTERFACE IMPORTED)
        set_property(TARGET Python::Python PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}")
        if (PYCLINGO_DYNAMIC_LOOKUP)
            set_property(TARGET Pyclingo::Pyclingo PROPERTY INTERFACE_LINK_LIBRARIES "${PYTHON_LIBRARIES}")
        else()
            set_property(TARGET Python::Python PROPERTY INTERFACE_LINK_LIBRARIES "${PYTHON_LIBRARIES}")
        endif()
    endif()
endif()
if (CLINGO_BUILD_WITH_LUA)
    if (CLINGO_REQUIRE_LUA)
        find_package(Lua REQUIRED)
    else()
        find_package(Lua)
    endif()
    if(LUA_FOUND)
        add_library(Lua::Lua INTERFACE IMPORTED)
        set_property(TARGET Lua::Lua PROPERTY INTERFACE_LINK_LIBRARIES "${LUA_LIBRARIES}")
        set_property(TARGET Lua::Lua PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}")
    endif()
endif()
find_package(BISON "2.5")
find_package(RE2C "0.13")

if (POLICY CMP0063 AND (CLINGO_BUILD_SHARED OR PYTHONLIBS_FOUND OR LUA_FOUND))
    set(CMAKE_CXX_VISIBILITY_PRESET hidden)
    set(CMAKE_C_VISIBILITY_PRESET hidden)
endif()

enable_testing()

# NOTE: assumes that submodule has been initialized
set(CLASP_BUILD_APP ${CLINGO_BUILD_APPS} CACHE BOOL "")
if (CLINGO_USE_LIB)
    set(clingo_library_targets)
    add_library(libclingo INTERFACE IMPORTED)
    set_property(TARGET libclingo PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CLINGO_SOURCE_DIR}/libclingo")
    set_property(TARGET libclingo PROPERTY INTERFACE_LINK_LIBRARIES "clingo")
else()
    set(clingo_library_targets libclingo libgringo libpotassco libclasp libreify)
    add_subdirectory(clasp)
    add_subdirectory(libreify)
    add_subdirectory(libgringo)
    add_subdirectory(libclingo)
endif()
if (PYTHONLIBS_FOUND)
    add_subdirectory(libpyclingo)
    list(APPEND clingo_library_targets libpyclingo)
else()
    add_library(libpyclingo INTERFACE IMPORTED)
endif()
if (LUA_FOUND)
    add_subdirectory(libluaclingo)
    list(APPEND clingo_library_targets libluaclingo)
else()
    add_library(libluaclingo INTERFACE IMPORTED)
endif()
if (CLINGO_BUILD_APPS AND NOT CLINGO_USE_LIB)
    add_subdirectory(app/reify)
    add_subdirectory(app/gringo)
    add_subdirectory(app/clingo)
endif()
if (CLINGO_BUILD_EXAMPLES)
    add_subdirectory(examples/c)
    add_subdirectory(examples/cc)
endif()
if (NOT CLINGO_BUILD_STATIC AND PYTHONLIBS_FOUND)
    add_subdirectory(app/pyclingo)
endif()
if (NOT CLINGO_BUILD_STATIC AND LUA_FOUND)
    add_subdirectory(app/luaclingo)
endif()
if (CLINGO_BUILD_WEB)
    add_subdirectory(app/web)
endif()
if (NOT CLINGO_BUILD_STATIC AND (CLINGO_BUILD_SHARED OR PYTHONLIBS_FOUND OR LUA_FOUND))
    foreach(target ${clingo_library_targets})
        set_target_properties(${target} PROPERTIES POSITION_INDEPENDENT_CODE ON)
    endforeach()
endif()

