cmake_minimum_required(VERSION 3.7...3.28)
project(tweak LANGUAGES C)

set(TWEAK_DISPLAY_MANAGER "any"
  CACHE STRING "Which display management package to build Tweak against")
set_property(CACHE TWEAK_DISPLAY_MANAGER
  PROPERTY STRINGS any curses slang)

set(display_source none)
if(display_source STREQUAL "none" AND
    (TWEAK_DISPLAY_MANAGER STREQUAL "any" OR
      TWEAK_DISPLAY_MANAGER STREQUAL "curses"))
  find_package(Curses)
  if(CURSES_FOUND)
    message(STATUS "Using curses for display management")
    set(display_source curses.c)
  endif()
endif()
if(display_source STREQUAL "none" AND
    (TWEAK_DISPLAY_MANAGER STREQUAL "any" OR
      TWEAK_DISPLAY_MANAGER STREQUAL "slang"))
  find_package(PkgConfig)
  pkg_check_modules(SLANG slang)
  if(SLANG_FOUND)
    message(STATUS "Using SLang for display management")
    set(display_source slang.c)
  endif()
endif()
if(display_source STREQUAL "none")
  message(FATAL_ERROR "Cannot build Tweak without either curses or SLang")
endif()

include(CheckCSourceCompiles)

check_c_source_compiles("
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
int main(int argc, char **argv) {
    fseeko(stdout, 0, SEEK_SET);
    ftello(stdout);
}" HAVE_FSEEKO_FTELLO)

check_c_source_compiles("
#include <alloca.h>
int main(int argc, char **argv) {
    alloca(128);
}" HAVE_ALLOCA)

add_executable(tweak
  main.c keytab.c actions.c search.c rcfile.c buffer.c btree.c
  ${display_source})
if(display_source STREQUAL "curses.c")
  target_include_directories(tweak PRIVATE ${CURSES_INCLUDE_DIRS})
  target_compile_options(tweak PRIVATE ${CURSES_CFLAGS})
  target_link_libraries(tweak ${CURSES_LIBRARIES})
elseif(display_source STREQUAL "slang.c")
  target_include_directories(tweak PRIVATE ${SLANG_INCLUDE_DIRS})
  target_compile_options(tweak PRIVATE ${SLANG_CFLAGS})
  target_link_libraries(tweak ${SLANG_LIBRARIES})
endif()

set(GENERATED_SOURCES_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY})
include_directories(${GENERATED_SOURCES_DIR})
configure_file(cmake.h.in ${GENERATED_SOURCES_DIR}/cmake.h)

# If Halibut is available, build the docs too.
find_program(HALIBUT halibut)
if(HALIBUT)
  set(BUILD_MANPAGE ON)
  add_custom_command(OUTPUT tweak.1
    COMMAND ${HALIBUT} --man=tweak.1
      ${CMAKE_CURRENT_SOURCE_DIR}/manpage.but
    DEPENDS
      ${CMAKE_CURRENT_SOURCE_DIR}/manpage.but)
  add_custom_target(doc ALL DEPENDS tweak.1)
else()
  set(BUILD_MANPAGE OFF)
endif()

# Installation
include(GNUInstallDirs)
if(CMAKE_VERSION VERSION_LESS 3.14)
  # CMake 3.13 and earlier required an explicit install destination.
  install(TARGETS tweak RUNTIME DESTINATION bin)
else()
  # 3.14 and above selects a sensible default, which we should avoid
  # overriding here so that end users can override it using
  # CMAKE_INSTALL_BINDIR.
  install(TARGETS tweak)
endif()

if(BUILD_MANPAGE)
  install(FILES ${CMAKE_BINARY_DIR}/tweak.1
    DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
elseif(EXISTS ${CMAKE_SOURCE_DIR}/tweak.1)
  # If we weren't able to build the man page from source, but we are
  # building from a source tarball in which a pre-built man page is
  # provided, we can install that.
  install(FILES ${CMAKE_SOURCE_DIR}/tweak.1
    DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif()
