#
# libflounder
#
# Dependencies:
#  * boost
#  * lapack
#  * cholmod
#  * ulapack
#  * libplankton
#
PROJECT(libflounder)

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

set(LIBFLOUNDER_VERSION 20160830.0.0)

#--------------------------------#
# Enforce an out-of-source build #
#--------------------------------#

STRING(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" INSOURCE)
IF(INSOURCE)
  MESSAGE(FATAL_ERROR "This project requires an out of source build. This is handled by the Makefile. Please type 'make'.")
ENDIF(INSOURCE)


#--------------------------------#
# Build Options                  #
#--------------------------------#

# this gets CMake to use the system triplet (x86_64-linux-gnu)
# for library locations
INCLUDE(GNUInstallDirs)

# Options can be set from the command line when running cmake.
#   eg. cmake . -DCMAKE_BUILD_TYPE=Release -DDEBUG_PROFILING=on
    
# Build types are: Release, Debug, RelWithDebInfo, MinSizeRel
IF( NOT CMAKE_BUILD_TYPE )
  SET( CMAKE_BUILD_TYPE Release CACHE STRING
       "Build type options are: None Debug Release RelWithDebInfo MinSizeRel."
       FORCE )
ENDIF( NOT CMAKE_BUILD_TYPE )


OPTION( DEBUG_OUTPUT
        "Enable debug printing such as function call traces."
        OFF )
        
OPTION( DEBUG_PROFILING
        "Enable debug profiling and timing code."
        OFF )
        
IF( NOT CHOLMOD_PREFIX )
   SET( CHOLMOD_PREFIX /usr/local/src/SuiteSparse CACHE PATH "CHOLMOD location")
ENDIF( NOT CHOLMOD_PREFIX )

#-----------------------#
# Dependencies          #
#-----------------------#

# Boost 
FIND_PACKAGE(Boost)
IF( NOT Boost_FOUND )
   MESSAGE( FATAL_ERROR  "ERROR - Can't find boost" )
ENDIF( NOT Boost_FOUND )      

# lapack
FIND_PACKAGE(LAPACK REQUIRED)
IF( NOT LAPACK_FOUND )
   MESSAGE( FATAL_ERROR  "ERROR - Can't find lapack" )
ENDIF( NOT LAPACK_FOUND )

# ulapack 
INCLUDE(CheckIncludeFileCXX)
CHECK_INCLUDE_FILE_CXX( "ulapack/matrix_types.hpp" HAVE_ULAPACK)
IF( NOT HAVE_ULAPACK )
   MESSAGE( FATAL_ERROR  "ERROR - Can't find ulapack" )
ENDIF( NOT HAVE_ULAPACK )      

# libplankton 
FIND_PACKAGE(LibPlankton REQUIRED)
IF( NOT LibPlankton_FOUND )
   MESSAGE( FATAL_ERROR  "ERROR - Can't find libplankton" )
ENDIF( NOT LibPlankton_FOUND )


# cholmod - see if it has been compiled with additional ordering functions
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
FIND_PACKAGE(Cholmod REQUIRED)
SET( CMAKE_REQUIRED_LIBRARIES ${CHOLMOD_LIB} )
INCLUDE(CheckFunctionExists)
CHECK_FUNCTION_EXISTS( cholmod_metis             HAVE_CHOLMOD_METIS  )
CHECK_FUNCTION_EXISTS( cholmod_nested_dissection HAVE_CHOLMOD_NESDIS )
CHECK_FUNCTION_EXISTS( cholmod_camd              HAVE_CHOLMOD_CAMD   )


#-----------------------#
# Compiler setup        #
#-----------------------#

ADD_DEFINITIONS( "-Wall" )

# Debug definitions
IF( DEBUG_OUTPUT )
   ADD_DEFINITIONS( -DDEBUG_OUTPUT )
ENDIF( DEBUG_OUTPUT )
IF( DEBUG_PROFILING )
   ADD_DEFINITIONS( -DDEBUG_TIMING )
ENDIF( DEBUG_PROFILING )

# Cholmod definitions
IF( HAVE_CHOLMOD_METIS )
   ADD_DEFINITIONS( -DHAVE_CHOLMOD_METIS )
ENDIF( HAVE_CHOLMOD_METIS )
IF( HAVE_CHOLMOD_NESDIS )
   ADD_DEFINITIONS( -DHAVE_CHOLMOD_NESDIS )
ENDIF( HAVE_CHOLMOD_NESDIS )
IF( HAVE_CHOLMOD_CAMD )
   ADD_DEFINITIONS( -DHAVE_CHOLMOD_CAMD )
ENDIF( HAVE_CHOLMOD_CAMD )


INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include
                     ${CHOLMOD_INCLUDE_DIR}
                     ${Boost_INCLUDE_DIR} )

LINK_DIRECTORIES( ${CHOLMOD_LINK_DIRS} )


#-----------------------#
# Print Some Info       #
#-----------------------#

MESSAGE( "" )
MESSAGE( "CONFIGURATION SUMMARY" )
MESSAGE( "---------------------" )
MESSAGE( "" )
MESSAGE( "CMAKE_BUILD_TYPE = '${CMAKE_BUILD_TYPE}'" )
MESSAGE( "" )
MESSAGE( "CMAKE_INSTALL_PREFIX = '${CMAKE_INSTALL_PREFIX}'" )
MESSAGE( "" )
MESSAGE( "DEBUG_OUTPUT    = '${DEBUG_OUTPUT}'" )
MESSAGE( "DEBUG_PROFILING = '${DEBUG_PROFILING}'" )
MESSAGE( "" )
MESSAGE( "CHOLMOD_PREFIX = '${CHOLMOD_PREFIX}'" )
MESSAGE( "" )
MESSAGE( "HAVE_CHOLMOD_METIS  = '${HAVE_CHOLMOD_METIS}'" )
MESSAGE( "HAVE_CHOLMOD_NESDIS = '${HAVE_CHOLMOD_NESDIS}'" )
MESSAGE( "HAVE_CHOLMOD_CAMD   = '${HAVE_CHOLMOD_CAMD}'" )
MESSAGE( "" )

