# CMake file for the main spigot project. This file also appears in
# the source distribution of the Python module, but only so that
# setup.py can read one variable definition out of it: it's otherwise
# useless.

cmake_minimum_required(VERSION 3.5)

project(spigot)

set(USE_GMP ON
  CACHE BOOL "Use GMP for multiprecision integers, if available")
set(GMP_DIR ""
  CACHE STRING "Location of GMP include and library directories")

include(FindCurses)
include(FindPerl)
include(GNUInstallDirs)
include(CheckIncludeFile)
include(CheckSymbolExists)
find_program(HALIBUT halibut)

if(USE_GMP)
  if(GMP_DIR)
    include_directories(${GMP_DIR}/include)
    link_directories(${GMP_DIR}/lib)
    list(APPEND CMAKE_REQUIRED_INCLUDES ${GMP_DIR}/include)
    list(APPEND CMAKE_LIBRARY_PATH ${GMP_DIR}/lib)
  endif()
  check_include_file(gmp.h HAVE_GMP_H)
  find_library(GMP_LIB gmp)
  if(NOT GMP_LIB)
    find_library(GMP_LIB libgmp)
  endif()
endif()

if(USE_GMP AND HAVE_GMP_H AND GMP_LIB)
  message("-- Bigint provider: GMP")
  set(HAVE_LIBGMP ON)
  link_libraries(${GMP_LIB})
else()
  message("-- Bigint provider: internal")
endif()

check_include_file(unistd.h HAVE_UNISTD_H)
check_symbol_exists(tcsetattr "termios.h;unistd.h" HAVE_TCSETATTR)
check_symbol_exists(fdopen "stdio.h" HAVE_FDOPEN)

set(HAVE_CURSES CURSES_FOUND)
if(CURSES_FOUND)
  if(CURSES_HAVE_NCURSES_NCURSES_H)
    set(CURSES_HEADER "ncurses/ncurses.h")
  elseif(CURSES_HAVE_NCURSES_CURSES_H)
    set(CURSES_HEADER "ncurses/curses.h")
  elseif(CURSES_HAVE_NCURSES_H)
    set(CURSES_HEADER "ncurses.h")
  elseif(CURSES_HAVE_CURSES_H)
    set(CURSES_HEADER "curses.h")
  endif()

  function(check_tiparm)
    list(APPEND CMAKE_REQUIRED_INCLUDES ${CURSES_INCLUDE_DIRS})
    list(APPEND CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARIES})
    check_symbol_exists(tiparm "${CURSES_HEADER};term.h" HAVE_TIPARM)
    set(HAVE_TIPARM ${HAVE_TIPARM} PARENT_SCOPE)
  endfunction()
  check_tiparm()

  include_directories(${CURSES_INCLUDE_DIRS})
  link_libraries(${CURSES_LIBRARIES})
endif()

configure_file(cmake.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/cmake.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
add_compile_definitions(HAVE_CMAKE_H)

if(CMAKE_SYSTEM_NAME MATCHES "Windows")
  add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()

# This list of source files is also used by setup.py to build the
# Python module. It contains all the source files shared between the
# standalone spigot program and the Python library.
#
# setup.py parses this definition crudely out of this file, so don't
# do anything fancy. Keep it to a list of literal .cpp file names.
set(SPIGOT_SHARED_MODULES
  consts.cpp erf.cpp exp.cpp expr.cpp gamma.cpp arithmetic.cpp io.cpp
  monotone.cpp baseout.cpp spigot.cpp sqrt.cpp trig.cpp unary.cpp
  lambertw.cpp algebraic.cpp expint.cpp trigint.cpp zeta.cpp
  enforce.cpp misc.cpp cfracout.cpp holefiller.cpp error.cpp
  hypergeom.cpp inverter.cpp)

add_executable(spigot
  main.cpp noexcept.cpp iocli.cpp
  ${SPIGOT_SHARED_MODULES})

set_property(TARGET spigot PROPERTY CXX_STANDARD 14)

install(TARGETS spigot
  RUNTIME
  DESTINATION ${CMAKE_INSTALL_BINDIR})

if(HALIBUT)
  set(manpage_sources
    ${CMAKE_CURRENT_SOURCE_DIR}/defs.but
    ${CMAKE_CURRENT_SOURCE_DIR}/manpage.but)
  add_custom_command(OUTPUT spigot.1
    COMMAND ${HALIBUT} --man=spigot.1 ${manpage_sources}
    DEPENDS ${manpage_sources})
  add_custom_target(manpage ALL DEPENDS spigot.1)
  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/spigot.1
    DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)

  if(PERL_EXECUTABLE)
    set(manual_sources
      ${CMAKE_CURRENT_SOURCE_DIR}/defs.but
      ${CMAKE_CURRENT_SOURCE_DIR}/manual.but
      ${CMAKE_CURRENT_SOURCE_DIR}/manpage.but)
    add_custom_command(OUTPUT spigot.html.pre
      COMMAND ${HALIBUT} --html=spigot.html.pre ${manual_sources}
      DEPENDS ${manual_sources})
    add_custom_command(OUTPUT spigot.html
      COMMAND ${PERL_EXECUTABLE}
        ${CMAKE_CURRENT_SOURCE_DIR}/manual.pl
        < spigot.html.pre > spigot.html
      DEPENDS
        ${CMAKE_CURRENT_SOURCE_DIR}/manual.pl
        spigot.html.pre)
    add_custom_target(manual ALL DEPENDS spigot.html)
    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/spigot.html
      DESTINATION ${CMAKE_INSTALL_DOCDIR})
  else() # PERL_EXECUTABLE
    message("Perl not found -- cannot build HTML manual")
  endif()
  
else() # HALIBUT
  message("Halibut not found -- cannot build documentation")
endif()

# Enable the sh-based test script, if we think sh is reasonably likely to work.
if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
  enable_testing()
  add_test(NAME test.sh
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test.sh
      ${CMAKE_CURRENT_BINARY_DIR}/spigot)
endif()
