# Copyright 2019-2025 by Jon Dart. All Rights Reserved.
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(arasan)

add_compile_definitions(ARASAN_VERSION=26.0)
set(NETWORK arasanv8-20260622.nnue CACHE STRING "default network file name")

set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)

set (CMAKE_CXX_STANDARD 17)

include(CheckIPOSupported)
check_ipo_supported()

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

# options
option(SYZYGY_TBS "Syzygy tablebase support" ON)
option(64BIT "64-bit target" ON)
option(OLD "Use no SIMD instructions" OFF)
option(MODERN "Use modern instructions" OFF)
# AVX2 and BMI2 can be specified separately or together and imply also "modern"
option(AVX2 "Use AVX2 instructions" OFF)
option(AVX512 "Use AVX512 instructions" OFF)
option(BMI2 "Use BMI2 instructions" OFF)
option(NEON "Use ARM NEON instructions" OFF)

set(EXE_NAME arasanx)

add_compile_definitions(SMP_STATS USE_INTRINSICS)

if(CMAKE_BUILD_TYPE MATCHES Debug)
    add_compile_definitions(_DEBUG)
endif()

if(CMAKE_SYSTEM_NAME MATCHES Darwin)
    add_compile_definitions(_MAC)
endif()

if(MSVC)
    add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS)
endif(MSVC)

if(SYZYGY_TBS)
    add_compile_definitions(SYZYGY_TBS)
    set(STB ${CMAKE_CURRENT_SOURCE_DIR}/syzygy/src)
    include_directories(${STB} .)
    list(APPEND EXTRA_SRC ${STB}/tbprobe.c ${STB}/tbprobe.h)
    SET_SOURCE_FILES_PROPERTIES(${STB}/tbprobe.c PROPERTIES LANGUAGE CXX )
endif(SYZYGY_TBS)

add_compile_definitions(NETWORK=${NETWORK})
set(NNUE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/nnue)
include_directories(${NNUE_DIR})
list(APPEND EXTRA_SRC evaluate.cpp)

if(64BIT)
    set(EXE_NAME ${EXE_NAME}-64)
    add_compile_definitions(_64BIT)
else()
    set(EXE_NAME ${EXE_NAME}-32)
endif(64BIT)

