#                                               -*- cmake -*-
#
#  CMakeLists.txt
#
#  (C) Copyright 2005-2012 EDF-EADS-Phimeca
#
#  This library is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2.1 of the License.
#
#  This library is distributed in the hope that it will be useful
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
#
#  @author: $LastChangedBy: dutka $
#  @date:   $LastChangedDate: 2010-02-04 16:44:49 +0100 (Thu, 04 Feb 2010) $
#  Id:      $Id: Makefile.am 1473 2010-02-04 15:44:49Z dutka $
#

cmake_minimum_required ( VERSION 2.8 )

project ( OpenTURNS CXX C Fortran )

option ( USE_BISON "Looks for Bison if true and then build parser" ON )
option ( USE_FLEX  "Looks for Flex if true and then build lexer" ON )
option ( USE_TBB   "Use Intel Threading Building Blocks library for multithreading" ON )

# Defines our own module path
set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules" ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY} )

# Find system prerequisites
include ( CMakeDetermineCXXCompiler )
include ( CMakeDetermineCCompiler )
include ( CMakeDetermineFortranCompiler )
include ( CMakeTestFortranCompiler )
include ( CheckIncludeFile )
include ( CMakeFortranCompiler )

if ( USE_BISON )
  find_package ( BISON REQUIRED )
endif ( USE_BISON )

if ( USE_FLEX )
  find_package ( FLEX REQUIRED )
endif ( USE_FLEX )

if ( USE_TBB )
  find_package ( TBB )
endif ()

find_package ( BLAS )
find_package ( LAPACK )
find_package ( Doxygen )
find_package ( LibXml2 )
find_package ( Threads )
find_package ( Libdl )
find_package ( Regex )
find_package ( R COMPONENTS base rotRPackage REQUIRED )

find_program ( RM_EXECUTABLE
               NAMES rm rem del delete
	       DOC "Path to the system remove command"
	     )
mark_as_advanced ( RM_EXECUTABLE )
check_include_file ( arpa/inet.h   HAVE_ARPA_INET_H   )
check_include_file ( assert.h      HAVE_ASSERT_H      )
check_include_file ( dirent.h      HAVE_DIRENT_H      )
check_include_file ( errno.h       HAVE_ERRNO_H       )
check_include_file ( inttypes.h    HAVE_INTTYPES_H    )
check_include_file ( math.h        HAVE_MATH_H        )
check_include_file ( netdb.h       HAVE_NETDB_H       )
check_include_file ( netinet/in.h  HAVE_NETINET_IN_H  )
check_include_file ( netinet/tcp.h HAVE_NETINET_TCP_H )
check_include_file ( pthread.h     HAVE_PTHREAD_H     )
check_include_file ( regex.h       HAVE_REGEX_H       )
check_include_file ( semaphore.h   HAVE_SEMAPHORE_H   )
check_include_file ( signal.h      HAVE_SIGNAL_H      )
check_include_file ( stdbool.h     HAVE_STDBOOL_H     )
check_include_file ( stdint.h      HAVE_STDINT_H      )
check_include_file ( stdlib.h      HAVE_STDLIB_H      )
check_include_file ( string.h      HAVE_STRING_H      )
check_include_file ( strings.h     HAVE_STRINGS_H     )
check_include_file ( sys/socket.h  HAVE_SYS_SOCKET_H  )
check_include_file ( sys/stat.h    HAVE_SYS_STAT_H    )
check_include_file ( sys/time.h    HAVE_SYS_TIME_H    )
check_include_file ( sys/types.h   HAVE_SYS_TYPES_H   )
check_include_file ( sys/un.h      HAVE_SYS_UN_H      )
check_include_file ( unistd.h      HAVE_UNISTD_H      )


# 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 ( BUILT_SOURCEFILES "" CACHE INTERNAL "List of source files to compile" )
macro ( ot_add_built_source_file FILENAME )
  set ( sf ${BUILT_SOURCEFILES} ${FILENAME} )
  set ( BUILT_SOURCEFILES ${sf} CACHE INTERNAL "List of built source files to compile" )
endmacro ( ot_add_built_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 )
macro ( ot_add_build_dir_to_include_dirs DIR )
  set ( inc_dirs ${INTERNAL_INCLUDE_DIRS} ${DIR} )
  set ( INTERNAL_INCLUDE_DIRS ${inc_dirs} CACHE INTERNAL "List of directories with header files needed for build" )
endmacro ( ot_add_build_dir_to_include_dirs )


# Add definitions according to the prerequisites found
add_definitions ( -DHAVE_CONFIG_H )
if ( LIBXML2_FOUND )
  set ( HAVE_LIBXML2 TRUE )
  add_definitions ( ${LIBXML2_DEFINITIONS} )
  #include_directories ( ${LIBXML2_INCLUDE_DIR} )
  ot_add_build_dir_to_include_dirs ( ${LIBXML2_INCLUDE_DIR} )
  set ( OPENTURNS_DEFINITIONS ${OPENTURNS_DEFINITIONS} ${LIBXML2_DEFINITIONS} )
  set ( OPENTURNS_INCLUDE     ${OPENTURNS_INCLUDE}     ${LIBXML2_INCLUDE_DIR} )
