cmake_minimum_required(VERSION 2.8)

project(OpenANN)

find_package(Doxygen)
find_package(OpenMP)
include(CheckIncludeFiles)
include(cmake/UseDoxygen.cmake)
include(cmake/Utilities.cmake)
include(cmake/FindEigen3.cmake)

# Check dependencies
if(NOT EIGEN3_FOUND)
  message(FATAL_ERROR "Could not find Eigen 3 library. You can either "
                      "install it with your package management system or "
                      "download it from http://eigen.tuxfamily.org/ and "
                      "install it with CMake.")
endif()
if(UNIX)
  find_program(SH_EXECUTABLE sh)
  if(NOT SH_EXECUTABLE)
    message(FATAL_ERROR "Command 'sh' is required to download required libraries.")
  endif()
  find_program(WGET_EXECUTABLE wget)
  if(NOT WGET_EXECUTABLE)
    message(FATAL_ERROR "Command 'wget' is required to download required libraries.")
  endif()
  find_program(UNZIP_EXECUTABLE unzip)
  if(NOT UNZIP_EXECUTABLE)
    message(FATAL_ERROR "Command 'unzip' is required to download required libraries.")
  endif()
else()
  message(WARNING "Only MacOS and Linux are supported!")
endif()

# Ensure out-of-source build
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
  message(FATAL_ERROR "Usage: mkdir build; cmake ..")
endif()

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

set(LOG_LEVEL "INFO" CACHE String "Log level (DEBUG, INFO, ERROR, DISABLED).")
set(PARALLEL_CORES 4 CACHE Integer "Number of cores that can be used in parallel.")

set(OPENANN_VERSION_NUMBER "1.1.0")
set(OPENANN_URL "https://github.com/OpenANN/OpenANN")
set(OPENANN_BRIEF_DESCRIPTION "An open source library for artificial neural networks.")
current_time(OPENANN_TIME)
set(OPENANN_OPTIMIZATION_FLAGS)
set(OPENANN_PYTHON_COMPILE_ARGS)
if(${CMAKE_BUILD_TYPE} STREQUAL Debug)
  message(STATUS "Debug configuration")
  if(CMAKE_COMPILER_IS_GNUCXX)
    compiler_check_add_flag("-ggdb")
    compiler_check_add_flag("-fno-default-inline")
    if(OPENMP_FOUND)
      check_cxx_compiler_flag("-fopenmp" COMPILER_SUPPORT_OPENMP)
      if(COMPILER_SUPPORT_OPENMP)
        compiler_add_flag("-fopenmp")
        compiler_add_flag("-DPARALLEL_CORES=1")
      endif()
    endif()
    compiler_add_flag("-DOPENANN_LOGLEVEL=OpenANN::Log::DEBUG")
  endif()
elseif(${CMAKE_BUILD_TYPE} STREQUAL Release)
  message(STATUS "Release configuration")
  if(CMAKE_COMPILER_IS_GNUCXX)
    compiler_check_add_flag("-g0")
    compiler_check_add_flag("-s")
    compiler_check_add_flag("-O3")
    compiler_check_add_flag("-msse")
    compiler_check_add_flag("-msse2")
    compiler_check_add_flag("-msse3")
    compiler_check_add_flag("-mssse3")
    compiler_check_add_flag("-msse4.1")
    compiler_check_add_flag("-msse4.2")
    if(OPENMP_FOUND)
      check_cxx_compiler_flag("-fopenmp" COMPILER_SUPPORT_OPENMP)
      if(COMPILER_SUPPORT_OPENMP)
        compiler_add_flag("-fopenmp")
        compiler_add_flag("-DPARALLEL_CORES=${PARALLEL_CORES}")
      endif()
    endif()
    compiler_add_flag("-DOPENANN_LOGLEVEL=OpenANN::Log::${LOG_LEVEL}")
  endif()
else()
  message(FATAL_ERROR "Unknown configuration, set CMAKE_BUILD_TYPE to Debug or Release")
endif()
set(OPENANN_COMPILER_FLAGS)
if(CMAKE_COMPILER_IS_GNUCXX)
  set(COMPILER_WARNING_FLAGS "-Wall -Wextra -pedantic -Wno-long-long -Wno-enum-compare")
endif()
set(OPENANN_LINK_LIBS "-lopenann") # libraries to link for external executables
if(OPENMP_FOUND AND CMAKE_COMPILER_IS_GNUCXX)
  set(OPENANN_LINK_LIBS "${OPENANN_LINK_LIBS} -lgomp")
endif()

set(OPENANN_COMPILER_FLAGS "${OPENANN_COMPILER_FLAGS} ${OPENANN_OPTIMIZATION_FLAGS}")
add_subdirectory(lib)

include_directories(. ${EIGEN3_INCLUDE_DIRS} lib/CMA-ESpp lib/ALGLIB test/lib/CPP-Test)
add_subdirectory(src)
option(EXCLUDE_TESTS_FROM_ALL "Exclude examples, benchmarks and test suite from standard target." ON)
if(EXCLUDE_TESTS_FROM_ALL)
  add_subdirectory(examples EXCLUDE_FROM_ALL)
  add_subdirectory(benchmarks EXCLUDE_FROM_ALL)
  add_subdirectory(test EXCLUDE_FROM_ALL)
else()
  add_subdirectory(examples)
  add_subdirectory(benchmarks)
  add_subdirectory(test)
endif()

option(BUILD_PYTHON "Build python extensions for OpenANN" ON)
if(BUILD_PYTHON)
  add_subdirectory(python)
endif()

install(DIRECTORY OpenANN DESTINATION include)

option(ALWAYS_BUILD_DOCUMENTATION "Always build OpenANN documentation using doxygen." OFF)
if(DOXYGEN_FOUND)
  if(DOXYGEN_DOT_FOUND)
    set(OPENANN_USE_DOT "YES")
  else()
    set(OPENANN_USE_DOT "NO")
  endif()
  file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/html)
  configure_file(doxygen.cfg.in ${PROJECT_SOURCE_DIR}/doxygen.cfg)
  if(ALWAYS_BUILD_DOCUMENTATION)
    add_documentation(openann_doc doxygen.cfg ADD_TO_ALL)
  else()
    add_documentation(openann_doc doxygen.cfg)
  endif()
  install_documentation(${PROJECT_BINARY_DIR}/html openann)
endif()

configure_file(openann.pc.in openann.pc @ONLY)
string(REPLACE ":" ";" pkg_target_search "$ENV{PKG_CONFIG_LIBDIR}")
find_path(pkg_target_dir "pkgconfig" ${pkg_target_search} "${CMAKE_INSTALL_PREFIX}/share" ${pkg_target_search})
if(NOT pkg_target_dir)
  set(pkg_target_dir "lib")
endif()
install(FILES "${PROJECT_BINARY_DIR}/openann.pc" DESTINATION "${pkg_target_dir}/pkgconfig")

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Alexander Fabisch <afabisch@googlemail.com>")
set(CPACK_PACKAGE_VERSION ${OPENANN_VERSION_NUMBER})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${OPENANN_BRIEF_DESCRIPTION})
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libeigen3-dev (>= 3.0.0)")
include(CPack)
