#===================================================================================
# cmake utility to build and run files using siconos library.
#
# 
#
# Siconos development team - September 2015.
#
# The generated CmakeLists.txt will be used when siconos script will be called.
#
# Input variables that must be provided during siconos script call:
# - CALL_PWD : path to input source.
# - MAIN_SOURCE : full path to main source file
# - BUILD_MAIN : true if an executable must be created (i.e. input file == c or cpp)
# - PLUGIN_DIRECTORIES : path to extra source files used to build some plugins (may be empty)
# - SOURCES_DIRECTORIES : path to extra source files used to build the executable (may be empty)
# - COMPILER_OPTIONS : user-defined option for compiler (-I dir, -O3 ...)
# - COMMAND_LINE_LINKER_OPTIONS : user defined linker options
# - LINKER_DIRECTORIES : path to linked libraries (i.e. -L dir)
# - LINKER_LIBRARIES : libraries to be linked with (-llib)
# - ALL_EXTRA_DEFINITIONS : preproc user-defined vars, thinks like -DVar, CMAKE_BUILD_TYPE ...
#
#====================================================================================
# Set minimum version for cmake
cmake_minimum_required(VERSION 3.0.2)

# Check path to the current install of siconos.
set(siconos_ROOT_DIR /usr)

# Set cmake modules directory (i.e. the one which contains all user-defined FindXXX.cmake files among other things)
set(CMAKE_MODULE_PATH ${siconos_ROOT_DIR}/share/siconos/cmake)
include(SiconosTools)

# Search siconos package components
# without siconos_DIR, the search for the config fails with a custom prefix
set(siconos_DIR ${siconos_ROOT_DIR}/share/siconos/cmake)
find_package(siconos 4.2.0 CONFIG REQUIRED)

# === Check required inputs ===
# Get the name of the main file => name of the executable
if(NOT MAIN_SOURCE)
  message(FATAL_ERROR "Main source file name is missing.")
endif()

# use variables to avoid warnings
# - CALL_PWD : path from which siconos script is run (set in siconos.py)
# - COMMAND_LINE_LINKER_OPTIONS : extra options set during call to siconos.py
# - LINKER_LIBRARIES : extra libraries to be linked with, set during call to siconos.py
set(_use_ ${CALL_PWD};${COMMAND_LINE_LINKER_OPTIONS};${LINKER_LIBRARIES})

# install target tracker
set(_install)

# =========== RPATH stuff ===========

# http://www.cmake.org/Wiki/CMake_RPATH_handling
# do not skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH  FALSE)

# when building, don't use the install RPATH already (but later on
# when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 

# add the automatically determined parts of the RPATH which point to
# directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

# =========== Build type ===========
# if not specified, same as siconos install
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE None)
endif()

# compiler selection : same as siconos install
set(CMAKE_Fortran_COMPILER "/usr/bin/gfortran")

# compile time flags : same as siconos install
set(CMAKE_Fortran_FLAGS "")

# Compiler options (given with --opt)
FOREACH(_O ${COMPILER_OPTIONS})
  ADD_DEFINITIONS(${_O})
ENDFOREACH()

# Definitions (given with -D) are passed to the preprocessor
FOREACH(_DEF ${ALL_EXTRA_DEFINITIONS})
  IF(DEFINED ${_DEF})
    ADD_DEFINITIONS(-D${_DEF}=${${_DEF}})
  ELSE()
    ADD_DEFINITIONS(-D${_DEF})
  ENDIF()
ENDFOREACH()

# === Check if build is required ===
if(BUILD_MAIN) # False for python input file
  get_filename_component(_EXE ${MAIN_SOURCE} NAME_WE)
endif()
# Path to main source file
get_filename_component(_MAIN_DIR ${MAIN_SOURCE} PATH)
assert(_MAIN_DIR)
get_standard_ext()
set(SRC_EXTS ${ALL_EXTS})

# === Include target ===
if(_EXE)
  # include optional user-defined cmake commands in ${_EXE}.cmake 
  if(EXISTS ${_EXE}.cmake)
    message(STATUS "Including ${_EXE}.cmake")
    include(${_EXE}.cmake)
  endif()
  if(EXISTS ${_MAIN_DIR}/${_EXE}.cmake)
    message(STATUS "Including ${_MAIN_DIR}/${_EXE}.cmake")
    include(${_MAIN_DIR}/${_EXE}.cmake)
  endif()
endif(_EXE)

# === Check some optional external libraries ===
IF(WithQGLViewer)
  FIND_PACKAGE(X11 REQUIRED)
  FIND_PACKAGE(OpenGL REQUIRED)
  FIND_PACKAGE(QGLViewer REQUIRED)
  INCLUDE_DIRECTORIES(${X11_INCLUDE_DIR})			
  INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})			
  IF(OPENGL_FOUND)
    FIND_PACKAGE_MESSAGE(OpenGL "Found OpenGL: ${OPENGL_LIBRARIES}"
      "[${OPENGL_INCLUDE_DIR}]")
  ELSE (OPENGL_FOUND)	
    IF (OPENGL_FIND_REQUIRED)	
      MESSAGE(FATAL_ERROR "Could not find OPENGL")
    ENDIF (OPENGL_FIND_REQUIRED)	 
  ENDIF (OPENGL_FOUND)	
  INCLUDE_DIRECTORIES(${QGLVIEWER_INCLUDE_DIR})   
  ADD_DEFINITIONS(${QGLVIEWER_DEFINITIONS})
  FIND_PACKAGE(Qt4 REQUIRED)
  INCLUDE(${QT_USE_FILE})
  # not set by UseQt4:
  INCLUDE_DIRECTORIES(${QT_INCLUDES})
  foreach(_L ${QGLVIEWER_LIBRARY} ${QT_QTXML_LIBRARY}
    ${QT_QTCORE_LIBRARY} ${QT_QTASSISTANT_LIBRARY}
    ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY}
    ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY})
    if (NOT (("${_L}" STREQUAL "optimized") OR ("${_L}" STREQUAL "debug")))
      set(LINKER_LIBRARIES ${LINKER_LIBRARIES} ${_L})
    endif()
  endforeach()
  