if(UNIX AND NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
    add_link_options("-fuse-ld=gold")
endif()

if (CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "86")
if(NOT OLD)
    add_compile_definitions(SIMD)
    add_compile_definitions(SSE2)
    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
        add_compile_options(-msse2)
    endif()

if(MODERN OR BMI2 OR AVX2 OR AVX512)
    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
        add_compile_options(-mssse3 -msse4.1 -msse4.2 -mpopcnt)
    endif()
    add_compile_definitions(SSSE3)
    add_compile_definitions(SSE41)
    add_compile_definitions(USE_POPCNT)
endif()

if(AVX2 OR AVX512)
    if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
        add_compile_options(/arch:AVX2)
    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
        add_compile_options(-mavx2 -mfma)
    endif()
    add_compile_definitions(AVX2)
endif(AVX2 OR AVX512)

if(AVX512)
    if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
        add_compile_options(/arch:AVX512)
    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
        add_compile_options(-mavx512bw)
    endif()
    add_compile_definitions(AVX512)
endif(AVX512)

if(BMI2)
    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
        add_compile_options(-mbmi2 -msse4.2)
    endif()
    add_compile_definitions(BMI2)
endif()

# end of block starting with architecture test
endif()
endif()

if(NEON)
    add_compile_definitions(SIMD)
    add_compile_definitions(NEON)
    set(EXE_NAME ${EXE_NAME}-neon)
elseif (AVX512)
     set(EXE_NAME ${EXE_NAME}-avx512)
elseif (AVX2)
     set(EXE_NAME ${EXE_NAME}-avx2)
if(BMI2)
    set(EXE_NAME ${EXE_NAME}-bmi2)
endif(BMI2)
elseif(MODERN)
    set(EXE_NAME ${EXE_NAME}-modern)
elseif (OLD)
    set(EXE_NAME ${EXE_NAME}-old)
endif()

add_executable (${EXE_NAME} arasanx.cpp attacks.cpp attacks.h bench.h
bench.cpp bhash.cpp bhash.h bitutil.h bitutil.cpp
bitboard.h bitprobe.cpp bitprobe.h board.cpp board.h boardio.cpp
boardio.h bookdefs.h bookread.cpp bookread.h bookwrit.cpp bookwrit.h
calctime.cpp calctime.h chess.cpp chess.h chessio.cpp chessio.h
constant.h eco.cpp eco.h epdrec.cpp epdrec.h
globals.cpp globals.h hash.cpp hash.h learn.cpp learn.h legal.cpp
legal.h material.cpp material.h movearr.cpp movearr.h movegen.cpp
movegen.h notation.cpp notation.h options.cpp options.h protocol.cpp
protocol.h scoring.cpp scoring.h searchc.cpp searchc.h search.cpp
search.h see.cpp see.h stats.cpp stats.h stdendian.h syzygy.cpp
syzygy.h tbconfig.h tester.cpp tester.h threadc.cpp threadc.h
threadp.cpp threadp.h types.h bench.cpp input.cpp ${EXTRA_SRC})

list(APPEND UTIL_SRC attacks.cpp attacks.h bhash.cpp bhash.h
bitutil.h bitutil.cpp bitboard.h bitprobe.cpp
bitprobe.h board.cpp board.h boardio.cpp boardio.h bookdefs.h
bookread.cpp bookread.h bookwrit.cpp bookwrit.h calctime.cpp
calctime.h chess.cpp chess.h chessio.cpp chessio.h constant.h eco.cpp
eco.h epdrec.cpp epdrec.h globals.cpp globals.h
hash.cpp hash.h learn.cpp learn.h legal.cpp legal.h material.cpp
material.h movearr.cpp movearr.h movegen.cpp movegen.h notation.cpp
notation.h options.cpp options.h scoring.cpp scoring.h searchc.cpp
searchc.h search.cpp search.h see.cpp see.h stats.cpp stats.h
stdendian.h syzygy.cpp syzygy.h tbconfig.h threadc.cpp threadc.h
threadp.cpp threadp.h types.h ${EXTRA_SRC})

add_executable (playchess EXCLUDE_FROM_ALL util/playchess.cpp ${UTIL_SRC})

add_executable (makebook EXCLUDE_FROM_ALL util/makebook.cpp ${UTIL_SRC})

add_executable (ecocoder EXCLUDE_FROM_ALL util/ecocoder.cpp ${UTIL_SRC})

add_executable (selfplay EXCLUDE_FROM_ALL util/selfplay.cpp ${UTIL_SRC} util/binformat.cpp)

add_executable (blundercheck EXCLUDE_FROM_ALL util/blundercheck.cpp ${UTIL_SRC})

add_executable (sortpgn EXCLUDE_FROM_ALL util/sortpgn.cpp ${UTIL_SRC})

add_executable (unit EXCLUDE_FROM_ALL unit.cpp nnuetest.cpp util/binformat.cpp ${UTIL_SRC})

target_link_libraries(${EXE_NAME} PRIVATE Threads::Threads)
target_link_libraries(playchess PRIVATE Threads::Threads)
target_link_libraries(ecocoder PRIVATE Threads::Threads)
target_link_libraries(makebook PRIVATE Threads::Threads)
target_link_libraries(selfplay PRIVATE Threads::Threads)
target_link_libraries(blundercheck PRIVATE Threads::Threads)
target_link_libraries(sortpgn PRIVATE Threads::Threads)
target_link_libraries(unit PRIVATE Threads::Threads)

set_target_properties(${EXE_NAME} playchess makebook ecocoder selfplay blundercheck sortpgn unit PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)

add_custom_target(utils)

add_dependencies(utils playchess ecocoder makebook selfplay blundercheck sortpgn)
