cmake_minimum_required(VERSION 2.6)
project(chflow)

# Install prefix is set with 'cmake -DCMAKE_INSTALL_PREFIX=...'

# Option to set a path where to look for fftw3 (set via 'cmake -DWITH_FFTW=...')
OPTION(WITH_FFTW "Specify path to fftw3" ON)
OPTION(WITH_HDF5 "Specify path to hdf5"  ON)
OPTION(WITH_EIGEN3 "Specify path to eigen3"  ON)

set (chflow_version_major 1)
set (chflow_version_minor 5)
set (chflow_version_patch 1)
set (PACKAGE_VERSION ${chflow_version_major}.${chflow_version_minor}.${chflow_version_patch})

# Echo an empty line and channelflow version
message("")
message(STATUS "configuring channelflow version " ${chflow_version_major} . ${chflow_version_minor} . ${chflow_version_patch})

# Handle build type (set via 'cmake -DCMAKE_BUILD_TYPE=...')
if(NOT CMAKE_BUILD_TYPE)
	set(CMAKE_BUILD_TYPE Release)
endif()

# Set compiler flags. If you have link errors with undefined references to functions that
# are definitely in the libraries (e.g. undefined reference to H5::Attribute::getName() const)
# you might be running into changes in the C++ ABI, say having compiled channelflow with C++11 ABI
# but linking to HDF5 libs compiled with C++03 ABI. Try adding -D_GLIBCXX_USE_CXX11_ABI=0 to
# the add_definitions(...) for C flags immediately below. 

string(TOLOWER ${CMAKE_BUILD_TYPE} BUILD_TYPE)
message(STATUS "Build type: ${BUILD_TYPE}")
if(BUILD_TYPE STREQUAL release)
	add_definitions (-Wall -fomit-frame-pointer -DNDEBUG)
elseif(BUILD_TYPE STREQUAL debug)
	add_definitions (-Wall -fno-inline -g)
elseif(BUILD_TYPE STREQUAL profile)
	add_definitions (-Wall -pg -DDEBUG)
else()
	message("Unknown build type ${CMAKE_BUILD_TYPE}")
endif()


# Set some include and link directories
include_directories ( ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR} )
link_directories ( ${PROJECT_BINARY_DIR}/channelflow ${PROJECT_BINARY_DIR} ) 

