cmake_minimum_required ( VERSION 2.8 )

option ( BUILD_PYTHON                 "Build the python module for the library"                               ON )
option ( BUILD_DOC                    "Build the documentation"                                               ON )
option ( LINK_PYTHON_LIBRARY          "Link python modules against python library"                            ON )
option ( INSTALL_TESTS                "Install compiled tests for native platform testing"                    OFF )
option ( BUILD_SHARED_LIBS            "Build shared libraries"                                                ON )
option ( USE_SYSTEM_FFTW              "Use system FFTW libraries"                                             ON )

# By default, build in Release mode. Must appear before project() command
if ( NOT DEFINED CMAKE_BUILD_TYPE )
   set( CMAKE_BUILD_TYPE Release CACHE STRING "Build type")
endif ()

project ( otfftw CXX )

string ( TOLOWER ${CMAKE_PROJECT_NAME} PACKAGE_NAME )

# set module dir to find custom scripts
list ( APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake )

find_package ( OpenTURNS NO_MODULE REQUIRED )
include ( ${OPENTURNS_USE_FILE} )
set ( OTFFTW_DEFINITIONS ${OPENTURNS_DEFINITIONS} )
if (NOT BUILD_SHARED_LIBS)
  list ( APPEND OTFFTW_DEFINITIONS "-DOTFFTW_STATIC" )
endif ()
add_definitions ( ${OTFFTW_DEFINITIONS} )

set ( OTFFTW_LIBRARY_PATH lib${LIB_SUFFIX} )
set ( OTFFTW_INCLUDE_PATH include/${PACKAGE_NAME} )
set ( OTFFTW_SWIG_INCLUDE_PATH ${OTFFTW_INCLUDE_PATH}/swig )
set ( OTFFTW_DATA_PATH share )
set ( OTFFTW_EXAMPLE_PATH ${OTFFTW_DATA_PATH}/${PACKAGE_NAME}/examples )
set ( OTFFTW_CONFIG_CMAKE_PATH lib${LIB_SUFFIX}/cmake/otfftw )
set ( DOC_INSTALL_PATH share/doc/${PACKAGE_NAME} )

if ( BUILD_PYTHON )
  # workaround for cmake bug #0013449
  if ( NOT DEFINED CMAKE_FIND_ROOT_PATH )
    find_package ( SWIG )
  else ()
    find_program ( SWIG_EXECUTABLE NAMES swig2.0 swig )
    if ( SWIG_EXECUTABLE )
      set ( SWIG_USE_FILE ${CMAKE_ROOT}/Modules/UseSWIG.cmake )
      set ( SWIG_FOUND TRUE )
    endif ()
  endif ()
  find_package ( PythonInterp )
  find_package ( PythonLibs )

  if ( PYTHONINTERP_FOUND )
    execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; print(sysconfig.get_python_lib(plat_specific=True, prefix='${CMAKE_INSTALL_PREFIX}'))"
                      OUTPUT_VARIABLE _ABS_PYTHON_MODULE_PATH
                      RESULT_VARIABLE _PYTHON_pythonlib_result 
                      OUTPUT_STRIP_TRAILING_WHITESPACE )

    if (NOT _PYTHON_pythonlib_result) 
      get_filename_component ( _ABS_PYTHON_MODULE_PATH ${_ABS_PYTHON_MODULE_PATH} ABSOLUTE )
      file ( RELATIVE_PATH _REL_PYTHON_MODULE_PATH ${CMAKE_INSTALL_PREFIX} ${_ABS_PYTHON_MODULE_PATH} )                   

      set (OTFFTW_PYTHON_MODULE_PATH ${_REL_PYTHON_MODULE_PATH})

    else ()
      message ( SEND_ERROR "Could not run ${PYTHON_EXECUTABLE}" ) 
    endif ()

    if (CMAKE_VERSION VERSION_LESS "2.8.6")
      execute_process (COMMAND ${PYTHON_EXECUTABLE} -c "import sys; print(sys.version_info[0])"
                       OUTPUT_VARIABLE PYTHON_VERSION_MAJOR
                       OUTPUT_STRIP_TRAILING_WHITESPACE)
    endif ()
    set (OTFFTW_PYTHON${PYTHON_VERSION_MAJOR}_MODULE_PATH ${OTFFTW_PYTHON_MODULE_PATH})
  endif ( PYTHONINTERP_FOUND )