endif ( LIBXML2_FOUND )


if ( Threads_FOUND )
  add_definitions ( -pthread )
endif ( Threads_FOUND )

if ( TBB_FOUND )
  set ( HAVE_TBB TRUE )
  set ( HAVE_TBB_TBB_H TRUE )
  include_directories ( ${TBB_INCLUDE_DIRS} )
endif ( TBB_FOUND )

if ( LIBDL_FOUND )
  set ( HAVE_LIBDL TRUE )
  include_directories ( ${LIBDL_INCLUDE_DIR} )
endif ( LIBDL_FOUND )

if ( REGEX_FOUND )
  set ( HAVE_REGEX TRUE )
  include_directories ( ${REGEX_INCLUDE_DIR} )
endif ( REGEX_FOUND )

set ( CPACK_PACKAGE_NAME          openturns      )
set ( CPACK_PACKAGE_VERSION_MAJOR 1              )
set ( CPACK_PACKAGE_VERSION_MINOR 0 )
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 ( CPACK_INSTALL_CMAKE_PROJECTS "lib;OpenTURNSLib;ALL;/" "python;OpenTURNSPython;ALL;/" )


# Set global definitions
# TODO: remove PACKAGE_<XX> from source code. Needed for compatibility with autotools
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 ( CPACK_PACKAGE_VERSION_PATCH )
set ( PACKAGE_BUGREPORT      bugs@openturns.org )
set( CPACK_SOURCE_PACKAGE_FILE_NAME ${PACKAGE_NAME}-${PACKAGE_VERSION} )

# uninstall target
configure_file (
  "${CMAKE_CURRENT_SOURCE_DIR}/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
)

# distcheck target
find_program( TAR_PROGRAM tar ) 
get_filename_component( BUILD_TOOL_NAME ${CMAKE_BUILD_TOOL} NAME )
if ( TAR_PROGRAM AND BUILD_TOOL_NAME MATCHES ".*make" )
  set ( DISTCHECK_BINARY_DIR ${CMAKE_BINARY_DIR}/${CPACK_SOURCE_PACKAGE_FILE_NAME}/_build )
  set ( DISTCHECK_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/${CPACK_SOURCE_PACKAGE_FILE_NAME}/_inst )
  add_custom_target ( distcheck 
    COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR} "$(MAKE)" package_source
    COMMAND ${CMAKE_COMMAND} -E remove_directory ${DISTCHECK_BINARY_DIR}
    COMMAND ${CMAKE_COMMAND} -E remove_directory ${DISTCHECK_INSTALL_PREFIX}
    COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR} ${TAR_PROGRAM} xvfz ${CMAKE_BINARY_DIR}/${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz
    COMMAND ${CMAKE_COMMAND} -E make_directory ${DISTCHECK_BINARY_DIR}
    COMMAND ${CMAKE_COMMAND} -E make_directory ${DISTCHECK_INSTALL_PREFIX}
    COMMAND ${CMAKE_COMMAND} -E chdir ${DISTCHECK_BINARY_DIR} ${CMAKE_COMMAND} .. -DCMAKE_INSTALL_PREFIX=${DISTCHECK_INSTALL_PREFIX}
    COMMAND ${CMAKE_COMMAND} -E chdir ${DISTCHECK_BINARY_DIR} "$(MAKE)"
    COMMAND ${CMAKE_COMMAND} -E chdir ${DISTCHECK_BINARY_DIR} "$(MAKE)" check
    COMMAND ${CMAKE_COMMAND} -E chdir ${DISTCHECK_BINARY_DIR} "$(MAKE)" install
    COMMAND ${CMAKE_COMMAND} -E chdir ${DISTCHECK_BINARY_DIR} "$(MAKE)" cppinstallcheck
    COMMAND ${CMAKE_COMMAND} -E chdir ${DISTCHECK_BINARY_DIR} "$(MAKE)" pyinstallcheck
    COMMAND ${CMAKE_COMMAND} -E chdir ${DISTCHECK_BINARY_DIR} "$(MAKE)" uninstall
    COMMAND ${CMAKE_COMMAND} -E chdir ${DISTCHECK_BINARY_DIR} "$(MAKE)" clean
  )
endif ()

set ( OPENTURNS_HOME_ENV_VAR OPENTURNS_HOME     )
set ( OPENTURNS_INSTALL_PATH
      ${CMAKE_INSTALL_PREFIX}
      CACHE PATH "The directory where Open TURNS is installed"
    )

# automatically set lib suffix
if ( UNIX AND NOT APPLE AND NOT CMAKE_CROSSCOMPILING AND NOT EXISTS "/etc/debian_version" )
  if ( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT LIB_SUFFIX )
    set ( LIB_SUFFIX 64 )
  endif ()
endif ()

set ( OPENTURNS_LIBRARY_PATH
      lib${LIB_SUFFIX}/openturns
      CACHE PATH "The directory where the library is installed"
    )
