cmake_minimum_required(VERSION 3.7)
project(VITE CXX C)

# Add cmake submodules
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/")

# Set c++11 support
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

### The current version number
set(VITE_VERSION_MAJOR 1)
set(VITE_VERSION_MINOR 4)
set(VITE_VERSION_PATCH 0)

# Enable export symbols to load plugins
set(CMAKE_ENABLE_EXPORTS ON)

find_package(Git)
if(GIT_FOUND)
  execute_process(COMMAND ${GIT_EXECUTABLE} show --no-patch --format="%h %aI"
    OUTPUT_VARIABLE VITE_WC_INFO
    ERROR_VARIABLE Git_info_error
    RESULT_VARIABLE Git_info_result
    OUTPUT_STRIP_TRAILING_WHITESPACE)

  if(NOT ${Git_info_result} EQUAL 0)
    set(VITE_WC_REVISION "")
    set(VITE_WC_DATE "")
  else()
    string(REGEX REPLACE "^\"(.*) (.*)\"$"
      "\\1" VITE_WC_REVISION "${VITE_WC_INFO}")
    string(REGEX REPLACE "^\"(.*) (.*)\"$"
      "\\2" VITE_WC_DATE "${VITE_WC_INFO}")
  endif()
endif()

set(VITE_VERSION "${VITE_VERSION_MAJOR}.${VITE_VERSION_MINOR}.${VITE_VERSION_PATCH}")

if(NOT ${VITE_WC_REVISION} STREQUAL "")
  set(VITE_VERSION "${VITE_VERSION} (${VITE_WC_REVISION})")
endif()


if(NOT ${VITE_WC_DATE} STREQUAL "")
  set(VITE_DATE "\"${VITE_WC_DATE}\"")
else()
  if(UNIX)
    set(_vite_SAVED_LC_ALL "$ENV{LC_ALL}")
    set(ENV{LC_ALL} C)
    set(_vite_SAVED_TZ "$ENV{TZ}")
    set(ENV{TZ} "")

    if(NOT $ENV{SOURCE_DATE_EPOCH} STREQUAL "")
      execute_process(COMMAND date -d @$ENV{SOURCE_DATE_EPOCH} +"%B %Y"
        OUTPUT_VARIABLE VITE_DATE
        ERROR_VARIABLE vite_date_error
        RESULT_VARIABLE vite_date_result
        OUTPUT_STRIP_TRAILING_WHITESPACE)
    else()
      execute_process(COMMAND date +"%B %Y"
        OUTPUT_VARIABLE VITE_DATE
        ERROR_VARIABLE vite_date_error
        RESULT_VARIABLE vite_date_result
        OUTPUT_STRIP_TRAILING_WHITESPACE)
    endif()

    # restore the previous LC_ALL
    set(ENV{LC_ALL} ${_vite_SAVED_LC_ALL})
    # restore the previous TZ
    set(ENV{TZ} ${_vite_SAVED_TZ})
  else()
    set(VITE_DATE "")
  endif()
endif()

message(STATUS "Current revision is ${VITE_VERSION} from ${VITE_DATE}")

if(COMMAND CMAKE_POLICY)
  # CMP0003: add the link paths to the link command as with cmake 2.4
  cmake_policy(SET CMP0003 NEW)
endif()

### Misc options
option(VITE_ENABLE_WARNING         "Enable warning messages from the compiler" OFF)
option(VITE_ENABLE_STATIC_ANALYSIS "Enable warning messages from external static analyzers such as cppcheck" OFF)
option(VITE_ENABLE_COVERAGE        "Enable flags for coverage test" OFF)
include(AuxilaryFlags)

option(BUILD_SHARED_LIBS
  "Build shared libraries" OFF)
option(BUILD_64bits
  "Build 64 bits mode" ON)

option(VITE_ENABLE_MPI
  "Use MPI" OFF)

set(CMAKE_BUILD_TYPE_DROP_LIST "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
include(Sanitizer)
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are None, Debug, Release, RelWithDebInfo, MinSizeRel, ..." FORCE)
endif()

set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_BUILD_TYPE_DROP_LIST})

# cmake modules setup
include(CMakeDetermineSystem)
include(CheckCCompilerFlag)
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckIncludeFile)
include(CheckIncludeFileCXX)
include(CheckIncludeFiles)
include(CheckLibraryExists)
include(CMakeDependentOption)
include(CheckCXXSymbolExists)

### Required Packages
# Try to find Qt5 : http://forum.openscenegraph.org/viewtopic.php?t=11431

set(CMAKE_AUTOMOC ON)
#set(CMAKE_AUTORCC ON)
#set(CMAKE_AUTOUIC ON)

set(QT_REQUIRED_VERSION 5.6.0)
find_package(Qt5 ${QT_REQUIRED_VERSION} COMPONENTS Widgets Core Xml OpenGL Charts Svg UiTools QUIET)

add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050600)
### Renderer option

#OpenGL
cmake_dependent_option(USE_OPENGL "Use OpenGL as renderer module" ON
  "NOT USE_VULKAN" OFF)

#OpenGL with VBO
cmake_dependent_option(VITE_ENABLE_VBO "Enable the support of VBO." ON
  USE_OPENGL OFF)

#Vulkan
#Later must be the default option
option(USE_VULKAN
  "Use Vulkan as renderer module" OFF)