ENDIF(WithQGLViewer)

IF(WithOpenGL)
  FIND_PACKAGE(OpenGL REQUIRED)
  IF(OPENGL_FOUND)		
    FIND_PACKAGE_MESSAGE(OpenGL "Found OpenGL: ${OPENGL_LIBRARIES}"
      "[${OPENGL_INCLUDE_DIR}]")
  ELSE (OPENGL_FOUND)	
    IF (OPENGL_FIND_REQUIRED)	
      MESSAGE(FATAL_ERROR "Could not find OPENGL")
    ENDIF (OPENGL_FIND_REQUIRED)	 
  ENDIF (OPENGL_FOUND) 
  INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})
  foreach(_L ${OPENGL_LIBRARIES})
    if (NOT (("${_L}" STREQUAL "optimized") OR ("${_L}" STREQUAL "debug")))
      set(LINKER_LIBRARIES ${LINKER_LIBRARIES} ${_L})
    endif()
  endforeach()
ENDIF(WithOpenGL)


# --- External libraries setup ---
# For a given target:
# - link the target with the external libraries on which siconos depends
# - link the target with user-defined libraries (from option LINKER_LIBRARIES)
# - add link flags (from option COMMAND_LINE_LINKER_OPTIONS)
#
macro(link_setup _TARGET)
  # link with libraries required by siconos
  target_link_libraries(${_TARGET} ${PRIVATE} ${${PACKAGE_NAME}_LIBRARIES})

  # link with user-defined libraries
  foreach(_L ${LINKER_LIBRARIES})
    target_link_libraries(${_TARGET} ${PRIVATE} ${_L})
  endforeach()

  set(_LINKER_OPTIONS "")
  # Add user-defined linker options
  foreach(_O ${COMMAND_LINE_LINKER_OPTIONS})
    set(_LINKER_OPTIONS "${_LINKER_OPTIONS} ${_O}")
  endforeach()
  set_target_properties(${_TARGET} PROPERTIES LINK_FLAGS "${_LINKER_OPTIONS}")
endmacro()

# === Check if build is required ===
if(BUILD_MAIN) # False for python input file
  get_filename_component(_EXE ${MAIN_SOURCE} NAME_WE)
endif()
# Path to main source file
get_filename_component(_MAIN_DIR ${MAIN_SOURCE} PATH)
assert(_MAIN_DIR)
get_standard_ext()
set(SRC_EXTS ${ALL_EXTS})

# === Include dirs ===
# Required for 'exe' and for plugins
#
# Set include directory for siconos headers and external libraries headers
include_directories(${${PACKAGE_NAME}_INCLUDE_DIRECTORIES})

# === Path to user-defined external libraries ===
foreach(_D ${LINKER_DIRECTORIES})
  link_directories(${_D})
endforeach()

# === Define target ===
if(_EXE)
  # if some extra directories for sources have
  # been defined by user, collect input files
  if(SOURCES_DIRECTORIES)
    get_sources(${SOURCES_DIRECTORIES})
  endif()
  
  if(CMAKE_SYSTEM_NAME MATCHES Windows)
    STRING(REGEX REPLACE "\\\\" "/" MAIN_SOURCE "${MAIN_SOURCE}")
  endif()

  # Set 'all sources list' with collected files and main source.
  set(_ALL_EXE_SRCS ${SOURCES_FILES} ${MAIN_SOURCE})
  list(REMOVE_DUPLICATES _ALL_EXE_SRCS)

  # set includes ...
  # === Include dirs ===
  # 'local' sources
  include_directories(${SOURCES_DIRECTORIES})
  include_directories(${_MAIN_DIR})
  
  add_executable("${_EXE}" ${_ALL_EXE_SRCS})

  # === Linked libraries ===
  link_setup(${_EXE})

  # === install ===
  install(TARGETS ${_EXE} DESTINATION ${CALL_PWD})
  set(_install TRUE)
endif()

# === Build a library from sources in PLUGIN_DIRECTORIES (if any) ===
# Note : one library for each dir in PLUGIN_DIRECTORIES, named dir.so
if(PLUGIN_DIRECTORIES)
  foreach(_D ${PLUGIN_DIRECTORIES})
    get_filename_component(_PLUGINNAME ${_D} NAME_WE)
    get_sources("${_D}")
    if(SOURCES_FILES)
      add_library(${_PLUGINNAME} MODULE ${SOURCES_FILES})
      set_target_properties(${_PLUGINNAME} PROPERTIES PREFIX "")
      link_setup(${_PLUGINNAME})
      install(TARGETS ${_PLUGINNAME} DESTINATION ${CALL_PWD})
      set(_install TRUE)
    endif()
  endforeach()
endif()

if(NOT _install)
  add_custom_target(install COMMAND cmake -E echo 'nothing to install')
endif()
