cmake_minimum_required(VERSION 3.21)
project(game_resolver_cpp VERSION 0.1.1 LANGUAGES CXX)

option(GAME_RESOLVER_BUILD_TESTS "Build the test suite" ${PROJECT_IS_TOP_LEVEL})
option(GAME_RESOLVER_BUILD_EXAMPLES "Build the example programs" ${PROJECT_IS_TOP_LEVEL})
option(GAME_RESOLVER_BUILD_BENCHMARKS "Build the benchmark program" ${PROJECT_IS_TOP_LEVEL})
option(GAME_RESOLVER_BUILD_PYTHON "Build the Python extension module" OFF)
option(GAME_RESOLVER_WERROR "Treat compiler warnings as errors" OFF)
option(GAME_RESOLVER_SANITIZE "Build with sanitizers (see GAME_RESOLVER_SANITIZERS)" OFF)

# macOS の Apple clang 15 に同梱の ASan ランタイムは、最近の macOS 上で
# 「CHECK failed: sanitizer_malloc_mac.inc」で起動時に落ちる（自明なプログラムでも再現する
# ツールチェーン側の問題）。そのため Apple では既定を UBSan のみにする。
# ASan は Linux の CI ジョブでかける。明示指定すれば macOS でも有効にできる。
if(APPLE)
  set(GAME_RESOLVER_SANITIZERS "undefined" CACHE STRING "Comma separated sanitizer list")
else()
  set(GAME_RESOLVER_SANITIZERS "address,undefined" CACHE STRING "Comma separated sanitizer list")
endif()

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()

# ---------------------------------------------------------------- library
add_library(game_resolver
  src/version.cpp
  src/action.cpp
  src/payoff.cpp
  src/nash_equilibrium.cpp
  src/solver/nash_solver.cpp
  src/bayesian/bayesian_player.cpp
  src/bayesian/bayesian_nash_equilibrium.cpp
)
add_library(game_resolver::game_resolver ALIAS game_resolver)

target_include_directories(game_resolver PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>
)
target_compile_features(game_resolver PUBLIC cxx_std_20)

# 静的ライブラリを共有オブジェクトにリンクできるようにする。
# これが無いと Linux で Python 拡張モジュール (_core.so) のリンクが
# 「relocation R_X86_64_32 ... can not be used when making a shared object」で失敗する。
# macOS は常に PIC なので気づきにくい。利用者が自分の共有ライブラリに組み込む場合にも要る。
set_target_properties(game_resolver PROPERTIES POSITION_INDEPENDENT_CODE ON)

find_package(Threads REQUIRED)
target_link_libraries(game_resolver PUBLIC Threads::Threads)

if(MSVC)
  target_compile_options(game_resolver PRIVATE /W4)
  if(GAME_RESOLVER_WERROR)
    target_compile_options(game_resolver PRIVATE /WX)
  endif()
else()
  target_compile_options(game_resolver PRIVATE -Wall -Wextra -Wpedantic)
  if(GAME_RESOLVER_WERROR)
    target_compile_options(game_resolver PRIVATE -Werror)
  endif()
endif()

if(GAME_RESOLVER_SANITIZE)
  message(STATUS "Sanitizers: ${GAME_RESOLVER_SANITIZERS}")
  target_compile_options(game_resolver PUBLIC
    -fsanitize=${GAME_RESOLVER_SANITIZERS} -fno-omit-frame-pointer)
  target_link_options(game_resolver PUBLIC -fsanitize=${GAME_RESOLVER_SANITIZERS})
endif()

# ---------------------------------------------------------------- subdirs
if(GAME_RESOLVER_BUILD_EXAMPLES)
  add_subdirectory(examples)
endif()

if(GAME_RESOLVER_BUILD_BENCHMARKS)
  add_subdirectory(benchmarks)
endif()

if(GAME_RESOLVER_BUILD_PYTHON)
  add_subdirectory(python)
endif()

if(GAME_RESOLVER_BUILD_TESTS)
  enable_testing()
  add_subdirectory(tests)
endif()

# ---------------------------------------------------------------- install
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

install(TARGETS game_resolver
  EXPORT game_resolverTargets
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

install(EXPORT game_resolverTargets
  FILE game_resolverTargets.cmake
  NAMESPACE game_resolver::
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/game_resolver
)

configure_package_config_file(
  ${CMAKE_CURRENT_SOURCE_DIR}/cmake/game_resolverConfig.cmake.in
  ${CMAKE_CURRENT_BINARY_DIR}/game_resolverConfig.cmake
  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/game_resolver
)
write_basic_package_version_file(
  ${CMAKE_CURRENT_BINARY_DIR}/game_resolverConfigVersion.cmake
  COMPATIBILITY SameMajorVersion
)
install(FILES
  ${CMAKE_CURRENT_BINARY_DIR}/game_resolverConfig.cmake
  ${CMAKE_CURRENT_BINARY_DIR}/game_resolverConfigVersion.cmake
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/game_resolver
)