if(USE_OPENGL)
  set(OpenGL_GL_PREFERENCE LEGACY)
  find_package(OpenGL)

  # Can only be used when OpenGL is enabled
endif()

if(USE_VULKAN)
  find_package(Vulkan)
endif()

### Optimization options

option(VITE_ENABLE_SERIALIZATION
  "Enable the support of Boost Serialization." OFF)
option(VITE_ENABLE_MT_PARSERS
  "Enable multi-threading in parsers." OFF)

### Debug options
option(VITE_DBG_MEMORY_USAGE
  "Enable statistic on memory usage." OFF)
cmake_dependent_option(VITE_DBG_MEMORY_TRACE
  "Enable trace generation of memory usage (requires MEMORY_USAGE)." OFF "VITE_DBG_MEMORY_USAGE" OFF)

### Trace format options
option(VITE_ENABLE_OTF2
  "Enable the support of OTF2 file format." OFF)
option(VITE_ENABLE_TAU
  "Enable the support of TAU file format." OFF)

# timeval, timespec, realtime clocks, etc
include(CheckStructHasMember)
check_struct_has_member("struct timespec" tv_nsec time.h HAVE_TIMESPEC_TV_NSEC)
if(NOT HAVE_TIMESPEC_TV_NSEC)
  add_definitions(-D_GNU_SOURCE)
  check_struct_has_member("struct timespec" tv_nsec time.h HAVE_TIMESPEC_TV_NSEC)
endif()
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
if(HAVE_CLOCK_GETTIME)
  set(EXTRA_LIBS "${EXTRA_LIBS};rt")
endif()

# stdlib, stdio, string, getopt, etc
check_include_files(stdarg.h HAVE_STDARG_H)
check_include_files(getopt.h HAVE_GETOPT_H)
check_include_files(unistd.h HAVE_UNISTD_H)
check_function_exists(getopt_long HAVE_GETOPT_LONG)
check_include_files(errno.h HAVE_ERRNO_H)
check_include_files(stddef.h HAVE_STDDEF_H)
check_function_exists(getrusage HAVE_GETRUSAGE)
check_include_files(limits.h HAVE_LIMITS_H)
check_include_files(string.h HAVE_STRING_H)

if(${Qt5Widgets_VERSION_STRING} VERSION_GREATER "5.15")
  set(HAVE_QT5_15 ON)
else()
  set(HAVE_QT5_15 OFF)
endif()

add_definitions(
    -DQT_USE_QSTRINGBUILDER
    -DQT_NO_CAST_TO_ASCII
    -DQT_NO_CAST_FROM_ASCII
    -DQT_NO_URL_CAST_FROM_STRING
    -DQT_NO_KEYWORDS
    -DQT_NO_FOREACH
)

#
# Find optional packages
#

# Search for Boost
#    Components : filesystem, iostreams, programoptions, python, regex,
#                 serialization, signals, system, thread, wave
if(VITE_ENABLE_SERIALIZATION)
  find_package(Boost COMPONENTS serialization thread iostreams system)
endif()

if(VITE_ENABLE_MPI)
  find_package(Boost COMPONENTS mpi)
endif()

if(VITE_ENABLE_VBO)
  find_package(GLEW REQUIRED)
  include_directories(${GLEW_INCLUDE_PATH})
  if(GLM_INC)
    include_directories(${GLM_INC})
    list(APPEND CMAKE_REQUIRED_INCLUDES ${GLM_INC})
  endif()
  check_include_file_cxx(glm/glm.hpp HAVE_GLM_H)
  if(NOT HAVE_GLM_H)
    message(FATAL_ERROR "libglm-dev package is required, you might specify the include directory where to find glm/glm.hpp through -DGLM_INC=/path/to/glm")
  endif()
endif()

if(VITE_ENABLE_OTF2)
  find_package(OTF2)
endif()

if(VITE_ENABLE_TAU)
  find_package(TAU)
endif()

if(VITE_ENABLE_MT_PARSERS)
  add_definitions(-DMT_PARSING)
endif()

if(VITE_DBG_MEMORY_USAGE)
  add_definitions(-DMEMORY_USAGE)
endif()

if(VITE_DBG_MEMORY_TRACE)
  add_definitions(-DMEMORY_TRACE)
endif()

option(VITE_ENABLE_IPO         "Enable interprocedural optimization (IPO/LTO) by the compiler" ON)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.9" AND VITE_ENABLE_IPO)
  cmake_policy(SET CMP0069 NEW)
  include(CheckIPOSupported)
  check_ipo_supported(RESULT ipo_supported)
  if(ipo_supported)
    message("interprocedural optimization is supported by the compiler")
    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
  else()
    message(WARNING "interprocedural optimization is not supported by the compiler")
  endif()
endif()

# Configuration header
configure_file(
  "${CMAKE_CURRENT_SOURCE_DIR}/src/common/ViteConfig.hpp.in"
  "${CMAKE_CURRENT_BINARY_DIR}/src/common/ViteConfig.hpp")

# Vite Desktop file
configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/vite.desktop.in"
    "${CMAKE_CURRENT_BINARY_DIR}/vite.desktop")

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/vite.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/vite.xpm DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmap)

add_subdirectory(src)
add_subdirectory(plugins)

include(CPackLists.txt)
