# ##############################################################################
# Project-Wide Settings
# ##############################################################################
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)

# Set the required policies
include(cmake/set_policy.cmake)

set_policy(CMP0054 NEW) # ENABLE  CMP0054: Only interpret if() arguments as
                        # variables or keywords when unquoted.
set_policy(CMP0063 NEW) # ENABLE  CMP0063: Honor visibility properties for all
                        # target types.
set_policy(CMP0077 NEW) # ENABLE  CMP0077: option() honors normal variables.
set_policy(CMP0091 NEW) # Enables the MSVC_RUNTIME_LIBRARY property on targets
set_policy(CMP0120 OLD) # DISABLE CMP0120: The WriteCompilerDetectionHeader
                        # module is removed.

# Define the project name, language and description
project(
  REmatch
  LANGUAGES CXX
  DESCRIPTION
    "REmatch: A C++ regex library for information extraction that uses constant delay algorithms"
)

# Set the project version
set(CMAKE_PROJECT_VERSION_MAJOR 1)
set(CMAKE_PROJECT_VERSION_MINOR 1)
set(CMAKE_PROJECT_VERSION_PATCH 0)
set(CMAKE_PROJECT_VERSION
    "${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}"
)

# Set the required C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

# Generate compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)

# Configure RPATH
# src: https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
  set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
endif()


# Configure the visibility of symbols in targets
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)

# Create a module definition with all global symbol definitions (Shared libraries)
set(WINDOWS_EXPORT_ALL_SYMBOLS ON)

# ##############################################################################
# Options
# ##############################################################################
option(BUILD_SHARED_LIBS "Build shared instead of static libraries" OFF)
option(BUILD_TESTING "Build tests" OFF)
option(ENABLE_PROFILING "Enable profiling" OFF)

# PIC is necessary for shared libraries and SKBUILD target
if(BUILD_SHARED_LIBS OR SKBUILD)
  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
else()
  set(CMAKE_POSITION_INDEPENDENT_CODE OFF)
endif()
# ##############################################################################
# Import CMake modules
# ##############################################################################
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(InstallRequiredSystemLibraries)
include(GenerateExportHeader)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler_options.cmake)

include(CMakePrintHelpers)

# Use all cores but one for compilation
include(ProcessorCount)
ProcessorCount(NUM_CORES)
if(NUM_CORES GREATER 1)
  math(EXPR PARALLEL_LEVEL "${NUM_CORES} - 1")
  set(CMAKE_BUILD_PARALLEL_LEVEL ${PARALLEL_LEVEL})
endif()

cmake_print_variables(BUILD_SHARED_LIBS)
cmake_print_variables(BUILD_TESTING)
cmake_print_variables(ENABLE_PROFILING)

# Check for system dir install
set(SYSTEM_DIR_INSTALL FALSE)
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr" OR "${CMAKE_INSTALL_PREFIX}"
                                                STREQUAL "/usr/local")
  set(SYSTEM_DIR_INSTALL TRUE)
endif()

# Set output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
# Prevent Windows autogenerated extra directories
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
  string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG}
      ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG}
      ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG}
      ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)

# Third parties
add_subdirectory(third_party/antlr4-cpp-runtime)
include_directories(third_party/antlr4-cpp-runtime/src)

include_directories(third_party/cli11)

# Source code
file(GLOB_RECURSE REMATCH_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/rematch/*.cpp)
file(GLOB_RECURSE REMATCH_HDR ${CMAKE_CURRENT_SOURCE_DIR}/src/rematch/*.hpp)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/rematch)

# Compile and install related commands.
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)

if(NOT EMSCRPTEN AND NOT SKBUILD)
  # Create and install CMake configuration files for your project that are
  # necessary to for other projects to call find_package(LibTemplateCMake).
  #
  # Note that it is extremely important to use exactly the project name while
  # installing configuration files (you can use PROJECT_NAME variable to avoid
  # any possible error). This is required to allow find_package() to properly
  # look for the installed library in system path, in particular in Windows when
  # the installation is performed in the default path.
  #
  # install_basic_package_files() comes with many input parameters to customize
  # the configuration files. The parameters used in the following call provide
  # basic versions of CMake configuration files. See
  # install_basic_package_files() documentation found in ./cmake folder.
  #
  # Note that if your library depends from other libraries, you are probably
  # required to used the install_basic_package_files() DEPENDENCIES option.
  include(InstallBasicPackageFiles)
  install_basic_package_files(
    ${PROJECT_NAME}
    VERSION
    ${CMAKE_PROJECT_VERSION}
    COMPATIBILITY
    AnyNewerVersion
    VARS_PREFIX
    ${PROJECT_NAME}
    NO_CHECK_REQUIRED_COMPONENTS_MACRO)

  # Add the uninstall target
  include(AddUninstallTarget)
endif()