set ( OPENTURNS_INCLUDE_PATH
      include/openturns
      CACHE PATH "The directory where the header files are installed"
    )
set ( OPENTURNS_SYSCONFIG_PATH
      etc
      CACHE PATH "The directory where the configuration file is installed"
    )
set ( OPENTURNS_DATA_PATH
      share
      CACHE PATH "The directory where the common files are installed"
    )
set ( OPENTURNS_WRAPPER_PATH
      lib${LIB_SUFFIX}/openturns/wrappers
      CACHE PATH "The directory where the wrapper files are installed"
    )
set ( OPENTURNS_EXAMPLE_PATH
      share/openturns/examples
      CACHE PATH "The directory where the example files are installed"
    )
set ( OPENTURNS_SAMPLE_PATH
      share/openturns/examples
      CACHE PATH "The directory where the sample files are installed"
    )
set ( OPENTURNS_VALIDATION_PATH
      share/openturns/validation
      CACHE PATH "The directory where validation files are installed"
    )
set ( OPENTURNS_DOC_PATH
      share/openturns/doc
      CACHE PATH "The directory where the license files are installed"
    )
set ( OPENTURNS_TEMPDIR
      /tmp
      CACHE PATH "The directory for temporary files. /tmp by default."
    )

# WARNING: This is where variables without OPENTURNS_ prefix are defined !
foreach ( _var INSTALL_PATH LIBRARY_PATH INCLUDE_PATH SYSCONFIG_PATH DATA_PATH WRAPPER_PATH EXAMPLE_PATH SAMPLE_PATH VALIDATION_PATH DOC_PATH TEMPDIR )
  if ( IS_ABSOLUTE ${OPENTURNS_${_var}} )
    set(${_var} ${OPENTURNS_${_var}})
  else ( IS_ABSOLUTE ${OPENTURNS_${_var}} )
    set(${_var} ${OPENTURNS_INSTALL_PATH}/${OPENTURNS_${_var}})
  endif ( IS_ABSOLUTE ${OPENTURNS_${_var}} )
endforeach ( _var )

# Selectively add or remove RPATH from executable
set ( OPENTURNS_SYSTEM_INSTALL OFF CACHE BOOL "True if Open TURNS is installed in a system directory. RPATH removed. False by default." )
if ( NOT OPENTURNS_SYSTEM_INSTALL )
  set ( CMAKE_INSTALL_RPATH ${LIBRARY_PATH}
                            ${CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES}
      )
  set ( CMAKE_BUILD_WITH_INSTALL_RPATH    TRUE )
  set ( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE )
endif ( NOT OPENTURNS_SYSTEM_INSTALL )


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

# Recurse in subdirectories
add_subdirectory ( utils )
add_subdirectory ( wrappers )

add_definitions ( -fPIC -DPIC )


set ( OPENTURNS_BUILD_LIB ON CACHE BOOL "Build the library" )
if ( OPENTURNS_BUILD_LIB )
  add_subdirectory ( lib )
  add_dependencies ( check cppcheck )
  add_dependencies ( installcheck cppinstallcheck )
endif ( OPENTURNS_BUILD_LIB )


set ( OPENTURNS_BUILD_PYTHON ON CACHE BOOL "Build the python module for the library" )
if ( OPENTURNS_BUILD_PYTHON )
  find_package ( SWIG REQUIRED )
  include ( ${SWIG_USE_FILE} )
  mark_as_advanced ( SWIG_VERSION SWIG_DIR )
  if ( SWIG_FOUND )
    message ( STATUS "Found SWIG version ${SWIG_VERSION} : ${SWIG_EXECUTABLE}" )
  endif ( SWIG_FOUND )
  find_package ( PythonInterp REQUIRED )
  find_package ( PythonLibs REQUIRED )
  find_package ( Numpy )
  find_package ( Rpy2 )

  if ( PYTHONINTERP_FOUND )
    execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "import sys; print '%d.%d' % ( sys.version_info[0], sys.version_info[1] )"
                      OUTPUT_VARIABLE PYTHON_VERSION
                      OUTPUT_STRIP_TRAILING_WHITESPACE )

    set ( OPENTURNS_PYTHON_MODULE_PATH
          ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/python${PYTHON_VERSION}/site-packages
          CACHE PATH "The directory where the python modules are installed"
        )
    set ( PYTHON_MODULE_PATH ${OPENTURNS_PYTHON_MODULE_PATH} )

  endif ( PYTHONINTERP_FOUND )

  add_subdirectory ( python )

  add_dependencies ( installcheck pyinstallcheck )

endif ( OPENTURNS_BUILD_PYTHON )


set ( OPENTURNS_BUILD_VALIDATION ON CACHE BOOL "Build the validation files of the library" )
if ( OPENTURNS_BUILD_VALIDATION )
  add_subdirectory ( validation )
endif ( OPENTURNS_BUILD_VALIDATION )

install ( FILES ${HEADERFILES}
          DESTINATION ${INCLUDE_PATH}
          PERMISSIONS OWNER_READ GROUP_READ WORLD_READ
        )

include ( CPack )