endif ()


# WARNING: This is where variables without OPENTURNS_ prefix are defined !
foreach ( _var PYTHON_MODULE_PATH LIBRARY_PATH INCLUDE_PATH CONFIG_CMAKE_PATH)
  if ( NOT IS_ABSOLUTE OTFFTW_${_var} )
    set ( OTFFTW_${_var} ${CMAKE_INSTALL_PREFIX}/${OTFFTW_${_var}} )
  endif ()
  set ( ${_var} ${OTFFTW_${_var}} )
endforeach ( _var )

# RPATH settings
set (CMAKE_INSTALL_RPATH ${LIBRARY_PATH} ${CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES})
set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if(POLICY CMP0042)
  # Set MACOSX_RPATH to ON
  cmake_policy(SET CMP0042 NEW)
endif()

# Some useful macros to ease CMakeLists.txt file writing
set ( SOURCEFILES "" CACHE INTERNAL "List of source files to compile" )
macro ( ot_add_source_file FILENAME )
  set ( sf ${SOURCEFILES} ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME} )
  set ( SOURCEFILES ${sf} CACHE INTERNAL "List of source files to compile" )
endmacro ( ot_add_source_file )

set ( HEADERFILES "" CACHE INTERNAL "List of header files to install" )
macro ( ot_install_header_file FILENAME )
  set ( hf ${HEADERFILES} ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME} )
  set ( HEADERFILES ${hf} CACHE INTERNAL "List of header files to install" )
endmacro ( ot_install_header_file )

set ( SWIGFILES "" CACHE INTERNAL "List of SWIG files to install" )
macro ( ot_install_swig_file FILENAME )
  set ( hf ${SWIGFILES} ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME} )
  set ( SWIGFILES ${hf} CACHE INTERNAL "List of SWIG files to install" )
endmacro ( ot_install_swig_file )

set ( INTERNAL_INCLUDE_DIRS "" CACHE INTERNAL "List of directories with header files needed for build" )
macro ( ot_add_current_dir_to_include_dirs )
  set ( inc_dirs ${INTERNAL_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} )
  set ( INTERNAL_INCLUDE_DIRS ${inc_dirs} CACHE INTERNAL "List of directories with header files needed for build" )
endmacro ( ot_add_current_dir_to_include_dirs )

if ( USE_SYSTEM_FFTW )
  find_package ( FFTW REQUIRED )
endif ()
if ( NOT FFTW_FOUND )
  include ( ExternalProject )
  set ( FFTW_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/fftw-prefix )
  ExternalProject_Add ( fftw
    URL ${CMAKE_CURRENT_SOURCE_DIR}/externals/fftw-3.3.4.tar.gz
    URL_MD5 2edab8c06b24feeb3b82bbb3ebf3e7b3
    PATCH_COMMAND patch --verbose -p1 -t -N < ${CMAKE_CURRENT_SOURCE_DIR}/externals/patch_no_mpi_no_doc
    CONFIGURE_COMMAND ${CMAKE_CURRENT_BINARY_DIR}/fftw-prefix/src/fftw/configure
      --prefix=${FFTW_PREFIX}
      --disable-shared
      --enable-sse2
      --disable-openmp
      --disable-threads
      "CFLAGS=-g -O3 -mtune=native -march=native -fPIC"
  )
  set ( FFTW_LIBRARIES ${FFTW_PREFIX}/lib/libfftw3.a )
  set ( FFTW_INCLUDE_DIRS ${FFTW_PREFIX}/include )