IF( CMAKE_BUILD_TYPE STREQUAL Debug )
   MESSAGE( "CMAKE_CXX_FLAGS_DEBUG = '${CMAKE_CXX_FLAGS_DEBUG}'" )
ENDIF( CMAKE_BUILD_TYPE STREQUAL Debug )

IF( CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo )
   MESSAGE( "CMAKE_CXX_FLAGS_RELWITHDEBINFO = '${CMAKE_CXX_FLAGS_RELWITHDEBINFO}'" )
ENDIF( CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo )

IF( CMAKE_BUILD_TYPE STREQUAL Release )
   MESSAGE( "CMAKE_CXX_FLAGS_RELEASE = '${CMAKE_CXX_FLAGS_RELEASE}'" )
ENDIF( CMAKE_BUILD_TYPE STREQUAL Release )

IF( CMAKE_BUILD_TYPE STREQUAL MinSizeRel )
   MESSAGE( "CMAKE_CXX_FLAGS_MINSIZEREL = '${CMAKE_CXX_FLAGS_MINSIZEREL}'" )
ENDIF( CMAKE_BUILD_TYPE STREQUAL MinSizeRel )

MESSAGE( "" )

#-----------------------#
# Build Instructions    #
#-----------------------#

# Locations for the library and binary files
SET( LIBRARY_OUTPUT_PATH     ${PROJECT_SOURCE_DIR}/lib )
SET( EXECUTABLE_OUTPUT_PATH  ${PROJECT_SOURCE_DIR}/bin )

ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(tests)


#-----------------------#
# Testing Instructions  #
#-----------------------#

ENABLE_TESTING( )
ADD_TEST( feature_add_remove_test ${EXECUTABLE_OUTPUT_PATH}/pose_add_remove_test    ${PROJECT_SOURCE_DIR}/test_data/seabed_slam.cfg )
ADD_TEST( pose_add_remove_test    ${EXECUTABLE_OUTPUT_PATH}/pose_add_remove_test    ${PROJECT_SOURCE_DIR}/test_data/seabed_slam.cfg )
ADD_TEST( seabed_predict_test     ${EXECUTABLE_OUTPUT_PATH}/seabed_predict_test     ${PROJECT_SOURCE_DIR}/test_data/seabed_slam.cfg )
ADD_TEST( seabed_dead_reckon_test ${EXECUTABLE_OUTPUT_PATH}/seabed_dead_reckon_test ${PROJECT_SOURCE_DIR}/test_data/seabed_slam.cfg )
ADD_TEST( load_save_test          ${EXECUTABLE_OUTPUT_PATH}/load_save_test          ${PROJECT_SOURCE_DIR}/test_data/seabed_slam.cfg )
ADD_TEST( seabed_eif_slam_test    ${EXECUTABLE_OUTPUT_PATH}/seabed_eif_slam_test    ${PROJECT_SOURCE_DIR}/test_data/seabed_slam.cfg )
ADD_TEST( seabed_rel_pose_test    ${EXECUTABLE_OUTPUT_PATH}/seabed_rel_pose_test    ${PROJECT_SOURCE_DIR}/test_data/seabed_slam.cfg )
ADD_TEST( marginalisation_test    ${EXECUTABLE_OUTPUT_PATH}/marginalisation_test    ${PROJECT_SOURCE_DIR}/test_data/seabed_slam.cfg )
ADD_TEST( cholesky_test           ${EXECUTABLE_OUTPUT_PATH}/cholesky_test )
ADD_TEST( takahashi_test          ${EXECUTABLE_OUTPUT_PATH}/takahashi_test ${PROJECT_SOURCE_DIR}/test_data/Y.data )

#-----------------------#
# Installation Related  #
#-----------------------#

INCLUDE(CMakePackageConfigHelpers)
WRITE_BASIC_PACKAGE_VERSION_FILE(
    "${CMAKE_CURRENT_BINARY_DIR}/LibFlounder/LibFlounderConfigVersion.cmake"
    VERSION ${LIBFLOUNDER_VERSION}
    COMPATIBILITY AnyNewerVersion
)

IF(CMAKE_VERSION VERSION_LESS "3.0")
    EXPORT(TARGETS flounder
        FILE "${CMAKE_CURRENT_BINARY_DIR}/LibFlounder/LibFlounderTargets.cmake"
        NAMESPACE libflounder::
    )
ELSE()
    EXPORT(EXPORT LibFlounderTargets
        FILE "${CMAKE_CURRENT_BINARY_DIR}/LibFlounder/LibFlounderTargets.cmake"
        NAMESPACE libflounder::
    )
ENDIF()

CONFIGURE_FILE(cmake/LibFlounderConfig.cmake
    "${CMAKE_CURRENT_BINARY_DIR}/LibFlounder/LibFlounderConfig.cmake"
    COPYONLY
)

set(ConfigPackageLocation lib/cmake/LibFlounder)
install(EXPORT LibFlounderTargets
    FILE LibFlounderTargets.cmake
    NAMESPACE libflounder::
    DESTINATION ${ConfigPackageLocation}
)
install(
    FILES cmake/LibFlounderConfig.cmake
    "${CMAKE_CURRENT_BINARY_DIR}/LibFlounder/LibFlounderConfigVersion.cmake"
    DESTINATION "${ConfigPackageLocation}"
)