# RPATH settings
# From: http://www.itk.org/Wiki/CMake_RPATH_handling
SET(CMAKE_SKIP_BUILD_RPATH  FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
IF("${isSystemDir}" STREQUAL "-1")
   SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
ENDIF("${isSystemDir}" STREQUAL "-1")


####### Some basic system introspection: type sizes,  ########
message(STATUS "Basic system introspection...")

include (CheckTypeSize)
CHECK_TYPE_SIZE(int SIZEOF_INT) 
CHECK_TYPE_SIZE(double SIZEOF_DOUBLE)

include (CheckLibraryExists)
include (CheckFunctionExists)

CHECK_FUNCTION_EXISTS(drand48 HAVE_DRAND48)



####### Package finding, generics######################################
message(STATUS "Finding packages...")
message("")
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")


######## FFTW  ################
find_package(FFTW REQUIRED)

message(STATUS "Adding ${FFTW_INCLUDE_DIR} to include path...")
include_directories(BEFORE SYSTEM ${FFTW_INCLUDE_DIR})

message(STATUS "Adding ${FFTW_LIBRARY} to libraries...")
set(LIBS ${LIBS} ${FFTW_LIBRARY})



######## Eigen3 ################
find_package(EIGEN3 REQUIRED)

# (note that eigen is a header-only package, so it doesn't need adding to library path)
message(STATUS "Adding ${EIGEN3_INCLUDE_DIR} to include path...")
include_directories(BEFORE SYSTEM ${EIGEN3_INCLUDE_DIR})




######## HDF5  ################
find_package(HDF5 COMPONENTS CXX)

if(HDF5_FOUND)
  message(STATUS "Adding ${HDF5_INCLUDE_DIR} to include directories...")
  include_directories(BEFORE SYSTEM ${HDF5_INCLUDE_DIR})

  message(STATUS "Adding ${HDF5_LIBRARY} to libraries...")
  set(LIBS ${LIBS} ${HDF5_LIBRARY})

  set(CMAKE_REQUIRED_LIBRARIES hdf5) 
  set(CMAKE_REQUIRED_LIBRARIES hdf5_cpp)
  
  # This kludge is required to fix the fact that find_package(hdf5) sets
  # HDF5_LIBRARY to only <path>/libhdf5.so, whereas libhdf5_cpp.so is needed

  # Unfortunately CHECK_LIBRARY_EXISTS doesn't work for C++ due to name mangling
  # so we just go ahead and assume libhdf5_cpp.so exists. 

  get_filename_component(HDF5_LIBDIR ${HDF5_LIBRARY} PATH)

  message(STATUS "Adding ${HDF5_LIBDIR}/libhdf5_cpp.so to libraries...")
  set(LIBS ${LIBS} ${HDF5_LIBDIR}/libhdf5_cpp.so)

  # would like to enclose above in a check and if(...)
  # CHECK_LIBRARY_EXISTS(hdf5_cpp H5Eprint2 ${HDF5_LIBDIR} HAVE_LIBHDF5_CPP) 
  # if(HAVE_LIBHDF5_CPP)  
  #   
  # 
  # endif()

  # For some reason, user-compiled HDF5 requires these libs, whereas
  # typical linux package HDF5 does not. Go figure.

  CHECK_LIBRARY_EXISTS(z gzopen ${HDF5_LIBDIR} HAVE_LIBZ) 
  if(HAVE_LIBZ)
    message(STATUS "Adding ${HDF5_LIBDIR}/libz.so to libraries...")
    set(LIBS ${LIBS} ${HDF5_LIBDIR}/libz.so)
  endif()

  CHECK_LIBRARY_EXISTS(szip szip_compress_memory ${HDF5_LIBDIR} HAVE_LIBSZIP) 
  if(HAVE_LIBSZIP)
    message(STATUS "Adding ${HDF5_LIBDIR}/libszip.so to libraries...")
    set(LIBS ${LIBS} ${HDF5_LIBDIR}/libszip.so)
  endif()

endif()


message(STATUS "LIBS=${LIBS}")
message(STATUS "INCLUDE_DIRS=${INCLUDE_DIRS}")


# Create config.h from config.h.in
configure_file( "${PROJECT_SOURCE_DIR}/config.h.in"
                "${PROJECT_BINARY_DIR}/config.h" )




####### Compilation ########
message("")

# compile libchflow (shared and static)
add_subdirectory(channelflow) 

set(chflowlib chflow)

add_subdirectory(programs)
add_subdirectory(examples)


####### Testing ########
ENABLE_TESTING()
add_subdirectory(tests)

####### Installation #######
install(DIRECTORY "${PROJECT_SOURCE_DIR}/data/" DESTINATION "data")


######## Packaging ########
# allows creating distribution package with 'make package_source'
set(CPACK_PACKAGE_VERSION_MAJOR ${chflow_version_major})
set(CPACK_PACKAGE_VERSION_MINOR ${chflow_version_minor})
set(CPACK_PACKAGE_VERSION_PATCH ${chflow_version_patch})
set(CPACK_GENERATOR TGZ RPM DEB)
set(CPACK_PACKAGE_NAME channelflow)
set(CPACK_PACKAGE_CONTACT "john.gibson@unh.edu")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A spectral Navier-Stokes simulator in C++")

set(CPACK_SOURCE_PACKAGE_FILE_NAME channelflow-devel-${chflow_version_major}.${chflow_version_minor}.${chflow_version_patch})
set(CPACK_PACKAGE_FILE_NAME channelflow-${chflow_version_major}.${chflow_version_minor}.${chflow_version_patch})
set(CPACK_SOURCE_GENERATOR TGZ RPM DEB)

add_subdirectory(data)
set(CPACK_SOURCE_IGNORE_FILES "/build/" "~$" "obsolete") 


include(CPack)