endif ()
list ( APPEND OTFFTW_INCLUDE_DIRS ${FFTW_INCLUDE_DIRS} )
list ( APPEND OTFFTW_LIBRARIES ${FFTW_LIBRARIES} )
list ( APPEND OTFFTW_LIBRARY_DIRS ${FFTW_LIBRARY_DIRS} )
include_directories(${FFTW_INCLUDE_DIRS})

# The tests can't be run if this function is absent
enable_testing ()
add_custom_target ( tests COMMENT "Build tests" )
add_custom_target ( check COMMENT "Run pre-installation tests" )
add_custom_target ( installcheck COMMENT "Run post-installation tests" )

add_subdirectory ( lib )
add_dependencies ( check cppcheck )

if ( PYTHONINTERP_FOUND AND PYTHONLIBS_FOUND AND SWIG_FOUND AND BUILD_SHARED_LIBS )
  add_subdirectory ( python )
  add_dependencies ( installcheck pyinstallcheck )
endif ()

set ( CPACK_PACKAGE_NAME          ${PACKAGE_NAME} )
set ( CPACK_PACKAGE_VERSION_MAJOR 0              )
set ( CPACK_PACKAGE_VERSION_MINOR 4              )
set ( CPACK_PACKAGE_VERSION_PATCH                )
set ( CPACK_SOURCE_GENERATOR      "TGZ;TBZ2"     )
set ( CPACK_BINARY_STGZ           "OFF"          )
set ( CPACK_BINARY_TBZ2           "ON"           )
set ( CPACK_BINARY_TGZ            "ON"           )
set ( CPACK_BINARY_TZ             "OFF"          )
set ( CPACK_SOURCE_IGNORE_FILES "/.svn;/build;.*~;${CPACK_SOURCE_IGNORE_FILES}" )
set ( PACKAGE_NAME           ${CPACK_PACKAGE_NAME} )
set ( PACKAGE_VERSION        ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR} )
if ( CPACK_PACKAGE_VERSION_PATCH )
  set ( PACKAGE_VERSION       ${PACKAGE_VERSION}.${CPACK_PACKAGE_VERSION_PATCH} )
endif ()
set ( CPACK_SOURCE_PACKAGE_FILE_NAME ${PACKAGE_NAME}-${PACKAGE_VERSION} )
include ( CPack )

# uninstall target
configure_file (
  ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in
  ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
  IMMEDIATE @ONLY
)

add_custom_target ( uninstall
  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
)

if ( BUILD_DOC )
  add_subdirectory ( doc )
endif ()

set ( OTFFTW_LIBRARY                 otfftw )
set ( OTFFTW_LIBRARIES ${OPENTURNS_LIBRARIES} )
list ( APPEND OTFFTW_LIBRARIES ${OTFFTW_LIBRARY} )
set ( OTFFTW_LIBRARY_DIRS ${OPENTURNS_LIBRARY_DIRS} )
list ( APPEND OTFFTW_LIBRARY_DIRS ${LIBRARY_PATH} )
set ( OTFFTW_INCLUDE_DIR ${OTFFTW_INCLUDE_PATH} )
set ( OTFFTW_INCLUDE_DIRS ${OTFFTW_INCLUDE_DIR} )
set ( OTFFTW_ROOT_DIR       ${CMAKE_INSTALL_PREFIX} )
list ( APPEND OTFFTW_INCLUDE_DIRS ${OPENTURNS_INCLUDE_DIRS} )
set ( OTFFTW_VERSION_STRING ${PACKAGE_VERSION} )
set ( OTFFTW_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR} )
set ( OTFFTW_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR} )
set ( OTFFTW_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH} )
set ( OTFFTW_USE_FILE      ${OTFFTW_CONFIG_CMAKE_PATH}/Useotfftw.cmake )
configure_file ( ${CMAKE_SOURCE_DIR}/cmake/otfftwConfig.cmake.in
                 ${CMAKE_BINARY_DIR}/otfftwConfig.cmake
     @ONLY ESCAPE_QUOTES
               )
install ( FILES ${CMAKE_BINARY_DIR}/otfftwConfig.cmake cmake/Useotfftw.cmake
          DESTINATION ${OTFFTW_CONFIG_CMAKE_PATH}
        )

