#############################################################################
#
# ViSP, open source Visual Servoing Platform software.
# Copyright (C) 2005 - 2024 by Inria. All rights reserved.
#
# This software is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# See the file LICENSE.txt at the root directory of this source
# distribution for additional information about the GNU GPL.
#
# For using ViSP with software that can not be combined with the GNU
# GPL, please contact Inria about acquiring a ViSP Professional
# Edition License.
#
# See https://visp.inria.fr for more information.
#
# This software was developed at:
# Inria Rennes - Bretagne Atlantique
# Campus Universitaire de Beaulieu
# 35042 Rennes Cedex
# France
#
# If you have questions regarding the use of this file, please contact
# Inria at visp@inria.fr
#
# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# Description:
# ViSP overall configuration file. Detect third party libraries (X11, GTK, ...)
#
#############################################################################

# Detect crosscompiling; need to be before project(VISP) to work
if(NOT CMAKE_TOOLCHAIN_FILE)
  # Modify default install prefix
  if(WIN32)
    set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory")
  endif()
else(NOT CMAKE_TOOLCHAIN_FILE)
  #Android: set output folder to ${CMAKE_BINARY_DIR}
  set(LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are compiled to" )
  # Crosscompiling
  set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory")
endif()

if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
  set(WINRT TRUE)
endif(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)

if(WINRT)
  add_definitions(-DWINRT)

  if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone)
    set(WINRT_PHONE TRUE)
    add_definitions(-DWINRT_PHONE)
  elseif(CMAKE_SYSTEM_NAME MATCHES WindowsStore)
    set(WINRT_STORE TRUE)
    add_definitions(-DWINRT_STORE)
  endif()

  if(CMAKE_SYSTEM_VERSION MATCHES 10 OR CMAKE_SYSTEM_VERSION MATCHES 10.0)
    set(WINRT_10 TRUE)
    add_definitions(-DWINRT_10)
  elseif(CMAKE_SYSTEM_VERSION MATCHES 8.1)
    set(WINRT_8_1 TRUE)
    add_definitions(-DWINRT_8_1)
  elseif(CMAKE_SYSTEM_VERSION MATCHES 8.0)
    set(WINRT_8_0 TRUE)
    add_definitions(-DWINRT_8_0)
  endif()
endif()

# By default set release configuration
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif()

cmake_minimum_required(VERSION 3.10) # needs to be before project() for policy CMP0025

# Detect if the toolchain is for Aldebaran naoqi
if(CMAKE_TOOLCHAIN_FILE AND I_AM_A_ROBOT)
  include(platforms/naoqi/cmake/extra.cmake)
endif()

if(POLICY CMP0020)
  cmake_policy(SET CMP0020 NEW) # For UsTK: Qt5
endif()
if(POLICY CMP0022)
  cmake_policy(SET CMP0022 NEW) # Due to sensor ATIDAQ_LIBRARIES
endif()
if(POLICY CMP0025)
  cmake_policy(SET CMP0025 NEW) # To set compiler id for Apple Clang to AppleClang instead of Clang. Required to detect OpenMP support on MacOS
endif()
if(POLICY CMP0053)
  cmake_policy(SET CMP0053 NEW) # For UsTK: VTK and Qt5
endif()
if(POLICY CMP0054)
  cmake_policy(SET CMP0054 NEW) # To turn off a warning in native FindOpenMP with cmake 3.9.2
endif()
if(POLICY CMP0068)
  cmake_policy(SET CMP0068 NEW)  # CMake 3.9+: `RPATH` settings on macOS do not affect `install_name`.
endif()
if(POLICY CMP0072)
  cmake_policy(SET CMP0072 NEW) # To use legacy GL library with FindOpenGL and cmake 3.12.0
endif()
if(POLICY CMP0074)
  cmake_policy(SET CMP0074 NEW) # For PCL_ROOT usage and cmake 3.12.0 when PCL 1.9.1 all in one is used on Windows
endif()
if(POLICY CMP0075)
  cmake_policy(SET CMP0075 NEW) # For check_include_file and cmake 3.12.0
endif()
if(POLICY CMP0146)
  cmake_policy(SET CMP0146 OLD) # The ``FindCUDA`` module deprecated since CMake 3.10
endif()

if(APPLE)
  # Fix following errors for libpng and libjpeg detection:
  # - Application built with libpng-1.4.12 but running with 1.6.37,
  # - Wrong JPEG library version: library is 90, caller expects 80.
  # The reason is that headers were found in /Library/Frameworks/Mono.framework/Headers
  # while libraries in /usr/local/lib
  set(CMAKE_FIND_FRAMEWORK LAST)
endif()

project(VISP C CXX)

list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")

include(cmake/VISPUtils.cmake)
include(cmake/VISPDetectCXXStandard.cmake) # Set cxx standard to 17 by default

#-----------------------------------------------------------------------------
# VISP version number.  An even minor number corresponds to releases.
set(VISP_VERSION_MAJOR "3")
set(VISP_VERSION_MINOR "7")
set(VISP_VERSION_PATCH "0")
set(VISP_VERSION "${VISP_VERSION_MAJOR}.${VISP_VERSION_MINOR}.${VISP_VERSION_PATCH}")
set(VISP_SOVERSION "${VISP_VERSION_MAJOR}.${VISP_VERSION_MINOR}")
# Package revision number
set(VISP_REVISION "1")

# Try to locate visp-images and, if it exists, its version
vp_find_dataset(VISP_DATASET_FOUND VISP_DATASET_LOCATION
                VISP_DATASET_VERSION
                VISP_DATASET_VERSION_MAJOR
                VISP_DATASET_VERSION_MINOR
                VISP_DATASET_VERSION_PATCH)

#-----------------------------------------------------------------------------
# TO BE CHECKED BEFORE NEXT RELEASE
#
# Remove following 3 next lines and check if pcl produces a CMP0144 complain around CMake variable FLANN_ROOT set to /opt/homebrew
if(NOT DEFINED CMAKE_SUPPRESS_DEVELOPER_WARNINGS)
  set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE INTERNAL "No dev warnings")
endif()
#-----------------------------------------------------------------------------

find_file(GNU_INSTALL_DIRS_FROM_CMAKE NAMES GNUInstallDirs.cmake PATHS ${CMAKE_ROOT}/Modules)
mark_as_advanced(GNU_INSTALL_DIRS_FROM_CMAKE)
if(GNU_INSTALL_DIRS_FROM_CMAKE)
  include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake)
else()
  include(cmake/GNUInstallDirs.cmake)
endif()

#----------------------------------------------------------------------
# Tool specific
#----------------------------------------------------------------------
# PCL tools
include(cmake/PCLTools.cmake)
# Eigen3 tools
include(cmake/Eigen3Tools.cmake)

#----------------------------------------------------------------------
# Platform specific
#----------------------------------------------------------------------
include(cmake/VISPDetectPlatform.cmake)

# Where to install the library and headers
if(ANDROID)
  # Where to build modules
  set(LIBRARY_OUTPUT_PATH                 "${VISP_BINARY_DIR}/lib/${ANDROID_NDK_ABI_NAME}")
  # Where to build internal 3rdparties
  vp_update(VISP_3P_LIBRARY_OUTPUT_PATH   "${VISP_BINARY_DIR}/3rdparty/lib/${ANDROID_NDK_ABI_NAME}")

  vp_update(VISP_INSTALL_BINARIES_PREFIX "sdk/native/")
  # set binary path
  vp_update(VISP_BIN_INSTALL_PATH         "sdk/native/bin/${ANDROID_NDK_ABI_NAME}")

  # set samples path
  vp_update(VISP_SAMPLES_BIN_INSTALL_PATH "sdk/native/samples/${ANDROID_NDK_ABI_NAME}")

  vp_update(VISP_LIB_INSTALL_PATH         "sdk/native/libs/${ANDROID_NDK_ABI_NAME}")
  vp_update(VISP_LIB_ARCHIVE_INSTALL_PATH "sdk/native/staticlibs/${ANDROID_NDK_ABI_NAME}")
  vp_update(VISP_3P_LIB_INSTALL_PATH      "sdk/native/3rdparty/libs/${ANDROID_NDK_ABI_NAME}")
  vp_update(VISP_CONFIG_INSTALL_PATH      "sdk/native/jni")
  vp_update(VISP_INC_INSTALL_PATH         "sdk/native/jni/include")
  vp_update(VISP_SAMPLES_SRC_INSTALL_PATH "samples/native")
  vp_update(VISP_INSTALL_DATAROOTDIR      "sdk/etc")

elseif(WIN32 AND CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
  # Where to build modules
  set(LIBRARY_OUTPUT_PATH         "${VISP_BINARY_DIR}/lib")
  # Where to build internal 3rdparties
  vp_update(VISP_3P_LIBRARY_OUTPUT_PATH "${VISP_BINARY_DIR}/3rdparty/lib${LIB_SUFFIX}")

  if(DEFINED VISP_RUNTIME AND DEFINED VISP_ARCH)
    vp_update(VISP_INSTALL_BINARIES_PREFIX "${VISP_ARCH}/${VISP_RUNTIME}/")
  else()
    message(STATUS "Can't detect runtime and/or arch")
    vp_update(VISP_INSTALL_BINARIES_PREFIX "")
  endif()

  if(VISP_STATIC)
    vp_update(VISP_LIB_INSTALL_PATH "${VISP_INSTALL_BINARIES_PREFIX}staticlib${LIB_SUFFIX}")
  else()
    vp_update(VISP_LIB_INSTALL_PATH "${VISP_INSTALL_BINARIES_PREFIX}lib${LIB_SUFFIX}")
  endif()
  vp_update(VISP_3P_LIB_INSTALL_PATH      "${VISP_INSTALL_BINARIES_PREFIX}staticlib${LIB_SUFFIX}")
  vp_update(VISP_SAMPLES_SRC_INSTALL_PATH samples/native)
  vp_update(VISP_JAR_INSTALL_PATH         java)
  vp_update(VISP_INC_INSTALL_PATH         "${CMAKE_INSTALL_INCLUDEDIR}")
  vp_update(VISP_BIN_INSTALL_PATH         "${VISP_INSTALL_BINARIES_PREFIX}bin")
  vp_update(VISP_INSTALL_DATAROOTDIR      "${CMAKE_INSTALL_DATAROOTDIR}/visp-${VISP_VERSION}")
  vp_update(VISP_CONFIG_INSTALL_PATH      ".")

else() # UNIX
  # Where to build modules
  set(LIBRARY_OUTPUT_PATH         "${VISP_BINARY_DIR}/lib")
  # Where to build internal 3rdparties
  vp_update(VISP_3P_LIBRARY_OUTPUT_PATH "${VISP_BINARY_DIR}/3rdparty/lib${LIB_SUFFIX}")

  vp_update(VISP_INSTALL_BINARIES_PREFIX "")

  #----------------------------------------------------------------------
  # Multi-arch option that should be enable for debian packaging
  #----------------------------------------------------------------------
  VP_OPTION(ENABLE_MULTIARCH  "" "" "Enable multi-arch support"  "" OFF IF (NOT APPLE))

  # The location where includes and libraries will be installed
  if(ENABLE_MULTIARCH)
    # The 2 following lines should be used to enable multi-arch support.
    vp_update(VISP_INC_INSTALL_PATH       "${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_LIBRARY_ARCHITECTURE}")
    vp_update(VISP_LIB_INSTALL_PATH       "${CMAKE_INSTALL_LIBDIR}/${CMAKE_LIBRARY_ARCHITECTURE}")
  else()
    # catkin doesn't support multi-arch; use rather the next 2 lines
    vp_update(VISP_INC_INSTALL_PATH       "${CMAKE_INSTALL_INCLUDEDIR}")
    vp_update(VISP_LIB_INSTALL_PATH       "${CMAKE_INSTALL_LIBDIR}")
  endif()
  vp_update(VISP_BIN_INSTALL_PATH         "${CMAKE_INSTALL_BINDIR}")
  vp_update(VISP_INSTALL_DATAROOTDIR      "${CMAKE_INSTALL_DATAROOTDIR}/visp-${VISP_VERSION}")
  vp_update(VISP_3P_LIB_INSTALL_PATH      "${VISP_LIB_INSTALL_PATH}/visp/3rdparty")
  vp_update(VISP_SAMPLES_SRC_INSTALL_PATH "${VISP_INSTALL_DATAROOTDIR}/samples")
  vp_update(VISP_JAR_INSTALL_PATH         "${VISP_INSTALL_DATAROOTDIR}/java")
  vp_update(VISP_CONFIG_INSTALL_PATH      "${VISP_LIB_INSTALL_PATH}/cmake/visp")
endif()

# the include directory we depend on for the build
set(VISP_INCLUDE_DIR ${VISP_BINARY_DIR}/${VISP_INC_INSTALL_PATH})
set(VISP_DOC_DIR "${VISP_BINARY_DIR}/doc")

# The location where includes and libraries will be build
set(BINARY_OUTPUT_PATH ${VISP_BINARY_DIR}/${VISP_BIN_INSTALL_PATH})

if(WIN32)
  # Postfix of .lib and .dll
  set(VISP_DEBUG_POSTFIX "d")
  set(VISP_DLLVERSION "${VISP_VERSION_MAJOR}${VISP_VERSION_MINOR}${VISP_VERSION_PATCH}")
else()
  set(VISP_DEBUG_POSTFIX "")
  set(VISP_DLLVERSION "")
endif()

# --- Python Support ---
if(NOT IOS AND NOT VISP_PYTHON_SKIP_DETECTION)
  # Make sure to refresh the python interpreter every time we rerun cmake
  # If we don't do this, we may use an old or invalid python when installing the bindings
  # that was cached by a previous attempt at building
  if(CMAKE_VERSION VERSION_LESS "3.15.0")
    set(PYTHON3_CACHE_LIST
      PYTHON3INTERP_FOUND PYTHONINTERP_FOUND PYTHONLIBS_FOUND PYTHON_FOUND
      PYTHON3_EXECUTABLE PYTHON_EXECUTABLE
    )
    foreach (_variableName ${PYTHON3_CACHE_LIST})
      unset(${_variableName} CACHE)
    endforeach()
    include(cmake/VISPDetectPython.cmake)
  else()
    set(PYTHON3_CACHE_LIST
        Python3_FOUND Python3_EXECUTABLE Python3_Interpreter_FOUND Python3_LIBRARIES
        _Python3_EXECUTABLE _Python3_INCLUDE_DIR _Python3_INTERPRETER_PROPERTIES _Python3_LIBRARY_RELEASE
    )
    foreach (_variableName ${PYTHON3_CACHE_LIST})
      unset(${_variableName} CACHE)
    endforeach()
    # Find strategy
    set(Python3_FIND_REGISTRY LAST)
    set(Python3_FIND_VIRTUALENV FIRST)
    set(Python3_FIND_STRATEGY LOCATION)
    find_package (Python3 COMPONENTS Interpreter Development)

    # Alias variables to be consistent with previous detection method
    set(PYTHON3_FOUND ${Python3_FOUND})
    set(PYTHON_DEFAULT_AVAILABLE TRUE)
    set(PYTHON3_EXECUTABLE ${Python3_EXECUTABLE})
    set(PYTHON_DEFAULT_EXECUTABLE ${PYTHON3_EXECUTABLE})
    set(PYTHON3INTERP_FOUND ${Python3_Interpreter_FOUND})
    set(PYTHON3_VERSION_STRING ${Python3_VERSION})
  endif()
endif()

# --- Python Bindings requirements ---
VP_OPTION(USE_PYBIND11       pybind11       QUIET    "Include pybind11 to create Python bindings" "" ON)
VP_OPTION(ALLOW_SYSTEM_PYTHON  "" "" "Allow the use of the system Python interpreter when compiling and installing bindings" "" OFF)

# Minimum tool versions
set(CMAKE_MINIMUM_VERSION_PYTHON_BINDINGS "3.19.0")
set(PYTHON3_MINIMUM_VERSION_PYTHON_BINDINGS "3.7.0")
if(CMAKE_VERSION VERSION_LESS ${CMAKE_MINIMUM_VERSION_PYTHON_BINDINGS})
  set(CMAKE_NOT_OK_FOR_BINDINGS TRUE)
  message(STATUS "Required CMake version for Python bindings is ${CMAKE_MINIMUM_VERSION_PYTHON_BINDINGS},
  but you have ${CMAKE_VERSION}.
  Python bindings generation will be deactivated.
  ")
else()
  set(CMAKE_NOT_OK_FOR_BINDINGS FALSE)
endif()

if(PYTHON3_VERSION_STRING VERSION_LESS ${PYTHON3_MINIMUM_VERSION_PYTHON_BINDINGS})
  set(PYTHON3_NOT_OK_FOR_BINDINGS TRUE)
  message(STATUS "Required Python version for Python bindings is ${PYTHON3_MINIMUM_VERSION_PYTHON_BINDINGS},
  but you have ${PYTHON3_VERSION_STRING}.
  Python bindings generation will be deactivated.
  ")
else()
  set(PYTHON3_NOT_OK_FOR_BINDINGS FALSE)
endif()
if(VISP_CXX_STANDARD LESS VISP_CXX_STANDARD_17)
  set(CXX_STANDARD_NOT_OK_FOR_BINDINGS TRUE)
  message(STATUS "Required C++ standard is C++17, but you have ${VISP_CXX_STANDARD}")
else()
  set(CXX_STANDARD_NOT_OK_FOR_BINDINGS FALSE)
endif()

# Forbid system Python if override flag is not false
if(DEFINED ENV{VIRTUAL_ENV} OR DEFINED ENV{CONDA_PREFIX})
  set(_pip_args)
  set(VISP_PYTHON_INTERPRETER_ALLOWED TRUE)
else()
  # First solution: raise an error when cmake will call pip install
  # set(_pip_args "--require-virtualenv") # If this is a system python, throw an error
  if(PYTHON3_FOUND)
    if(ALLOW_SYSTEM_PYTHON)
      set(VISP_PYTHON_INTERPRETER_ALLOWED TRUE)
    else()
      message(STATUS "The python version that you are using (${PYTHON3_EXECUTABLE}) is the system interpreter.
      pip packages should not be installed system-wide!
      Python bindings targets will be deactivated!
      To reenable them, install conda or virtualenv, or reconfigure with ALLOW_SYSTEM_PYTHON to true.
      delete the CMakeCache file then rerun cmake when inside the virtual environment.
      ")
      set(VISP_PYTHON_INTERPRETER_ALLOWED FALSE)
    endif()
  endif()
endif()

# ---


include_directories(${VISP_INCLUDE_DIR})

#----------------------------------------------------------------------
# x86 SIMD optimization
#----------------------------------------------------------------------
VP_OPTION(ENABLE_SSE2  "" "" "Enable SSE2 instructions"  "" ON IF ((MSVC OR CMAKE_COMPILER_IS_GNUCXX) AND (X86 OR X86_64)) )
VP_OPTION(ENABLE_SSE3  "" "" "Enable SSE3 instructions"  "" ON IF ((MSVC OR CMAKE_COMPILER_IS_GNUCXX) AND (X86 OR X86_64)) )
VP_OPTION(ENABLE_SSSE3 "" "" "Enable SSSE3 instructions" "" ON IF ((MSVC OR CMAKE_COMPILER_IS_GNUCXX) AND (X86_64)) ) # X86 disabled since it produces an issue on Debian i386
if(X86_64)
  VP_OPTION(ENABLE_AVX   "" "" "Enable AVX instructions"   "" OFF) # should be explicitly enabled, used in matrix transpose code
endif()

#----------------------------------------------------------------------
# BLAS / LAPACK
#----------------------------------------------------------------------
if(NOT WINRT AND NOT IOS)
  include(cmake/ChooseBlas.cmake)
endif()

# ----------------------------------------------------------------------------
# Handle RPATH
# ----------------------------------------------------------------------------
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${VISP_LIB_INSTALL_PATH}")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

if(ANDROID)
  vp_update(VISP_JNI_INSTALL_PATH "${VISP_LIB_INSTALL_PATH}")
elseif(INSTALL_CREATE_DISTRIB)
  vp_update(VISP_JNI_INSTALL_PATH "${VISP_JAR_INSTALL_PATH}/${VISP_ARCH}")
else()
  vp_update(VISP_JNI_INSTALL_PATH "${VISP_JAR_INSTALL_PATH}")
endif()
vp_update(VISP_JNI_BIN_INSTALL_PATH "${VISP_JNI_INSTALL_PATH}")

if(NOT VISP_LIB_ARCHIVE_INSTALL_PATH)
  set(VISP_LIB_ARCHIVE_INSTALL_PATH ${VISP_LIB_INSTALL_PATH})
endif()

# ----------------------------------------------------------------------------
#  Path for additional contrib modules
# ----------------------------------------------------------------------------
set(VISP_CONTRIB_MODULES_PATH "" CACHE PATH "Where to look for additional contrib ViSP modules")

# Get the OS
set(OS ${CMAKE_SYSTEM_NAME})

set(OGRE_DIR $ENV{OGRE_DIR})
if(NOT OGRE_DIR) # For compat with previous ViSP versions
  set(OGRE_DIR $ENV{OGRE_HOME})
endif()
if(OGRE_DIR)
  # replace \ with / especially for windows
  STRING(REGEX REPLACE "\\\\" "/" OGRE_DIR ${OGRE_DIR})
endif()

# ----------------------------------------------------------------------------
# Check for system libs
# ----------------------------------------------------------------------------
include(CheckLibraryExists)

if(UNIX)
  # try to found -lm requested on some platforms to link with X11
  find_library(M_LIBRARY NAMES m)
  mark_as_advanced(M_LIBRARY)
  if(M_LIBRARY)
    list(APPEND VISP_LINKER_LIBS ${M_LIBRARY})
  endif()
  # try to found -lsocket -lnsl requested for vpNetwork and vpSickLDMRS
  find_library(SOCKET_LIBRARY NAMES socket)
  find_library(NSL_LIBRARY NAMES nsl)
  mark_as_advanced(SOCKET_LIBRARY NSL_LIBRARY)
  if (SOCKET_LIBRARY)
    list(APPEND VISP_LINKER_LIBS ${SOCKET_LIBRARY})
  endif()
  if (NSL_LIBRARY)
    list(APPEND VISP_LINKER_LIBS ${NSL_LIBRARY})
  endif()
endif()

if(WIN32)
  # winmm.lib for timeGetTime() under windows
  check_library_exists("winmm.lib" getch "" HAVE_LIBWINMM) # for timeGetTime()
  if(HAVE_LIBWINMM)
    list(APPEND VISP_LINKER_LIBS "winmm.lib")
  endif()

  # rpcrt4.lib for timeGetTime() under windows
  check_library_exists("rpcrt4.lib" getch "" HAVE_LIBRPCRT4) # for UuidToString()
  if(HAVE_LIBRPCRT4)
    list(APPEND VISP_LINKER_LIBS "rpcrt4.lib")
  endif()
endif()

if(WIN32 AND NOT CYGWIN)
  VP_CHECK_PACKAGE(WS2_32)
  # Should be before include(cmake/VISPDetectCXXStandard.cmake)
  VP_CHECK_FUNCTION_EXISTS(inet_ntop "${WS2_32_LIBRARY}")
else()
  # Should be before include(cmake/VISPDetectCXXStandard.cmake)
  VP_CHECK_FUNCTION_EXISTS(inet_ntop "")
endif()

#--------------------------------------------------------------------
# Option management
#--------------------------------------------------------------------

# Choose static or shared libraries.
VP_OPTION(BUILD_SHARED_LIBS  "" "" "Build ViSP shared libraries (.dll/.so) instead of static ones (.lib/.a)" "" NOT (ANDROID OR APPLE_FRAMEWORK))
# Build apps as an option.
VP_OPTION(BUILD_APPS "" "" "Build utility applications (used for example for calibration)" "" (NOT ANDROID AND NOT WINRT AND NOT APPLE_FRAMEWORK) )
# Build examples as an option.
VP_OPTION(BUILD_EXAMPLES  "" "" "Build ViSP examples" "" ON)
# Build examples as an option.
VP_OPTION(BUILD_TESTS  "" "" "Build ViSP tests" "" ON)
VP_OPTION(BUILD_COVERAGE "" "" "Enables test coverage" "" OFF IF (BUILD_TESTS AND (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGCXX)))

# Build java as an option
VP_OPTION(BUILD_JAVA  "" "" "Enable Java support" "" (ANDROID OR NOT CMAKE_CROSSCOMPILING)  IF (ANDROID OR (NOT APPLE_FRAMEWORK AND NOT WINRT)) )
VP_OPTION(BUILD_FAT_JAVA_LIB  "" "" "Create Java wrapper exporting all functions of ViSP library (requires static build of ViSP modules)" "" ANDROID IF NOT BUILD_SHARED_LIBS)
VP_OPTION(BUILD_ANDROID_SERVICE   "" "" "Build ViSP Manager for Google Play"          "" OFF IF ANDROID )
VP_OPTION(BUILD_ANDROID_PROJECTS  "" "" "Build Android projects providing .apk files" "" ON  IF ANDROID )
VP_OPTION(BUILD_ANDROID_EXAMPLES  "" "" "Build examples for Android platform"         "" ON  IF ANDROID )
VP_OPTION(INSTALL_ANDROID_EXAMPLES "" "" "Install Android examples"  ""                  OFF IF ANDROID )

# Build python bindings as an option
VP_OPTION(BUILD_PYTHON_BINDINGS  "" "" "Build Python bindings" "" ON IF (PYTHON3INTERP_FOUND AND USE_PYBIND11 AND NOT CMAKE_NOT_OK_FOR_BINDINGS AND VISP_PYTHON_INTERPRETER_ALLOWED AND NOT PYTHON3_NOT_OK_FOR_BINDINGS AND NOT CXX_STANDARD_NOT_OK_FOR_BINDINGS) )
VP_OPTION(BUILD_PYTHON_BINDINGS_DOC  "" "" "Build the documentation for the Python bindings" "" ON IF BUILD_PYTHON_BINDINGS )


# Build demos as an option.
VP_OPTION(BUILD_DEMOS  "" "" "Build ViSP demos" "" ON)
# Build tutorials as an option.
VP_OPTION(BUILD_TUTORIALS  "" "" "Build ViSP tutorials" "" ON)
# Build apps as an option.
vp_check_subdirectories(VISP_CONTRIB_MODULES_PATH apps APPS_FOUND)
if(APPS_FOUND)
  VP_OPTION(BUILD_APPS  "" "" "Build ViSP apps" "" ON)
endif()
# Build deprecated functions as an option.
VP_OPTION(BUILD_DEPRECATED_FUNCTIONS  "" "" "Build deprecated functionalities" "" ON)
VP_OPTION(ACTIVATE_WARNING_3PARTY_MUTE  "" "" "Add flags to disable warning due to known 3rd parties" "" ON)
# Debug and trace cflags
set(ENABLE_DEBUG_LEVEL 0 CACHE STRING "Set a debug level value between 0 and 9")

if(ENABLE_DEBUG_LEVEL)
  if(ENABLE_DEBUG_LEVEL MATCHES "^([0-9]+)?$")
    set(VP_DEBUG_MODE ${CMAKE_MATCH_1})
    set(VP_DEBUG TRUE)
    set(VP_TRACE TRUE)
  else()
    set(VP_DEBUG_MODE 0)
  endif()
else()
  set(VP_DEBUG_MODE 0)
endif()

VP_OPTION(BUILD_WITH_STATIC_CRT  "" "" "Enables use of staticaly linked CRT for staticaly linked ViSP" "" ON IF MSVC)

# ----------------------------------------------------------------------------
# Build options
# ----------------------------------------------------------------------------
VP_OPTION(ENABLE_SOLUTION_FOLDERS "" "" "Solution folder in Visual Studio or in other IDEs" "" (MSVC_IDE OR CMAKE_GENERATOR MATCHES Xcode))
# Note that it is better to set ENABLE_MOMENTS_COMBINE_MATRICES to OFF
VP_OPTION(ENABLE_MOMENTS_COMBINE_MATRICES  "" "" "Use linear combination of matrices instead of linear combination of moments to compute interaction matrices." "" OFF)
VP_OPTION(ENABLE_TEST_WITHOUT_DISPLAY      "" "" "Don't use display feature when testing" "" ON)
VP_OPTION(ENABLE_FULL_DOC      "" "" "Build doc with internal classes that are by default not part of the doc" "" OFF)

# Allow introduction of "visp" namespace. By default disabled to keep compat with previous versions
VP_OPTION(ENABLE_VISP_NAMESPACE "" "" "Enable visp namespace" "" OFF)
# Allow introduction of "explicit" keyword. By default disabled to keep compat with previous versions
VP_OPTION(ENABLE_EXPLICIT_KEYWORD "" "" "Enable c++ explicit keyword" "" OFF)
# Enable the vpImageTools::warp() methods
VP_OPTION(ENABLE_IMAGE_TOOLS_WARP "" "" "Enable vpImageTools::warp() methods" "" ON)

if(ENABLE_SOLUTION_FOLDERS)
  set_property(GLOBAL PROPERTY USE_FOLDERS ON)
  set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
endif()

if(ENABLE_TEST_WITHOUT_DISPLAY)
  set(SHORT_OPTION_TO_DISABLE_DISPLAY "-d")
   # catch does not support passing -d as argument as it is already reserved
  set(LONG_OPTION_TO_DISABLE_DISPLAY "--no-display")
endif()

# Check for Inria's robot drivers
VP_CHECK_PACKAGE(RAW1394)
VP_CHECK_PACKAGE(RT)
VP_CHECK_PACKAGE(CALINUX)
VP_CHECK_PACKAGE(IRISA)
# check for linux/parport.h
VP_CHECK_PACKAGE(PARPORT)
# OpenGL
VP_CHECK_PACKAGE(OpenGL)
# for pioneer
VP_CHECK_PACKAGE(RT)
VP_CHECK_PACKAGE(DL)
# for Afma6 calibration data
VP_CHECK_PACKAGE(Afma6_data)
if(AFMA6_DATA_FOUND)
  set(VISP_AFMA6_DATA_PATH ${AFMA6_DATA_PATH})
else()
  set(VISP_AFMA6_DATA_PATH "")
endif()
# for Viper850 calibration data
VP_CHECK_PACKAGE(Viper850_data)
if(VIPER850_DATA_FOUND)
  set(VISP_VIPER850_DATA_PATH ${VIPER850_DATA_PATH})
else()
  set(VISP_VIPER850_DATA_PATH "")
endif()
# for Viper650 calibration data
VP_CHECK_PACKAGE(Viper650_data)
if(VIPER650_DATA_FOUND)
  set(VISP_VIPER650_DATA_PATH ${VIPER650_DATA_PATH})
else()
  set(VISP_VIPER650_DATA_PATH "")
endif()

find_host_program(XRANDR xrandr)

VP_CHECK_PACKAGE(C99)

VP_OPTION(USE_AFMA6       ""          ""    "Include Afma6 robot support"      "" ON IF (RAW1394_FOUND AND RT_FOUND AND CALINUX_FOUND AND IRISA_FOUND AND NOT WINRT AND NOT IOS))
VP_OPTION(USE_VIPER650    ""          ""    "Include Viper s650 robot support" "" ON IF (RAW1394_FOUND AND RT_FOUND AND CALINUX_FOUND AND IRISA_FOUND AND NOT WINRT AND NOT IOS))
VP_OPTION(USE_VIPER850    ""          ""    "Include Viper s850 robot support" "" ON IF (RAW1394_FOUND AND RT_FOUND AND CALINUX_FOUND AND IRISA_FOUND AND NOT WINRT AND NOT IOS))
VP_OPTION(USE_UR_RTDE     ur_rtde     QUIET "Include Universal Robot RTDE C++ interface support for UR robots" "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_VIRTUOSE    Virtuose    ""    "Include Virtuose SDK support for Haption devices" "" ON IF NOT WINRT)
VP_OPTION(USE_ARSDK       ARSDK       QUIET "Include Parrot ARSDK support"     "" ON IF NOT WINRT AND NOT IOS)
if(USE_ARSDK)
  VP_OPTION(USE_FFMPEG    FFMPEG       ""    "Include ffmpeg support for Parrot Bebop2"  "" ON)
endif()
VP_OPTION(USE_FRANKA      Franka      QUIET "Include libfranka SDK support for Franka robots" "" ON IF NOT WINRT AND NOT IOS)
# Note: libfranka needs c++14 option to build, but to use the library c++11 is enough.
# That's why, setting USE_CXX_STANDARD=11 (which is the default) allows to use libfranka.
VP_OPTION(USE_JACOSDK     JacoSDK     ""    "Include Kinova Jaco SDK support"  "" ON IF NOT MINGW AND NOT APPLE AND NOT WINRT AND NOT IOS)
VP_OPTION(USE_MAVSDK      MAVSDK      QUIET "Include mavsdk support"           "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_DC1394      DC1394      ""    "Include dc1394 support"           "" ON IF UNIX AND NOT WINRT AND NOT IOS)
VP_OPTION(USE_V4L2        V4L2        ""    "Include v4l2 support"             "" ON IF UNIX AND NOT WINRT AND NOT IOS)
VP_OPTION(USE_FLYCAPTURE  FlyCapture  ""    "Include FlyCapture SDK support for FLIR cameras" "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_PYLON       Pylon       ""    "Include Pylon SDK support for Basler cameras" "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_UEYE        Ueye        ""    "Include uEye SDK support for IDS cameras" "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_COMEDI      Comedi      ""    "Include comedi (linux control and measurement device interface) support" "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_FTIITSDK    FTIITSDK    ""    "Include IIT force-torque SDK support" "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_BICLOPS     BICLOPS     ""    "Include biclops support"          "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_PTU46       PTU46       ""    "Include ptu-46 support"           "" ON IF UNIX AND NOT WINRT AND NOT IOS)
VP_OPTION(USE_FLIRPTUSDK  FlirPtuSDK  ""    "Include Flir PTU SDK support"     "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_CMU1394     CMU1394     ""    "Include cmu1494 support"          "" ON IF WIN32 AND NOT WINRT AND NOT IOS)
VP_OPTION(USE_QUALISYS    Qualisys    ""    "Include Qualisys SDK support"     "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_VICON       Vicon       ""    "Include Vicon SDK support"        "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_GDI         GDI         ""    "Include gdi support"              "" ON IF WIN32 AND NOT WINRT AND NOT IOS)
VP_OPTION(USE_DIRECT3D    DIRECT3D    ""    "Include d3d support"             "" ON IF WIN32 AND NOT WINRT AND NOT IOS)
#VP_OPTION(USE_DIRECTSHOW  DIRECTSHOW  ""    "Include dshow support"            "" ON IF WIN32 AND NOT WINRT AND NOT IOS)

VP_OPTION(USE_OPENMP      OpenMP      ""    "Include openmp support"           "" ON)
VP_OPTION(USE_EIGEN3      Eigen3      QUIET "Include eigen3 support"           "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_COIN3D      Coin3D      ""    "Include coin3d support"           "" ON IF OPENGL_FOUND AND NOT WINRT AND NOT IOS)
VP_OPTION(USE_PANDA3D     "Panda3D;MyPanda3D;COMPONENTS;Core;Contrib;Direct;Egg;Framework;TinyDisplay" QUIET "Include Panda3D support"          "" ON IF NOT IOS)
VP_OPTION(USE_YARP        YARP        QUIET "Include yarp support"             "YARP_DIR" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_OGRE        OGRE        QUIET "Include Ogre3D support"           "OGRE_DIR" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_OIS         OIS         QUIET "Include Ogre3D/ois support"       "OIS_DIR"  ON IF USE_OGRE AND NOT WINRT AND NOT IOS)
VP_OPTION(USE_LIBFREENECT LIBFREENECT ""    "Include libfreenect support"      "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_LIBUSB_1    LIBUSB_1    ""    "Include libusb-1 support"         "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_REALSENSE2  RealSense2  ""    "Include RealSense2 SDK support"   "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_OCCIPITAL_STRUCTURE   Occipital_Structure   ""    "Include Occipital Structure SDK support" "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_SOWIN       SOWIN       ""    "Include Coin/SoWin support"   "" OFF IF (WIN32 AND USE_COIN3D) AND NOT WINRT AND NOT IOS)
# Check for SoQt 1.6.0 linked to Qt5 or older version with SOQT
VP_OPTION(USE_SOQT        "SoQt;SOQT" QUIET "Include Coin/SoQt support"    "" OFF IF USE_COIN3D AND NOT WINRT AND NOT IOS)
if(SOQT_FOUND) # SoQt < 1.6.0 that depends on Qt4 was found. We need an explicit Qt4 search
  VP_OPTION(USE_QT        Qt          ""    "Include Coin/SoQt/Qt support" "" ON  IF USE_SOQT AND NOT WINRT AND NOT IOS)
endif()
VP_OPTION(USE_SOXT        SOXT        ""    "Include Coin/SoXt support"    "" OFF IF USE_COIN3D AND NOT WINRT AND NOT IOS)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
VP_OPTION(USE_THREADS     Threads     ""    "Include std::thread support"  "" ON)

VP_OPTION(USE_XML2        LibXml2     ""    "Include libxml2 support"      "" ON IF NOT WINRT)
if(USE_XML2 AND WIN32)
  # libxml2 needs iconv on windows
  VP_OPTION(USE_ICONV        Iconv     ""    "Include Iconv support"      "" ON IF NOT WINRT)
endif()

if(CMAKE_TOOLCHAIN_FILE)
  # Find opencv2.framework for ios and naoqi
  VP_OPTION(USE_OPENCV      "MyOpenCV" QUIET "Include OpenCV support" "OpenCV_DIR;OpenCV_FOUND;OPENCV_FOUND" ON)
else()
  VP_OPTION(USE_OPENCV      "OpenCV;MyOpenCV" QUIET "Include OpenCV support" "OpenCV_DIR;OpenCV_FOUND;OPENCV_FOUND" ON)
endif()
VP_OPTION(USE_ZLIB        ZLIB         ""    "Include zlib support"         "" ON IF NOT WINRT AND NOT IOS)
set(X11_ADVANCED "X11_xcb_util_LIB;X11_xcb_util_INCLUDE_PATH;X11_xcb_xfixes_INCLUDE_PATH;X11_xcb_xfixes_LIB")
VP_OPTION(USE_X11         X11          ""    "Include X11 support"          "${X11_ADVANCED}" ON IF NOT WINRT AND NOT IOS)
# Workaround, see below. The following line searching for GKT2 has to be moved after searching for PCL
#VP_OPTION(USE_GTK2        GTK2         ""    "Include gtk2 support"         "" OFF IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_JPEG        JPEG         ""    "Include jpeg support"         "" ON IF NOT IOS)
VP_OPTION(USE_PNG         PNG          ""    "Include png support"          "" ON IF NOT IOS)
# To control Pioneer mobile robots, under UNIX we need Aria and std::threads, rt and dl 3rd party libraries
VP_OPTION(USE_ARIA        ARIA         ""    "Include aria support"         "" ON IF NOT WINRT AND NOT IOS)
#VP_OPTION(USE_RT          RT           ""    "Include rt support"           "" ON)
#VP_OPTION(USE_DL          DL           ""    "Include dl support"           "" ON)
# bar codes
VP_OPTION(USE_ZBAR        ZBAR         ""    "Include zbar support"         "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_DMTX        DMTX         ""    "Include dmtx support"         "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_PCL         PCL          QUIET "Include Point Cloud Library support" "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_TENSORRT    TensorRT     ""    "Include TensorRT support"     "" ON IF NOT WINRT AND NOT IOS)
VP_OPTION(USE_NLOHMANN_JSON nlohmann_json QUIET "Include nlohmann json support" "" ON)

if(USE_EIGEN3)
  # Since Eigen 5.0.0, EIGEN3_INCLUDE_DIRS is not defined anymore.
  # We need to get the include dir from the imported target Eigen3::Eigen.
  vp_find_eigen3(EIGEN3_INCLUDE_DIRS Eigen3_VERSION)
endif()

if(USE_PCL)
  # PCL is used in modules gui, sensor and mbt.
  # In these modules we cannot directly use PCL_INCLUDE_DIRS and PCL_LIBRARIES using:
  #   list(APPEND opt_incs ${PCL_INCLUDE_DIRS})
  #   list(APPEND opt_libs ${PCL_LIBRARIES})
  # Using PCL_LIBRARIES works to build visp libraries, embedded examples, demos, tests and tutorials thanks to the
  # components. But when examples, demos, tests and tutorials are build outside ViSP workspace as independent projects
  # that are using ViSP as 3rd-party we lead to build issues due to VTK headers and libraries that are not found.
  # That's why here, we are using vp_find_pcl() macro that will set PCL_DEPS_INCLUDE_DIRS, PCL_DEPS_LIBRARIES
  # and PCL_DEPS_COMPILE_OPTIONS that contains also VTK material location.
  # Compile options are needed to overcome this issue https://github.com/lagadic/visp/issues/1681
  #   Potential runtime error due to aligned malloc mismatch! You likely have to compile your code with AVX enabled
  #   or define EIGEN_MAX_ALIGN_BYTES=32
  # Note that according to https://github.com/PointCloudLibrary/pcl/issues/5806#issuecomment-2900397246
  # it is not a good practice to use PCL_DEFINITIONS and PCL_COMPILE_OPTIONS. The following macro
  # gets rather compile options from interfaces.
  vp_find_pcl(PCL_LIBRARIES PCL_DEPS_INCLUDE_DIRS PCL_DEPS_LIBRARIES PCL_DEPS_COMPILE_OPTIONS)
  set(PCL_REQUIRED_COMPONENTS "common;filters;io;visualization;segmentation")
  # Create cmake vars corresponding to pcl components used by ViSP like VISP_HAVE_PCL_COMMON...
  vp_detect_required_pcl_components(PCL_REQUIRED_COMPONENTS)

  # USE_NLOHMANN_JSON is set to ON if nlohmann_json is installed and found thanks to nlohmann_jsonConfig.cmake.
  # VTK that is a PCL 3rd party embbed also a built in version of nlohmann_json.
  # Here we add a specific case to consider the nlohmann version coming from VTK when the system version is not found
  if(NOT USE_NLOHMANN_JSON)
    if(VISP_HAVE_NLOHMANN_JSON_FROM_VTK)
      message(WARNING "json 3rd party is detected and used as a VTK 3rd party which is itself a PCL 3rd party. Thus we enable nlohmann json usage turning USE_NLOHMANN_JSON=ON.")
      unset(USE_NLOHMANN_JSON)
      set(USE_NLOHMANN_JSON ON CACHE BOOL "Include nlohmann json support thanks to VTK" FORCE)
    endif()
  endif()
endif()

# ----------------------------------------------------------------------------
# Workaround for the following issue that occured on FreeBSD 14.2 with pcl-1.15.0
# and vtk-9.5.0. It occurs when GTK2 is searched before PCL. Searching first PCL
# and after GTK2 does the trick.
# The following error seems due to the fact that FindGTK2.cmake is seraching for
# freetype2.
#
# See PCL issue: https://github.com/PointCloudLibrary/pcl/issues/6301
#
#  CMake Error at /usr/local/lib/cmake/freetype/freetype-config.cmake:42 (message):
#    Some (but not all) targets in this export set were already defined.
#
#    Targets Defined: Freetype::Freetype
#
#    Targets not yet defined: freetype
#
#  Call Stack (most recent call first):
#    /usr/local/lib/cmake/vtk-9.5/FindFreetype.cmake:98 (find_package)
#    /usr/local/lib/cmake/vtk-9.5/VTK-vtk-module-find-packages.cmake:1061 (find_package)
#    /usr/local/lib/cmake/vtk-9.5/vtk-config.cmake:170 (include)
#    /usr/local/share/pcl-1.15/PCLConfig.cmake:255 (find_package)
#    /usr/local/share/pcl-1.15/PCLConfig.cmake:304 (find_VTK)
#    /usr/local/share/pcl-1.15/PCLConfig.cmake:555 (find_external_library)
#    cmake/VISPUtils.cmake:549 (find_package)
#    CMakeLists.txt:674 (VP_OPTION)
# ----------------------------------------------------------------------------
VP_OPTION(USE_GTK2        GTK2         ""    "Include gtk2 support"         "" OFF IF NOT WINRT AND NOT IOS)

# ----------------------------------------------------------------------------
# Handle OpenCV 2.4.8 as minimal version
# ----------------------------------------------------------------------------
if(USE_OPENCV)
  if(OpenCV_VERSION)
    if(OpenCV_VERSION VERSION_LESS "2.4.8")
      message(WARNING "OpenCV 3rd party was detected but its version ${OpenCV_VERSION} is too old. Thus we disable OpenCV usage turning USE_OPENCV=OFF.")
      unset(USE_OPENCV)
      set(USE_OPENCV OFF CACHE BOOL "Include OpenCV support" FORCE)
    endif()
  else()
    message(WARNING "OpenCV 3rd party was detected but its version cannot be found or is too old. Thus we disable OpenCV usage turning USE_OPENCV=OFF.")
    unset(USE_OPENCV)
    set(USE_OPENCV OFF CACHE BOOL "Include OpenCV support" FORCE)
  endif()
endif()

# ----------------------------------------------------------------------------
# Handle cxx standard depending on specific 3rd parties. Should be before module parsing and VISP3rdParty.cmake include
# ----------------------------------------------------------------------------
# if c++ standard is not at leat c++17, force 3rd parties that require at least c++17 to OFF
if(VISP_CXX_STANDARD LESS VISP_CXX_STANDARD_17)
  if(USE_MAVSDK)
    message(WARNING "mavsdk 3rd party was detected and needs at least c++17 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable MAVSDK usage turning USE_MAVSDK=OFF.")
    unset(USE_MAVSDK)
    set(USE_MAVSDK OFF CACHE BOOL "Include mavsdk support for mavlink compatible devices" FORCE)
  endif()
  if(USE_PCL AND (PCL_VERSION VERSION_GREATER_EQUAL 1.15.0))
    # pcl >= 1.15.0 requires c++17
    message(WARNING "pcl 3rd party was detected and needs at least c++17 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable pcl usage turning USE_PCL=OFF.")
    unset(USE_PCL)
    set(USE_PCL OFF CACHE BOOL "Include pcl support" FORCE)
  endif()
endif()

if(VISP_CXX_STANDARD LESS VISP_CXX_STANDARD_14)
  if(USE_FTIITSDK)
    message(WARNING "IIT force-torque SDK 3rd party was detected and needs at least c++14 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable IIT force-torque usage turning USE_FTIITSDK=OFF.")
    unset(USE_FTIITSDK)
    set(USE_FTIITSDK OFF CACHE BOOL "Include IIT force-torque SDK support" FORCE)
  endif()
  if(USE_EIGEN3 AND (Eigen3_VERSION VERSION_GREATER_EQUAL 5.0.0))
    # Eigen >= 5.0.0 requires c++14
    message(WARNING "Eigen3 3rd party was detected and needs at least c++14 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable Eigen3 usage turning USE_EIGEN3=OFF.")
    unset(USE_EIGEN3)
    set(USE_EIGEN3 OFF CACHE BOOL "Include Eigen3 support" FORCE)
  endif()
  if(USE_PCL AND (PCL_VERSION VERSION_GREATER 1.9.1))
    # pcl > 1.9.1 requires c++14
    message(WARNING "pcl 3rd party was detected and needs at least c++14 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable pcl usage turning USE_PCL=OFF.")
    unset(USE_PCL)
    set(USE_PCL OFF CACHE BOOL "Include pcl support" FORCE)
  endif()
endif()

if(VISP_CXX_STANDARD LESS VISP_CXX_STANDARD_11)
  if(USE_OPENCV)
    message(WARNING "OpenCV 3rd party was detected and needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable OpenCV usage turning USE_OPENCV=OFF.")
    unset(USE_OPENCV)
    set(USE_OPENCV OFF CACHE BOOL "Include OpenCV support" FORCE)
  endif()
  if(USE_NLOHMANN_JSON)
    message(WARNING "nlohmann json 3rd party was detected and needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable nlohmann json usage turning USE_NLOHMANN_JSON=OFF.")
    unset(USE_NLOHMANN_JSON)
    set(USE_NLOHMANN_JSON OFF CACHE BOOL "Include nlohmann json support" FORCE)
  endif()
  if(USE_REALSENSE2)
    message(WARNING "librealsense2 3rd party was detected and needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable realsense2 usage turning USE_REALSENSE2=OFF.")
    unset(USE_REALSENSE2)
    set(USE_REALSENSE2 OFF CACHE BOOL "Include librealsense2 support" FORCE)
  endif()
  if(USE_XML2)
    message(WARNING "libxml2 3rd party was detected and needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable libxml2 usage turning USE_XML2=OFF.")
    unset(USE_XML2)
    set(USE_XML2 OFF CACHE BOOL "Include libxml2 support" FORCE)
  endif()
  if(USE_QUALISYS)
    message(WARNING "Qualisys SDK 3rd party was detected and needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable qualisys usage turning USE_QUALISYS=OFF.")
    unset(USE_QUALISYS)
    set(USE_QUALISYS OFF CACHE BOOL "Include Qualisys SDK support" FORCE)
  endif()
  if(USE_BICLOPS)
    message(WARNING "Biclops SDK 3rd party was detected and needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable biclops usage turning USE_BICLOPS=OFF.")
    unset(USE_BICLOPS)
    set(USE_BICLOPS OFF CACHE BOOL "Include biclops support" FORCE)
  endif()
  if(USE_ARSDK)
    message(WARNING "Parrot ARSDK 3rd party was detected and needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable ARSDK usage turning USE_ARSDK=OFF.")
    unset(USE_ARSDK)
    set(USE_ARSDK OFF CACHE BOOL "Include Parrot ARSDK support" FORCE)
  endif()
  if(USE_THREADS)
    message(WARNING "std::thread was detected but needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable std::thread usage turning USE_THREADS=OFF.")
    unset(USE_THREADS)
    set(USE_THREADS OFF CACHE BOOL "Include std::thread support" FORCE)
  endif()
  if(USE_PANDA3D)
    message(WARNING "Panda3D was detected but needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable Panda3D usage turning USE_PANDA3D=OFF.")
    unset(USE_PANDA3D)
    set(USE_PANDA3D OFF CACHE BOOL "Include Panda3D support" FORCE)
  endif()
  if(USE_OGRE)
    message(WARNING "Ogre3D was detected but needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable Ogre3D usage turning USE_OGRE=OFF.")
    unset(USE_OGRE)
    set(USE_OGRE OFF CACHE BOOL "Include Ogre3D support" FORCE)
  endif()
  if(USE_FRANKA)
    message(WARNING "libfranka was detected but needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable libfranka usage turning USE_FRANKA=OFF.")
    unset(USE_FRANKA)
    set(USE_FRANKA OFF CACHE BOOL "Include libfranka SDK support for Franka robots" FORCE)
  endif()
  if(USE_UR_RTDE)
    message(WARNING "Universal rtde library was detected but needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable rtde usage turning USE_UR_RTDE=OFF.")
    unset(USE_UR_RTDE)
    set(USE_UR_RTDE OFF CACHE BOOL "Include Universal Robot RTDE C++ interface support for UR robots" FORCE)
  endif()
endif()

if(UNIX AND Threads_FOUND)
  # Apriltag on unix needs native pthread. On windows we are using pthread built-in
  set(USE_PTHREAD ON) # for AprilTag only
endif()

# ----------------------------------------------------------------------------
# Build-in 3rd parties. Should be after c++ standard potential modification
# ----------------------------------------------------------------------------
# Since C99 is not supported by MSVC 2010 or prior, we disable apriltag if MSVC < 2012
VP_OPTION(WITH_APRILTAG   ""           ""    "Use AprilTag as built-in library"  "" ON IF (USE_THREADS OR USE_PTHREAD) AND (NOT WINRT) AND (NOT MSVC_VERSION LESS 1700))
VP_OPTION(WITH_APRILTAG_BIG_FAMILY ""  ""    "Use AprilTag big family (41h12, 48h12, 49h12, 52h13)" "" OFF IF WITH_APRILTAG)
VP_OPTION(WITH_MINIZ      ""           ""    "Use npz related I/O as built-in functions"   "" ON)
VP_OPTION(WITH_ATIDAQ     ""           ""    "Use atidaq-c as built-in library"  "" ON IF USE_COMEDI AND NOT WINRT)
VP_OPTION(WITH_CLIPPER    ""           ""    "Use clipper as built-in library"   "" ON IF USE_OPENCV)
VP_OPTION(WITH_LAPACK     ""           ""    "Use lapack as built-in library"    "" ON IF NOT USE_LAPACK)
VP_OPTION(WITH_QBDEVICE   ""           ""    "Use qbdevice-api as built-in library" "" ON IF (NOT WINRT) AND (NOT IOS))
VP_OPTION(WITH_TAKKTILE2  ""           ""    "Use Right Hand takktile2 driver as built-in library"   "" ON IF (NOT WIN32) AND (NOT WINRT) AND (NOT IOS) AND (NOT ANDROID))
VP_OPTION(WITH_CATCH2     ""           ""    "Use catch2 built-in library" "" ON)
VP_OPTION(WITH_POLOLU     ""           ""    "Use rapa pololu as built-in library" "" ON IF (NOT WINRT) AND (NOT IOS) AND (NOT ANDROID))
VP_OPTION(WITH_PUGIXML    ""           ""    "Use pugixml built-in third-party" "" ON)
VP_OPTION(WITH_SIMDLIB    ""           ""    "Use simdlib built-in third-party" "" ON)
VP_OPTION(WITH_STBIMAGE   ""           ""    "Use std_image built-in third-party" "" ON)
VP_OPTION(WITH_TINYEXR    ""           ""    "Use tinyexr built-in third-party" "" ON)

if(VISP_CXX_STANDARD LESS VISP_CXX_STANDARD_11)
  if(WITH_POLOLU)
    message(WARNING "pololu 3rd party needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable pololu usage turning WITH_POLOLU=OFF.")
    unset(WITH_POLOLU)
    set(WITH_POLOLU OFF CACHE BOOL "Build rapa pololu as built-in library" FORCE)
  endif()
  if(WITH_QBDEVICE)
    message(WARNING "qbdevice-api 3rd party needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable qbdevice usage turning WITH_QBDEVICE=OFF.")
    unset(WITH_QBDEVICE)
    set(WITH_QBDEVICE OFF CACHE BOOL "Build rapa pololu as built-in library" FORCE)
  endif()
  if(WITH_TAKKTILE2)
    message(WARNING "Right Hand takktile2 3rd party needs at least c++11 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable takktile2 usage turning WITH_TAKKTILE2=OFF.")
    unset(WITH_TAKKTILE2)
    set(WITH_TAKKTILE2 OFF CACHE BOOL "Build rapa pololu as built-in library" FORCE)
  endif()
endif()

if(VISP_CXX_STANDARD LESS VISP_CXX_STANDARD_14)
  if(WITH_CATCH2)
    message(WARNING "catch2 3rd party needs at least c++14 standard compiler flag while you have set c++${USE_CXX_STANDARD}. Thus we disable catch2 usage turning WITH_CATCH2=OFF.")
    unset(WITH_CATCH2)
    set(WITH_CATCH2 OFF CACHE BOOL "Use catch2 built-in library" FORCE)
  endif()
endif()

# ----------------------------------------------------------------------------
# Check for specific functions. Should be after cxx standard detection in VISPDetectCXXStandard.cmake and
# potential modification depending on pcl, realsense2, libfranka
# ----------------------------------------------------------------------------
VP_CHECK_PACKAGE(IsNaN)
VP_CHECK_PACKAGE(IsInf)
VP_CHECK_PACKAGE(Round)
VP_CHECK_PACKAGE(Erfc)
VP_CHECK_PACKAGE(Strtof)
VP_CHECK_PACKAGE(IsFinite)
VP_CHECK_PACKAGE(Log1p)

#----------------------------------------------------------------------
# For Dart server and tests
# We use CDash set through CTestConfig.cmake file
# Dashboards are sent to https://cdash-ci.inria.fr/index.php?project=ViSP
#----------------------------------------------------------------------
if(BUILD_TESTS OR BUILD_EXAMPLES OR BUILD_DEMOS)
  enable_testing()
  mark_as_advanced(DART_ROOT)
  mark_as_advanced(BUILD_TESTING)
endif()

#----------------------------------------------------------------------
# Try to find doxygen for documentation generation
# Use "make visp_doc" target to generate the documentation
#----------------------------------------------------------------------
find_package(Doxygen)
if(DOXYGEN_FOUND)
  set(VISP_HAVE_DOXYGEN "yes")        # for header vpConfig.h
  ## we need latex for doxygen because of the formulas
  find_package(LATEX)
  if(NOT LATEX_COMPILER)
    message(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user interaction on doxy run.")
  endif()
  if(NOT MAKEINDEX_COMPILER)
    message(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
  endif()
  if(NOT DVIPS_CONVERTER)
    message(STATUS "dvips command DVIPS_CONVERTER not found but usually required.")
  endif()

  # set vars used in doxygen config file
  # - DOXYGEN_STRIP_FROM_INC_PATH corresponding to STRIP_FROM_INC_PATH in the doxy file
  set(DOXYGEN_STRIP_FROM_INC_PATH "")
  foreach(m ${VISP_MODULES_BUILD} ${VISP_MODULES_DISABLED_USER} ${VISP_MODULES_DISABLED_AUTO} ${VISP_MODULES_DISABLED_FORCE})
    if(m MATCHES "^visp_")
      set(DOXYGEN_STRIP_FROM_INC_PATH "${DOXYGEN_STRIP_FROM_INC_PATH} \\ \n\t\t\t \"${VISP_MODULE_${m}_LOCATION}/include\"")
    endif()
  endforeach()
  # - DOXYGEN_IMAGE_PATH corresponding to IMAGE_PATH in the doxy file
  set(DOXYGEN_IMAGE_PATH "\"${VISP_SOURCE_DIR}/doc/image\"")
  if(VISP_CONTRIB_MODULES_PATH)
    foreach(contrib ${VISP_CONTRIB_MODULES_PATH})
      set(image_path_ "${VISP_CONTRIB_MODULES_PATH}/doc/image")
      if(EXISTS ${image_path_})
        set(DOXYGEN_IMAGE_PATH "${DOXYGEN_IMAGE_PATH} \\ \n\t\t\t \"${image_path_}\"")
      endif()
    endforeach()
  endif()
  # - DOXYGEN_CITE_BIB_FILES corresponding to CITE_BIB_FILES in the doxy file
  set(DOXYGEN_CITE_BIB_FILES "\"${VISP_SOURCE_DIR}/doc/biblio/references.bib\"")
  if(VISP_CONTRIB_MODULES_PATH)
    set(cite_bib_file_ "${VISP_CONTRIB_MODULES_PATH}/doc/biblio/references.bib")
    if(EXISTS ${cite_bib_file_})
      set(DOXYGEN_CITE_BIB_FILES "${DOXYGEN_CITE_BIB_FILES} \\ \n\t\t\t \"${cite_bib_file_}\"")
    endif()
  endif()
  # - DOXYGEN_SHOULD_SKIP_THIS var
  if (ENABLE_FULL_DOC)
    set(DOXYGEN_SHOULD_SKIP_THIS "")
  else()
    set(DOXYGEN_SHOULD_SKIP_THIS "DOXYGEN_SHOULD_SKIP_THIS")
  endif()
  # - DOXYGEN_USE_MATHJAX corresponding to USE_MATHJAX in the doxy file
  VP_OPTION(USE_MATHJAX  "" "" "Use MathJax to generate latex formula" "" OFF)
  if (USE_MATHJAX)
    set(DOXYGEN_USE_MATHJAX "YES")
  else()
    set(DOXYGEN_USE_MATHJAX "NO")
  endif()

  if(DOXYGEN_AWESOME_DIR)
    set(DOXYGEN_HTML_EXTRA_STYLESHEET "${DOXYGEN_AWESOME_DIR}/doxygen-awesome.css ${VISP_SOURCE_DIR}/doc/doxygen-awesome.custom.css")
  endif()

  # HTML version of the doc
  set(DOXYGEN_GENERATE_HTML "YES")
  set(DOXYGEN_GENERATE_XML "NO")
  set(DOXYGEN_GENERATE_TEST_LIST "YES")
  set(DOXYGEN_QUIET "NO")
  set(DOXYGEN_INPUTS
    "${VISP_SOURCE_DIR}/apps"
    "${VISP_SOURCE_DIR}/demo"
    "${VISP_SOURCE_DIR}/doc"
    "${VISP_SOURCE_DIR}/example"
    "${VISP_SOURCE_DIR}/modules"
    "${VISP_SOURCE_DIR}/tutorial"
    "${VISP_BINARY_DIR}/doc"
    "${VISP_CONTRIB_MODULES_PATH}"
  )
  string (REPLACE ";" " " DOXYGEN_INPUTS "${DOXYGEN_INPUTS}")
  configure_file(${VISP_SOURCE_DIR}/doc/config-doxygen.in
    ${VISP_DOC_DIR}/config-doxygen
    @ONLY )

  # XML version  of the doc
  set(DOXYGEN_GENERATE_HTML "NO")
  set(DOXYGEN_GENERATE_XML "YES")
  set(DOXYGEN_GENERATE_TEST_LIST "NO")
  set(DOXYGEN_QUIET "YES")
  set(DOXYGEN_INPUTS
    "${VISP_SOURCE_DIR}/modules"
  )
  string (REPLACE ";" " " DOXYGEN_INPUTS "${DOXYGEN_INPUTS}")
  configure_file(${VISP_SOURCE_DIR}/doc/config-doxygen.in
    ${VISP_DOC_DIR}/config-doxygen-xml
    @ONLY )

  # set vars used in mainpage.dox.in
  # - VISP_MAINPAGE_EXTENSION
  set(VISP_MAINPAGE_EXTENSION "")
  if(VISP_CONTRIB_MODULES_PATH)
    foreach(contrib ${VISP_CONTRIB_MODULES_PATH})
      set(mainpage_ext_file_ "${contrib}/doc/mainpage_extension.doc")
      if(EXISTS ${mainpage_ext_file_})
        file(READ ${mainpage_ext_file_} mainpage_ext_content_)
        set(VISP_MAINPAGE_EXTENSION "${VISP_MAINPAGE_EXTENSION}\n${mainpage_ext_content_}")
      endif()
    endforeach()
  endif()

  configure_file(${VISP_SOURCE_DIR}/doc/mainpage.dox.in
    ${VISP_DOC_DIR}/mainpage.dox
    @ONLY )
else()
  set(VISP_HAVE_DOXYGEN "no")        # for header vpConfig.h
endif()

# ----------------------------------------------------------------------------
# Extra ViSP targets: uninstall, etc.
# ----------------------------------------------------------------------------
include(cmake/VISPExtraTargets.cmake)

# Ogre plugins and resources
include(cmake/OgreTools.cmake)
if(USE_OGRE)
  vp_set_ogre_plugin()
  vp_set_ogre_resources()
  set(VISP_HAVE_OGRE_VERSION "(${OGRE_VERSION_MAJOR}<<16 | ${OGRE_VERSION_MINOR}<<8 | ${OGRE_VERSION_PATCH})") # for vpConfig.h
endif()

#----------------------------------------------------------------------
# Add definitions
#----------------------------------------------------------------------
# With Visual Studio 2005, Microsoft deprecates the standard C library, for
# example fopen() and sprintf(), to non-portable functions fopen_s() and
# sprintf_s(). These functions are considered by Microsoft more secure. This is
# a worthwhile exercise ! The use of these deprecated functions causes a lot of
# warnings. To suppress it, we add the _CRT_SECURE_NO_DEPRECATE preprocessor
# definition
if(WIN32 AND MSVC)
  add_definitions("-D_CRT_SECURE_NO_DEPRECATE")
  add_definitions("-D_SCL_SECURE_NO_WARNINGS") # to avoid warning C4996; std::copy::_Unchecked_iterators::_Deprecate
endif()

#----------------------------------------------------------------------
# Use statically or dynamically linked CRT?
# Default: dynamic
#----------------------------------------------------------------------
if(MSVC)
   include(cmake/VISPCRTLinkage.cmake)
endif(MSVC)

#----------------------------------------------------------------------
# Create and install visp-config.1.gz man page
#----------------------------------------------------------------------
if(UNIX AND NOT ANDROID)
  find_host_program(GZIP gzip)
  if(GZIP)
    file(MAKE_DIRECTORY ${VISP_BINARY_DIR}/doc/man/man1)
    add_custom_command(
      OUTPUT ${VISP_BINARY_DIR}/doc/man/man1/visp-config.1.gz
      COMMAND ${GZIP} -9 -c ${CMAKE_CURRENT_SOURCE_DIR}/doc/man/man1/visp-config.1 > ${VISP_BINARY_DIR}/doc/man/man1/visp-config.1.gz
      DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/doc/man/man1/visp-config.1
    )
    add_custom_target(man ALL
      DEPENDS ${VISP_BINARY_DIR}/doc/man/man1/visp-config.1.gz
    )
    install(FILES
      ${VISP_BINARY_DIR}/doc/man/man1/visp-config.1.gz
      DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/man/man1
      PERMISSIONS OWNER_READ GROUP_READ WORLD_READ OWNER_WRITE
      COMPONENT dev
    )
  endif()
endif()

#----------------------------------------------------------------------
# Add 3rd-party libraries
#----------------------------------------------------------------------
include(cmake/VISP3rdParty.cmake)

# --- Java Support ---
if(BUILD_JAVA)
  if(ANDROID)
    include(cmake/android/ViSPDetectAndroidSDK.cmake)
  else()
    include(cmake/VISPDetectApacheAnt.cmake)
    if(ANT_EXECUTABLE AND NOT OPENCV_JAVA_IGNORE_ANT)
      vp_update(VISP_JAVA_SDK_BUILD_TYPE "ANT")
    elseif(NOT ANDROID)
      find_package(Java)
      if(Java_FOUND)
        include(UseJava)
        vp_update(VISP_JAVA_SDK_BUILD_TYPE "JAVA")
      endif()
    endif()
    find_package(JNI)
  endif()
endif()

if(ANDROID AND ANDROID_EXECUTABLE AND ANT_EXECUTABLE AND (ANT_VERSION VERSION_GREATER 1.7) AND (ANDROID_TOOLS_Pkg_Revision GREATER 13))
  SET(CAN_BUILD_ANDROID_PROJECTS TRUE)
else()
  SET(CAN_BUILD_ANDROID_PROJECTS FALSE)
endif()

#-----------------------------------------------------------------------------
# Add extra compilation flags
#-----------------------------------------------------------------------------
include(cmake/AddExtraCompilationFlags.cmake) # should be called after FindOpenMP and cxx standard potential changes

#----------------------------------------------------------------------
# Modules
#----------------------------------------------------------------------
include(cmake/VISPModule.cmake)

# process subdirectories
add_subdirectory(modules)

#-------------------------------------------------------------------------------
# specific things that need to be updated in vpConfig.h
#-------------------------------------------------------------------------------
VP_SET(VISP_HAVE_OPENMP      TRUE IF USE_OPENMP)
VP_SET(VISP_HAVE_OPENCV      TRUE IF (BUILD_MODULE_visp_core AND USE_OPENCV))
VP_SET(VISP_HAVE_X11         TRUE IF (BUILD_MODULE_visp_core AND USE_X11))
VP_SET(VISP_HAVE_GTK         TRUE IF (BUILD_MODULE_visp_core AND USE_GTK2))
VP_SET(VISP_HAVE_GDI         TRUE IF (BUILD_MODULE_visp_core AND USE_GDI))
VP_SET(VISP_HAVE_D3D9        TRUE IF (BUILD_MODULE_visp_core AND USE_DIRECT3D))
VP_SET(VISP_HAVE_JPEG        TRUE IF (BUILD_MODULE_visp_core AND USE_JPEG))
VP_SET(VISP_HAVE_PNG         TRUE IF (BUILD_MODULE_visp_core AND USE_PNG))
VP_SET(VISP_HAVE_YARP        TRUE IF (BUILD_MODULE_visp_core AND USE_YARP))
VP_SET(VISP_HAVE_EIGEN3      TRUE IF (BUILD_MODULE_visp_core AND USE_EIGEN3))
VP_SET(VISP_HAVE_MKL         TRUE IF (BUILD_MODULE_visp_core AND USE_MKL))
VP_SET(VISP_HAVE_NETLIB      TRUE IF (BUILD_MODULE_visp_core AND USE_NETLIB))
VP_SET(VISP_HAVE_OPENBLAS    TRUE IF (BUILD_MODULE_visp_core AND USE_OPENBLAS))
VP_SET(VISP_HAVE_ATLAS       TRUE IF (BUILD_MODULE_visp_core AND USE_ATLAS))
VP_SET(VISP_HAVE_GSL         TRUE IF (BUILD_MODULE_visp_core AND USE_GSL))
VP_SET(VISP_HAVE_LAPACK      TRUE IF (BUILD_MODULE_visp_core AND (USE_LAPACK OR WITH_LAPACK)))
VP_SET(VISP_HAVE_LAPACK_ATLAS    TRUE IF (BUILD_MODULE_visp_core AND USE_ATLAS))
VP_SET(VISP_HAVE_LAPACK_BUILT_IN TRUE IF (BUILD_MODULE_visp_core AND WITH_LAPACK))
VP_SET(VISP_HAVE_LAPACK_GSL      TRUE IF (BUILD_MODULE_visp_core AND USE_GSL))
VP_SET(VISP_HAVE_LAPACK_MKL      TRUE IF (BUILD_MODULE_visp_core AND USE_MKL))
VP_SET(VISP_HAVE_LAPACK_NETLIB   TRUE IF (BUILD_MODULE_visp_core AND USE_NETLIB))
VP_SET(VISP_HAVE_LAPACK_OPENBLAS TRUE IF (BUILD_MODULE_visp_core AND USE_OPENBLAS))

# Keep VISP_HAVE_PTHREAD for the moment for compat and for vpMutex and vpThread deprecated classes
VP_SET(VISP_HAVE_PTHREAD     TRUE IF (BUILD_MODULE_visp_core AND (USE_PTHREAD AND UNIX)))

VP_SET(VISP_HAVE_THREADS     TRUE IF (BUILD_MODULE_visp_core AND USE_THREADS))
VP_SET(VISP_HAVE_XML2        TRUE IF (BUILD_MODULE_visp_core AND ((USE_XML2 AND WIN32 AND USE_ICONV) OR (USE_XML2 AND NOT WIN32))))
VP_SET(VISP_HAVE_PCL         TRUE IF (BUILD_MODULE_visp_core AND USE_PCL))
VP_SET(VISP_HAVE_TENSORRT    TRUE IF (BUILD_MODULE_visp_core AND USE_TENSORRT))
VP_SET(VISP_HAVE_NLOHMANN_JSON          TRUE IF (BUILD_MODULE_visp_core AND USE_NLOHMANN_JSON))
VP_SET(VISP_HAVE_NLOHMANN_JSON_FROM_VTK TRUE IF (BUILD_MODULE_visp_core AND VISP_HAVE_NLOHMANN_JSON_FROM_VTK))

VP_SET(VISP_HAVE_OGRE        TRUE IF (BUILD_MODULE_visp_ar AND USE_OGRE))
VP_SET(VISP_HAVE_OIS         TRUE IF (BUILD_MODULE_visp_ar AND USE_OIS))
VP_SET(VISP_HAVE_COIN3D      TRUE IF (BUILD_MODULE_visp_ar AND USE_COIN3D))
VP_SET(VISP_HAVE_SOWIN       TRUE IF (BUILD_MODULE_visp_ar AND USE_SOWIN))
VP_SET(VISP_HAVE_SOXT        TRUE IF (BUILD_MODULE_visp_ar AND USE_SOXT))
VP_SET(VISP_HAVE_SOQT        TRUE IF (BUILD_MODULE_visp_ar AND USE_SOQT))
VP_SET(VISP_HAVE_QT          TRUE IF (BUILD_MODULE_visp_ar AND USE_QT))
VP_SET(VISP_HAVE_PANDA3D     TRUE IF (BUILD_MODULE_visp_ar AND USE_PANDA3D))

VP_SET(VISP_HAVE_ZBAR        TRUE IF (BUILD_MODULE_visp_detection AND USE_ZBAR))
VP_SET(VISP_HAVE_DMTX        TRUE IF (BUILD_MODULE_visp_detection AND USE_DMTX))

VP_SET(VISP_HAVE_AFMA6       TRUE IF (BUILD_MODULE_visp_robot AND USE_AFMA6))
VP_SET(VISP_HAVE_VIPER650    TRUE IF (BUILD_MODULE_visp_robot AND USE_VIPER650))
VP_SET(VISP_HAVE_VIPER850    TRUE IF (BUILD_MODULE_visp_robot AND USE_VIPER850))
VP_SET(VISP_HAVE_UR_RTDE     TRUE IF (BUILD_MODULE_visp_robot AND USE_UR_RTDE))
VP_SET(VISP_HAVE_FRANKA      TRUE IF (BUILD_MODULE_visp_robot AND USE_FRANKA))
VP_SET(VISP_HAVE_JACOSDK     TRUE IF (BUILD_MODULE_visp_robot AND USE_JACOSDK))
VP_SET(VISP_HAVE_MAVSDK      TRUE IF (BUILD_MODULE_visp_robot AND USE_MAVSDK))
VP_SET(VISP_HAVE_BICLOPS     TRUE IF (BUILD_MODULE_visp_robot AND USE_BICLOPS))
VP_SET(VISP_HAVE_PTU46       TRUE IF (BUILD_MODULE_visp_robot AND USE_PTU46))
VP_SET(VISP_HAVE_FLIR_PTU_SDK TRUE IF (BUILD_MODULE_visp_robot AND USE_FLIRPTUSDK))
VP_SET(VISP_HAVE_ARSDK       TRUE IF (BUILD_MODULE_visp_robot AND USE_ARSDK))
VP_SET(VISP_HAVE_FFMPEG      TRUE IF (BUILD_MODULE_visp_robot AND USE_FFMPEG))
#VP_SET(VISP_HAVE_PIONEER     TRUE IF (BUILD_MODULE_visp_robot AND USE_ARIA))
if(BUILD_MODULE_visp_robot AND USE_ARIA)
  if(UNIX AND USE_THREADS AND RT_FOUND AND DL_FOUND)
    set(VISP_HAVE_PIONEER TRUE)
  elseif(NOT UNIX)
    set(VISP_HAVE_PIONEER TRUE)
  endif()
endif()
#VP_SET(VISP_HAVE_VIRTUOSE    TRUE IF (BUILD_MODULE_visp_robot AND USE_VIRTUOSE))
if(BUILD_MODULE_visp_robot AND USE_VIRTUOSE)
  if(UNIX AND USE_THREADS AND RT_FOUND AND DL_FOUND)
    set(VISP_HAVE_VIRTUOSE TRUE)
  elseif(NOT UNIX)
    set(VISP_HAVE_VIRTUOSE TRUE)
  endif()
endif()
VP_SET(VISP_HAVE_COIN3D      TRUE IF (BUILD_MODULE_visp_robot AND USE_COIN3D))

VP_SET(VISP_HAVE_V4L2        TRUE IF (BUILD_MODULE_visp_sensor AND USE_V4L2))
VP_SET(VISP_HAVE_DC1394      TRUE IF (BUILD_MODULE_visp_sensor AND USE_DC1394))
VP_SET(VISP_HAVE_CMU1394     TRUE IF (BUILD_MODULE_visp_sensor AND USE_CMU1394))
VP_SET(VISP_HAVE_DIRECTSHOW  TRUE IF (BUILD_MODULE_visp_sensor AND USE_DIRECTSHOW))
VP_SET(VISP_HAVE_LIBFREENECT TRUE IF (BUILD_MODULE_visp_sensor AND USE_LIBFREENECT))
VP_SET(VISP_HAVE_LIBUSB_1    TRUE IF (BUILD_MODULE_visp_sensor AND USE_LIBUSB_1))
VP_SET(VISP_HAVE_REALSENSE2  TRUE IF (BUILD_MODULE_visp_sensor AND USE_REALSENSE2))
VP_SET(VISP_HAVE_OCCIPITAL_STRUCTURE   TRUE IF (BUILD_MODULE_visp_sensor AND USE_OCCIPITAL_STRUCTURE))
VP_SET(VISP_HAVE_FLYCAPTURE  TRUE IF (BUILD_MODULE_visp_sensor AND USE_FLYCAPTURE))
VP_SET(VISP_HAVE_PYLON       TRUE IF (BUILD_MODULE_visp_sensor AND USE_PYLON))
VP_SET(VISP_HAVE_UEYE        TRUE IF (BUILD_MODULE_visp_sensor AND USE_UEYE))
VP_SET(VISP_HAVE_COMEDI      TRUE IF (BUILD_MODULE_visp_sensor AND USE_COMEDI))
VP_SET(VISP_HAVE_ATIDAQ      TRUE IF (BUILD_MODULE_visp_sensor AND WITH_ATIDAQ))
VP_SET(VISP_HAVE_FT_IIT_SDK  TRUE IF (BUILD_MODULE_visp_sensor AND USE_FTIITSDK))
VP_SET(VISP_HAVE_CLIPPER     TRUE IF (BUILD_MODULE_visp_mbt AND BUILD_MODULE_visp_klt AND WITH_CLIPPER))
VP_SET(VISP_HAVE_APRILTAG    TRUE IF (BUILD_MODULE_visp_detection AND WITH_APRILTAG))
VP_SET(VISP_HAVE_APRILTAG_BIG_FAMILY TRUE IF (BUILD_MODULE_visp_detection AND WITH_APRILTAG AND WITH_APRILTAG_BIG_FAMILY))
VP_SET(VISP_HAVE_QBDEVICE    TRUE IF (BUILD_MODULE_visp_robot AND WITH_QBDEVICE))
VP_SET(VISP_HAVE_TAKKTILE2   TRUE IF (BUILD_MODULE_visp_robot AND WITH_TAKKTILE2))
VP_SET(VISP_HAVE_POLOLU      TRUE IF (BUILD_MODULE_visp_robot AND WITH_POLOLU))
VP_SET(VISP_HAVE_CATCH2      TRUE IF (BUILD_MODULE_visp_core AND WITH_CATCH2))
VP_SET(VISP_HAVE_SIMDLIB     TRUE IF (BUILD_MODULE_visp_core AND WITH_SIMDLIB))
VP_SET(VISP_HAVE_STBIMAGE    TRUE IF (BUILD_MODULE_visp_core AND WITH_STBIMAGE))
VP_SET(VISP_HAVE_TINYEXR     TRUE IF (BUILD_MODULE_visp_core AND WITH_TINYEXR))
VP_SET(VISP_HAVE_PUGIXML     TRUE IF (BUILD_MODULE_visp_core AND WITH_PUGIXML))
VP_SET(VISP_HAVE_MINIZ       TRUE IF (BUILD_MODULE_visp_core AND WITH_MINIZ))

VP_SET(VISP_HAVE_QUALISYS    TRUE IF (BUILD_MODULE_visp_sensor AND USE_QUALISYS))
VP_SET(VISP_HAVE_VICON       TRUE IF (BUILD_MODULE_visp_sensor AND USE_VICON))

VP_SET(VISP_BUILD_SHARED_LIBS            TRUE IF BUILD_SHARED_LIBS) # for header vpConfig.h
VP_SET(VISP_HAVE_DC1394_CAMERA_ENUMERATE TRUE IF (USE_DC1394 AND DC1394_CAMERA_ENUMERATE_FOUND)) # for header vpConfig.h
VP_SET(VISP_HAVE_DC1394_FIND_CAMERAS     TRUE IF (USE_DC1394 AND DC1394_FIND_CAMERAS_FOUND)) # for header vpConfig.h
VP_SET(VISP_HAVE_XRANDR      TRUE IF XRANDR) # for header vpConfig.h
VP_SET(VISP_HAVE_NULLPTR     TRUE IF HAVE_NULLPTR) # for header vpConfig.h

# Check if libfreenect dependencies (ie libusb-1.0 and threads) are available
if(USE_LIBFREENECT AND USE_LIBUSB_1 AND USE_THREADS)
  if(LIBFREENECT_FOUND AND LIBUSB_1_FOUND)
    set(VISP_HAVE_LIBFREENECT_AND_DEPENDENCIES TRUE)

    # The material is found. Check if libfreenect is an old version
    include(CheckCXXSourceCompiles)
    set(CMAKE_REQUIRED_LIBRARIES ${LIBFREENECT_LIBRARIES} ${PTHREAD_LIBRARIES} ${LIBUSB_1_LIBRARIES})
    set(CMAKE_REQUIRED_INCLUDES ${LIBFREENECT_INCLUDE_DIRS} ${PTHREAD_INCLUDE_DIRS} ${LIBUSB_1_INCLUDE_DIRS})
    CHECK_CXX_SOURCE_COMPILES("
      #include <libfreenect.hpp>

      class vpMyKinect : public Freenect::FreenectDevice
      {
      };

      int main()
      {
        Freenect::Freenect<vpMyKinect> freenect;
      }
      " LIBFREENECT_IS_OLD_VERSION)
    #MESSAGE("LIBFREENECT_IS_OLD_VERSION: ${LIBFREENECT_IS_OLD_VERSION}")
    if(LIBFREENECT_IS_OLD_VERSION)
      set(VISP_HAVE_LIBFREENECT_OLD TRUE)  # for header vpConfig.h
    else()
      set(VISP_HAVE_LIBFREENECT_OLD FALSE) # for header vpConfig.h
    endif()
  endif()
endif()

# OpenCV version
if(USE_OPENCV)
  set(VISP_HAVE_OPENCV_VERSION "(${OpenCV_VERSION_MAJOR}<<16 | ${OpenCV_VERSION_MINOR}<<8 | ${OpenCV_VERSION_PATCH})") # for vpConfig.h
endif()

# PCL version
if(USE_PCL)
  set(VISP_HAVE_PCL_VERSION "(${PCL_VERSION_MAJOR}<<16 | ${PCL_VERSION_MINOR}<<8 | ${PCL_VERSION_PATCH})") # for vpConfig.h
endif()

# coin and gui
if(USE_SOWIN OR USE_SOXT OR (USE_SOQT AND SoQt_FOUND) OR (USE_SOQT AND USE_QT))
  set(VISP_HAVE_COIN3D_AND_GUI TRUE)         # for header vpConfig.h
endif()

# check libfranka and set version
if(USE_FRANKA)
  set(VISP_HAVE_FRANKA_VERSION "(${Franka_VERSION_MAJOR}<<16 | ${Franka_VERSION_MINOR}<<8 | ${Franka_VERSION_PATCH})") # for vpConfig.h
endif()

# check MAVSDK and set version
if(USE_MAVSDK)
  set(VISP_HAVE_MAVSDK_VERSION "(${MAVSDK_VERSION_MAJOR}<<16 | ${MAVSDK_VERSION_MINOR}<<8 | ${MAVSDK_VERSION_PATCH})") # for vpConfig.h
endif()

# NaN
# Find isnan macro (C-style): https://www.cplusplus.com/reference/cmath/isnan/
VP_SET(VISP_HAVE_FUNC_ISNAN TRUE IF HAVE_FUNC_ISNAN) # for header vpConfig.h
# Find std::isnan function (cmath): https://en.cppreference.com/w/cpp/numeric/math/isnan
VP_SET(VISP_HAVE_FUNC_STD_ISNAN TRUE IF HAVE_FUNC_STD_ISNAN) # for header vpConfig.h
# Find _isnan function for MSVC: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/isnan-isnan-isnanf?view=msvc-170
VP_SET(VISP_HAVE_FUNC__ISNAN TRUE IF HAVE_FUNC__ISNAN) # for header vpConfig.h

# Inf
# Find isinf macro (C-style): https://www.cplusplus.com/reference/cmath/isinf/
VP_SET(VISP_HAVE_FUNC_ISINF TRUE IF HAVE_FUNC_ISINF) # for header vpConfig.h
# Find std::isinf function (cmath): https://en.cppreference.com/w/cpp/numeric/math/isinf
VP_SET(VISP_HAVE_FUNC_STD_ISINF TRUE IF HAVE_FUNC_STD_ISINF) # for header vpConfig.h
# Macro to indicate if ViSP is build with -fast-math compiler option
VP_SET(VISP_HAVE_FAST_MATH TRUE IF ENABLE_FAST_MATH) # for header vpConfig.h

# round
# Find round function (math.h): https://www.cplusplus.com/reference/cmath/round/
VP_SET(VISP_HAVE_FUNC_ROUND TRUE IF HAVE_FUNC_ROUND) # for header vpConfig.h
# Find std::round function (cmath): https://en.cppreference.com/w/cpp/numeric/math/round
VP_SET(VISP_HAVE_FUNC_STD_ROUND TRUE IF HAVE_FUNC_STD_ROUND) # for header vpConfig.h

# erfc
# Find erfc function (math.h): https://www.cplusplus.com/reference/cmath/erfc/
VP_SET(VISP_HAVE_FUNC_ERFC TRUE IF HAVE_FUNC_ERFC) # for header vpConfig.h
# Find std::erfc function (cmath): https://en.cppreference.com/w/cpp/numeric/math/erfc
VP_SET(VISP_HAVE_FUNC_STD_ERFC TRUE IF HAVE_FUNC_STD_ERFC) # for header vpConfig.h

# Find strtof function (stdlib.h)
VP_SET(VISP_HAVE_FUNC_STRTOF TRUE IF HAVE_FUNC_STRTOF) # for header vpConfig.h

# Find log1p function (math.h)
VP_SET(VISP_HAVE_FUNC_LOG1P TRUE IF HAVE_FUNC_LOG1P) # for header vpConfig.h

# Find inet_ntop function
VP_SET(VISP_HAVE_FUNC_INET_NTOP TRUE IF HAVE_FUNC_INET_NTOP) # for header vpConfig.h

# isfinite
# Find isfinite macro (C-style): https://www.cplusplus.com/reference/cmath/isfinite/
VP_SET(VISP_HAVE_FUNC_ISFINITE TRUE IF HAVE_FUNC_ISFINITE) # for header vpConfig.h
# Find std::isfinite function (cmath): https://en.cppreference.com/w/cpp/numeric/math/isfinite
VP_SET(VISP_HAVE_FUNC_STD_ISFINITE TRUE IF HAVE_FUNC_STD_ISFINITE) # for header vpConfig.h
# Find _finite function for MSVC: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/finite-finitef?view=msvc-170
VP_SET(VISP_HAVE_FUNC__FINITE TRUE IF HAVE_FUNC__FINITE) # for header vpConfig.h

VP_SET(VISP_BUILD_DEPRECATED_FUNCTIONS TRUE IF BUILD_DEPRECATED_FUNCTIONS) # for header vpConfig.h
VP_SET(VISP_MOMENTS_COMBINE_MATRICES TRUE IF ENABLE_MOMENTS_COMBINE_MATRICES) # for header vpConfig.h
VP_SET(VISP_USE_MSVC TRUE IF MSVC) # for header vpConfig.h

VP_SET(VISP_HAVE_BICLOPS_AND_GET_HOMED_STATE_FUNCTION TRUE IF (USE_BICLOPS AND BICLOPS_HAVE_GET_HOMED_STATE_FUNCTION)) # for header vpConfig.h

if(VISP_DATASET_FOUND)
  VP_SET(VISP_HAVE_DATASET TRUE)
  set(VISP_HAVE_DATASET_VERSION "(${VISP_DATASET_VERSION_MAJOR}<<16 | ${VISP_DATASET_VERSION_MINOR}<<8 | ${VISP_DATASET_VERSION_PATCH})") # for vpConfig.h
endif()

if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modules/vision/include/visp3/vision/vpHomography.h")
  set(VISP_HAVE_HOMOGRAPHY TRUE)
endif()

# libraries for Pioneer mobile robots
if(USE_ARIA AND UNIX)
  if(ARIA_FOUND AND USE_THREADS AND RT_FOUND AND DL_FOUND)
    set(VISP_HAVE_PIONEER TRUE) # for header vpConfig.h
  endif()
elseif(USE_ARIA AND NOT UNIX)
  set(VISP_HAVE_PIONEER TRUE) # for header vpConfig.h
endif()

# examples
if(BUILD_ANDROID_EXAMPLES)
  add_subdirectory(samples)
endif()

if(ANDROID)
  add_subdirectory(platforms/android/service)
endif()

# ----------------------------------------------------------------------------
# Finalization: generate configuration-based files
# ----------------------------------------------------------------------------

# Generate platform-dependent and configuration-dependent headers
include(cmake/VISPGenerateHeaders.cmake)

# Configure the file describing how to use ViSP. VISPConfig.cmake
# is the main file configuring a CMake package.
# . Exports build settings and dependencies for projects using ViSP as a
#   third party project.
# . Create and install files for simple use of find_package(VISP)
#   by other cmakified "user" projects and libraries depending on ViSP.
#   (see "Mastering CMake", pp.72)
# . To use ViSP in a third party project based on CMake:
#   find_package(VISP REQUIRED)
#   include_directories(${VISP_INCLUDE_DIRS})
#   target_link_libraries(<target> ${VISP_LIBRARIES})
include(cmake/VISPGenerateConfig.cmake)

# Generate Info.plist for the IOS/OSX frameworks
if(APPLE_FRAMEWORK)
  include(cmake/VISPGenerateInfoPlist.cmake)
endif()

#----------------------------------------------------------------------
# For Dart server and tests
# We use CDash set through CTestConfig.cmake file
# Dashboards are sent to http://cdash.irisa.fr/CDash/index.php?project=ViSP
#----------------------------------------------------------------------
if(BUILD_TESTS)
  include(CTest)
endif()

#----------------------------------------------------------------------
# For CPack packaging tool
#----------------------------------------------------------------------

option(BUILD_PACKAGE "Configure ViSP packaging" OFF)
if(BUILD_PACKAGE)
  if(UNIX AND NOT APPLE AND NOT WIN32) # =linux
    option(BUILD_PACKAGE_DEBIAN "Build debian package" ON)
    option(BUILD_PACKAGE_RPM "Build rpm package" ON)
  endif()

  include(cmake/CPackConfig.cmake)
endif(BUILD_PACKAGE)

#----------------------------------------------------------------------
# Generate the package dependent visp-config shell script for projects which
# are not using CMake:
# Usage:
#    visp-config --cflags ...
#----------------------------------------------------------------------
if(NOT CMAKE_GENERATOR MATCHES "Xcode")
  include(cmake/VISPGenerateConfigScript.cmake)
endif()

#----------------------------------------------------------------------
# Propagation in sub dirs to build demo, example, test, tutorial
#----------------------------------------------------------------------

set(VISP_DIR ${PROJECT_BINARY_DIR})
mark_as_advanced(VISP_DIR)
mark_as_advanced(VISP_INCLUDE_DIRS)

if(BUILD_APPS)
  add_subdirectory(apps)
  vp_add_subdirectories(VISP_CONTRIB_MODULES_PATH apps)
endif()
if(BUILD_DEMOS)
  add_subdirectory(demo)
  vp_add_subdirectories(VISP_CONTRIB_MODULES_PATH demo)
endif()
if(BUILD_EXAMPLES)
  add_subdirectory(example)
  vp_add_subdirectories(VISP_CONTRIB_MODULES_PATH example)
endif()
if(BUILD_TUTORIALS)
  add_subdirectory(tutorial)
  vp_add_subdirectories(VISP_CONTRIB_MODULES_PATH tutorial)
endif()
if(BUILD_APPS)
  vp_add_subdirectories(VISP_CONTRIB_MODULES_PATH apps)
endif()
if(BUILD_PYTHON_BINDINGS)
  add_subdirectory(modules/python)
endif()



# ----------------------------------------------------------------------------
#  Make some cmake vars advanced
# ----------------------------------------------------------------------------
if(JPEG_FOUND)
  mark_as_advanced(jconfig_dir)
endif()
if(OGRE_FOUND)
  vp_set_ogre_advanced_var()
endif()
if(Coin_FOUND)
  mark_as_advanced(Coin_DIR Coin_LIBRARY Qt5OpenGL_DIR)
endif()

# ----------------------------------------------------------------------------
#  Update version of 3rd party for which info is missing
# ----------------------------------------------------------------------------
if(USE_JPEG)
  if(NOT JPEG_LIB_VERSION)
    vp_parse_header("${JPEG_INCLUDE_DIR}/jpeglib.h" JPEG_VERSION_LINES JPEG_LIB_VERSION)
  endif()
  if(NOT JPEG_LIB_VERSION)
    get_filename_component(JPEG_LIB_DIR ${JPEG_LIBRARIES} PATH)
    string(REPLACE "lib" "include" JPEG_INC_DIR ${JPEG_LIB_DIR})
    vp_parse_header("${JPEG_INC_DIR}/jconfig.h" JPEG_VERSION_LINES JPEG_LIB_VERSION)
  endif()
  if(NOT JPEG_LIB_VERSION)
    vp_parse_header("${JPEG_INCLUDE_DIR}/jconfig.h" JPEG_VERSION_LINES JPEG_LIB_VERSION)
    if(NOT JPEG_LIB_VERSION)
      vp_parse_header("${JPEG_INCLUDE_DIR}/jconfig-32.h" JPEG_LIB_VERSION JPEG_LIB_VERSION)
      if(NOT JPEG_LIB_VERSION)
        vp_parse_header("${JPEG_INCLUDE_DIR}/jconfig-64.h" JPEG_LIB_VERSION JPEG_LIB_VERSION)
      endif()
    endif()
  endif()
endif()
if(USE_COIN3D)
  vp_parse_header("${COIN3D_INCLUDE_DIRS}/Inventor/C/basic.h" COIN_VERSION_LINES COIN_MAJOR_VERSION COIN_MINOR_VERSION COIN_MICRO_VERSION)
  set(COIN3D_VERSION "${COIN_MAJOR_VERSION}.${COIN_MINOR_VERSION}.${COIN_MICRO_VERSION}")
endif()
if(USE_FLIRPTUSDK)
  vp_parse_header("${FLIRPTUSDK_CPI_INCLUDE_DIR}/cpi.h" CPI_VERSION_LINES CPI_VER_MAJOR CPI_VER_MINOR CPI_VER_REV)
  set(FLIRPTUSDK_VERSION "${CPI_VER_MAJOR}.${CPI_VER_MINOR}.${CPI_VER_REV}")
endif()

# ----------------------------------------------------------------------------
#  System information
# ----------------------------------------------------------------------------
vp_system_information(NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES TOTAL_PHYSICAL_MEMORY OS_NAME OS_RELEASE
                      OS_VERSION OS_PLATFORM PROCESSOR_NAME PROCESSOR_DESCRIPTION IS_64BIT HAS_FPU CPU_OPTIM)

# ----------------------------------------------------------------------------
#  Autodetect if we are in a GIT repository
# ----------------------------------------------------------------------------
find_host_package(Git QUIET)

if(NOT DEFINED VISP_VCSVERSION AND GIT_FOUND)
  vp_git_describe(VISP_VCSVERSION "${VISP_SOURCE_DIR}")
elseif(NOT DEFINED VISP_VCSVERSION)
  # We don't have git:
  set(VISP_VCSVERSION "unknown")
endif()

# ----------------------------------------------------------------------------
# Summary:
# ----------------------------------------------------------------------------
status("")
status("==========================================================")
status("General configuration information for ViSP ${VISP_VERSION}")
status("")
if(VISP_VCSVERSION)
  status("  Version control:" ${VISP_VCSVERSION})
endif()

# ========================== contrib modules ==========================
if(VISP_CONTRIB_MODULES_PATH)
  set(__dump_extra_header OFF)
  foreach(p ${VISP_CONTRIB_MODULES_PATH})
    if(EXISTS ${p})
      if(NOT __dump_extra_header)
        set(__dump_extra_header ON)
        status("")
        status("  Extra modules:")
      else()
        status("")
      endif()
      set(EXTRA_MODULES_VCSVERSION "unknown")
      if(GIT_FOUND)
        execute_process(COMMAND "${GIT_EXECUTABLE}" describe --tags --always --dirty --match "[0-9].[0-9].[0-9]*"
          WORKING_DIRECTORY "${p}"
          OUTPUT_VARIABLE EXTRA_MODULES_VCSVERSION
          RESULT_VARIABLE GIT_RESULT
          ERROR_QUIET
          OUTPUT_STRIP_TRAILING_WHITESPACE
        )
        if(NOT GIT_RESULT EQUAL 0)
          set(EXTRA_MODULES_VCSVERSION "unknown")
        endif()
      endif()
      status("    Location (extra):" ${p})
      status("    Version control (extra):" ${EXTRA_MODULES_VCSVERSION})
    endif()
  endforeach()
  unset(__dump_extra_header)
endif()

# ========================== build platform ==========================
status("")
status("  Platform:")
if(NOT DEFINED VISP_TIMESTAMP AND NOT BUILD_INFO_SKIP_TIMESTAMP)
  string(TIMESTAMP VISP_TIMESTAMP "" UTC)
  set(VISP_TIMESTAMP "${VISP_TIMESTAMP}" CACHE STRING "Timestamp of ViSP build configuration" FORCE)
endif()
if(VISP_TIMESTAMP)
  status("    Timestamp:"      ${VISP_TIMESTAMP})
endif()
status("    Host:"             ${CMAKE_HOST_SYSTEM_NAME} ${CMAKE_HOST_SYSTEM_VERSION} ${CMAKE_HOST_SYSTEM_PROCESSOR})
if(CMAKE_CROSSCOMPILING)
  status("    Target:"         ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_VERSION} ${CMAKE_SYSTEM_PROCESSOR})
endif()
status("    CMake:"            ${CMAKE_VERSION})
status("    CMake generator:"  ${CMAKE_GENERATOR})
status("    CMake build tool:" ${CMAKE_BUILD_TOOL})
if(MSVC)
  status("    MSVC:"           ${MSVC_VERSION})
endif()
if(CMAKE_GENERATOR MATCHES Xcode)
  status("    Xcode:"          ${XCODE_VERSION})
endif()
if(NOT CMAKE_GENERATOR MATCHES "Xcode|Visual Studio")
  status("    Configuration:"  ${CMAKE_BUILD_TYPE})
endif()

# ========================== system information ==========================

status("")
status("  System information:")
status("    Number of CPU logical cores:"                  "${NUMBER_OF_LOGICAL_CORES}")
status("    Number of CPU physical cores:"                 "${NUMBER_OF_PHYSICAL_CORES}")
status("    Total physical memory (in MiB):"               "${TOTAL_PHYSICAL_MEMORY}")
status("    OS name:"                                      "${OS_NAME}")
status("    OS release:"                                   "${OS_RELEASE}")
status("    OS version:"                                   "${OS_VERSION}")
status("    OS platform:"                                  "${OS_PLATFORM}")
status("    CPU name:"                                     "${PROCESSOR_NAME}")
status("    CPU description:"                              "${PROCESSOR_DESCRIPTION}")
status("    Is the CPU 64-bit?"                            ${IS_64BIT} THEN "yes" ELSE "no")
status("    Does the CPU have FPU?"                        ${HAS_FPU} THEN "yes" ELSE "no")
status("    CPU optimization:"                             ${CPU_OPTIM})
if(NOT ("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 3.20))
# https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_BYTE_ORDER.html
# https://github.com/libevent/libevent/pull/1349/files
  if(CMAKE_CXX_BYTE_ORDER STREQUAL "BIG_ENDIAN")
    status("    CPU endianness:"                 "big-endian")
  elseif(CMAKE_CXX_BYTE_ORDER STREQUAL "LITTLE_ENDIAN")
    status("    CPU endianness:"                 "little-endian")
  else()
    status("    CPU endianness:"                 "unknown")
  endif()
endif()

# ========================== C/C++ options ==========================
if(CMAKE_CXX_COMPILER_VERSION)
  set(VISP_COMPILER_STR "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} (ver ${CMAKE_CXX_COMPILER_VERSION})")
elseif(CMAKE_COMPILER_IS_CLANGCXX)
  set(VISP_COMPILER_STR "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} (ver ${CMAKE_CLANG_REGEX_VERSION})")
elseif(CMAKE_COMPILER_IS_GNUCXX)
  set(VISP_COMPILER_STR "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} (ver ${CMAKE_GCC_REGEX_VERSION})")
else()
  set(VISP_COMPILER_STR "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}")
endif()
string(STRIP "${VISP_COMPILER_STR}" VISP_COMPILER_STR)

status("")
status("  C/C++:")
status("    Built as dynamic libs?:" BUILD_SHARED_LIBS THEN "yes" ELSE "no")
status("    C++ Compiler:"           ${VISP_COMPILER_STR})
status("    C++ flags (Release):"    ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE})
status("    C++ flags (Debug):"      ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG})
status("    C Compiler:"             ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1})
status("    C flags (Release):"      ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE})
status("    C flags (Debug):"        ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG})
if(WIN32)
  status("    Linker flags (Release):" ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_RELEASE})
  status("    Linker flags (Debug):"   ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_DEBUG})
else()
  status("    Linker flags (Release):" ${CMAKE_SHARED_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS_RELEASE})
  status("    Linker flags (Debug):"   ${CMAKE_SHARED_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS_DEBUG})
endif()
status("    Use cxx standard:"       CMAKE_CXX_STANDARD THEN "${CMAKE_CXX_STANDARD}" ELSE "no")

# ========================== ViSP modules ==========================
status("")
status("  ViSP modules:")
string(REPLACE "visp_" "" VISP_MODULES_BUILD_ST          "${VISP_MODULES_BUILD}")
string(REPLACE "visp_" "" VISP_MODULES_DISABLED_USER_ST  "${VISP_MODULES_DISABLED_USER}")
string(REPLACE "visp_" "" VISP_MODULES_DISABLED_FORCE_ST "${VISP_MODULES_DISABLED_FORCE}")
set(VISP_MODULES_DISABLED_AUTO_ST "")
foreach(m ${VISP_MODULES_DISABLED_AUTO})
  set(__mdeps "")
  foreach(d ${VISP_MODULE_${m}_DEPS})
    if(d MATCHES "^visp_" AND NOT USE_${d})
      list(APPEND __mdeps ${d})
    endif()
  endforeach()
  if(__mdeps)
    list(APPEND VISP_MODULES_DISABLED_AUTO_ST "${m}(deps: ${__mdeps})")
  else()
    list(APPEND VISP_MODULES_DISABLED_AUTO_ST "${m}")
  endif()
endforeach()
string(REPLACE "visp_" "" VISP_MODULES_DISABLED_AUTO_ST  "${VISP_MODULES_DISABLED_AUTO_ST}")

status("    To be built:"             VISP_MODULES_BUILD          THEN ${VISP_MODULES_BUILD_ST}          ELSE "-")
status("    Disabled:"                VISP_MODULES_DISABLED_USER  THEN ${VISP_MODULES_DISABLED_USER_ST}  ELSE "-")
status("    Disabled by dependency:"  VISP_MODULES_DISABLED_AUTO  THEN ${VISP_MODULES_DISABLED_AUTO_ST}  ELSE "-")
status("    Unavailable:"             VISP_MODULES_DISABLED_FORCE THEN ${VISP_MODULES_DISABLED_FORCE_ST} ELSE "-")
status("    Enable visp namespace:"   ENABLE_VISP_NAMESPACE       THEN "yes" ELSE "no")
status("    Enable explicit keyword:" ENABLE_EXPLICIT_KEYWORD     THEN "yes" ELSE "no")

# ========================== Android details ==========================
if(ANDROID)
  status("")
  if(DEFINED ANDROID_NDK_REVISION)
    set(__msg "${ANDROID_NDK} (ver ${ANDROID_NDK_REVISION})")
  else()
    set(__msg "location: ${ANDROID_NDK}")
  endif()
  status("  Android NDK: " ${__msg})
  status("    Android ABI:" ${ANDROID_ABI})
  if(BUILD_WITH_STANDALONE_TOOLCHAIN)
    status("    NDK toolchain:" "standalone: ${ANDROID_STANDALONE_TOOLCHAIN}")
  elseif(BUILD_WITH_ANDROID_NDK OR DEFINED ANDROID_TOOLCHAIN_NAME)
    status("    NDK toolchain:" "${ANDROID_TOOLCHAIN_NAME}")
  endif()
  status("    STL type:" ${ANDROID_STL})
  status("    Native API level:" ${ANDROID_NATIVE_API_LEVEL})

  if(BUILD_ANDROID_PROJECTS)
    status("  Android SDK: " "${ANDROID_SDK} (tools: ${ANDROID_SDK_TOOLS_VERSION} build tools: ${ANDROID_SDK_BUILD_TOOLS_VERSION})")
    if(ANDROID_EXECUTABLE)
      status("    android tool:"  "${ANDROID_EXECUTABLE}")
    endif()
  else()
    status("  Android SDK: " "not used, projects are not built")
  endif()
  if(DEFINED ANDROID_SDK_COMPATIBLE_TARGET)
    status("    SDK target:" "${ANDROID_SDK_COMPATIBLE_TARGET}")
  endif()
  if(DEFINED ANDROID_PROJECTS_BUILD_TYPE)
    if(ANDROID_PROJECTS_BUILD_TYPE STREQUAL "ANT")
      status("    Projects build scripts:" "Ant/Eclipse compatible")
    elseif(ANDROID_PROJECTS_BUILD_TYPE STREQUAL "ANT")
      status("    Projects build scripts:" "Gradle")
    endif()
  endif()
endif()

# ================== Windows RT features ==================
if(WIN32)
  status("")
  status("  Windows RT support:" WINRT THEN "yes" ELSE "no")
  if(WINRT)
    status("    Building for Microsoft platform: " ${CMAKE_SYSTEM_NAME})
    status("    Building for architectures: " ${CMAKE_VS_EFFECTIVE_PLATFORMS})
    status("    Building for version: " ${CMAKE_SYSTEM_VERSION})
  endif()
endif()

# ========================== java ==========================
status("")
status("  Python 3:")
status("    Interpreter:"     PYTHON3INTERP_FOUND  THEN "${PYTHON3_EXECUTABLE} (ver ${PYTHON3_VERSION_STRING})"    ELSE "no")

if(BUILD_JAVA OR BUILD_visp_java)
  status("")
  status("  Java:"            BUILD_FAT_JAVA_LIB  THEN "export all functions"                    ELSE "")
  status("    ant:"           ANT_EXECUTABLE      THEN "${ANT_EXECUTABLE} (ver ${ANT_VERSION})"  ELSE "no")
  if(NOT ANDROID)
  status("    Java:"          Java_FOUND          THEN "yes (ver ${Java_VERSION})"                 ELSE "no")
  status("    JNI:"           JNI_INCLUDE_DIRS    THEN "${JNI_INCLUDE_DIRS}"                       ELSE "no")
  status("    Java wrappers:" HAVE_visp_java      THEN "yes (${VISP_JAVA_SDK_BUILD_TYPE})"         ELSE "no")
  endif()
endif()

# ======================= Python bindings ========================
status("")
status("  Python3 bindings:"           BUILD_PYTHON_BINDINGS    THEN "yes" ELSE "no")
if(BUILD_PYTHON_BINDINGS)
  status("    Python3 interpreter:"    PYTHON3INTERP_FOUND  THEN "${PYTHON3_EXECUTABLE} (ver ${PYTHON3_VERSION_STRING})" ELSE "no")
  status("    Pybind11:"               USE_PYBIND11         THEN "${pybind11_DIR} (${pybind11_VERSION})" ELSE "no")
  status("    Package version:"        "${VISP_PYTHON_PACKAGE_VERSION}")
  status("    Wrapped modules:"        "${VISP_PYTHON_BOUND_MODULES}")
  status("    Generated input config:" "${VISP_PYTHON_GENERATED_CONFIG_FILE}")
else()
  status("    Requirements: ")
  status("      Python version > ${PYTHON3_MINIMUM_VERSION_PYTHON_BINDINGS}:" PYTHON3_FOUND AND NOT PYTHON3_NOT_OK_FOR_BINDINGS THEN "ok (ver ${PYTHON3_VERSION_STRING})" ELSE "python not found or too old (${PYTHON3_VERSION_STRING})")
  status("      Python in virtual env. or conda (or system with override):" VISP_PYTHON_INTERPRETER_ALLOWED THEN "failed" ELSE "ok")
  status("      Pybind11 found:"     USE_PYBIND11 THEN "ok" ELSE "failed")
  status("      CMake > ${CMAKE_MINIMUM_VERSION_PYTHON_BINDINGS}:" CMAKE_NOT_OK_FOR_BINDINGS THEN "failed (${CMAKE_VERSION})" ELSE "ok (${CMAKE_VERSION})")
  status("      C++ standard > ${VISP_CXX_STANDARD_17}:" CXX_STANDARD_NOT_OK_FOR_BINDINGS THEN "failed (${VISP_CXX_STANDARD})" ELSE "ok (${VISP_CXX_STANDARD})")
endif()


# ============================ Options ===========================
status("")
status("  Build options: ")
status("    Build deprecated:"           BUILD_DEPRECATED_FUNCTIONS      THEN "yes" ELSE "no")
status("    Build with moment combine:"  ENABLE_MOMENTS_COMBINE_MATRICES THEN "yes" ELSE "no")

# ===================== Optional 3rd parties =====================
status("")
status("  OpenCV: ")
status("    Version:"                USE_OPENCV         THEN "${OpenCV_VERSION}" ELSE "n/a")
if(USE_OPENCV)
  vp_list_replace_string(OpenCV_LIB_COMPONENTS OpenCV_LIB_COMPONENTS_FILTERED "^opencv_+" "")
  status("    Modules:"    "${OpenCV_LIB_COMPONENTS_FILTERED}")
  status("    OpenCV dir:" "${OpenCV_DIR}")
endif()
status("")
status("  YARP: ")
status("    Version:"                USE_YARP           THEN "${YARP_VERSION_SHORT}" ELSE "n/a")
status("")
status("  Mathematics: ")
status("    Blas/Lapack:"            (USE_LAPACK OR WITH_LAPACK) THEN "yes" ELSE "no")
status("    \\- Use MKL:"            USE_MKL            THEN "yes" ELSE "no")
status("    \\- Use OpenBLAS:"       USE_OPENBLAS       THEN "yes (ver ${OpenBLAS_VERSION})" ELSE "no")
status("    \\- Use Atlas:"          USE_ATLAS          THEN "yes" ELSE "no")
status("    \\- Use Netlib:"         USE_NETLIB         THEN "yes (ver ${NETLIB_VERSION})" ELSE "no")
status("    \\- Use GSL:"            USE_GSL            THEN "yes (ver ${GSL_VERSION})" ELSE "no")
status("    \\- Use Lapack (built-in):" WITH_LAPACK     THEN "yes (ver ${LAPACK_VERSION})" ELSE "no")
status("    Use Eigen3:"             USE_EIGEN3         THEN "yes (ver ${Eigen3_VERSION})" ELSE "no")
status("    Use OpenCV:"             USE_OPENCV         THEN "yes (ver ${OpenCV_VERSION})" ELSE "no")
status("")
status("  Simulator: ")
status("    Ogre simulator: ")
status("    \\- Use Ogre3D:"         USE_OGRE         THEN "yes (ver ${OGRE_VERSION})" ELSE "no")
status("    \\- Use OIS:"            USE_OIS          THEN "yes (ver ${OIS_VERSION})" ELSE "no")
status("    Coin simulator: ")
status("    \\- Use Coin3D:"         USE_COIN3D       THEN "yes (ver ${COIN3D_VERSION})" ELSE "no")
status("    \\- Use SoWin:"          USE_SOWIN        THEN "yes" ELSE "no")
status("    \\- Use SoXt:"           USE_SOXT         THEN "yes" ELSE "no")
if(USE_SOQT AND SoQt_FOUND)
status("    \\- Use SoQt:"           USE_SOQT    AND SoQt_FOUND THEN "yes (ver ${SoQt_VERSION})" ELSE "no")
else()
status("    \\- Use SoQt:"           USE_SOQT         THEN "yes" ELSE "no")
endif()
status("    \\- Use Qt5:"            USE_SOQT AND SoQt_FOUND                    THEN "yes" ELSE "no")
status("    \\- Use Qt4:"            USE_QT   AND DESIRED_QT_VERSION MATCHES 4  THEN "yes" ELSE "no")
status("    \\- Use Qt3:"            USE_QT   AND DESIRED_QT_VERSION MATCHES 3  THEN "yes" ELSE "no")
status("    Panda3D:"                USE_PANDA3D      THEN "yes (ver ${Panda3D_VERSION_STRING})" ELSE "no")

status("")
status("  Media I/O: ")
status("    Use JPEG:"               USE_JPEG         THEN "yes (ver ${JPEG_LIB_VERSION})" ELSE "no")
status("    Use PNG:"                USE_PNG          THEN "yes (ver ${PNG_VERSION_STRING})" ELSE "no")
status("    \\- Use ZLIB:"           USE_ZLIB         THEN "yes (ver ${ZLIB_VERSION_STRING})" ELSE "no")
status("    Use OpenCV:"             USE_OPENCV       THEN "yes (ver ${OpenCV_VERSION})" ELSE "no")
status("    Use stb_image (built-in):" WITH_STBIMAGE  THEN "yes (ver ${STBIMAGE_VERSION})" ELSE "no")
status("    Use TinyEXR (built-in):" WITH_TINYEXR     THEN "yes (ver ${TINYEXR_VERSION})" ELSE "no")
status("    Use simdlib (built-in):" WITH_SIMDLIB     THEN "yes (ver ${SIMD_VERSION})" ELSE "no")
status("    Use npz I/O (built-in):" WITH_MINIZ       THEN "yes" ELSE "no")
status("")
status("  Real robots: ")
status("    Use Afma6:"              USE_AFMA6        THEN "yes" ELSE "no")
if(USE_AFMA6)
status("    \\- Data:"               AFMA6_DATA_FOUND THEN "yes (in ${AFMA6_DATA_PATH})" ELSE "no")
endif()
status("    Use Franka:"             USE_FRANKA       THEN "yes (ver ${Franka_VERSION})" ELSE "no")
status("    Use Viper650:"           USE_VIPER650     THEN "yes" ELSE "no")
if(USE_VIPER650)
status("    \\- Data:"               VIPER650_DATA_FOUND THEN "yes (in ${VIPER650_DATA_PATH})" ELSE "no")
endif()
status("    Use Viper850:"           USE_VIPER850     THEN "yes" ELSE "no")
if(USE_VIPER850)
status("    \\- Data:"               VIPER850_DATA_FOUND THEN "yes (in ${VIPER850_DATA_PATH})" ELSE "no")
endif()
status("    Use ur_rtde:"            USE_UR_RTDE      THEN "yes (ver ${ur_rtde_VERSION})" ELSE "no")
status("    Use Kinova Jaco:"        USE_JACOSDK      THEN "yes" ELSE "no")
status("    Use aria (Pioneer):"     USE_ARIA         THEN "yes" ELSE "no")
status("    Use PTU46:"              USE_PTU46        THEN "yes" ELSE "no")
status("    Use Biclops PTU:"        USE_BICLOPS      THEN "yes" ELSE "no")
status("    Use Flir PTU SDK:"       USE_FLIRPTUSDK   THEN "yes (ver ${FLIRPTUSDK_VERSION})" ELSE "no")
status("    Use MAVSDK:"             USE_MAVSDK       THEN "yes (ver ${MAVSDK_VERSION})" ELSE "no")
status("    Use Parrot ARSDK:"       USE_ARSDK        THEN "yes (ver ${ARSDK_VERSION})" ELSE "no")
status("    \\- Use ffmpeg:"         USE_FFMPEG       THEN "yes" ELSE "no")
if(USE_FFMPEG)
status("       \\- Use libavcodec:"  USE_FFMPEG     THEN "yes (ver ${FFMPEG_LIBAVCODEC_VERSION})" ELSE "no")
status("       \\- Use libavformat:" USE_FFMPEG     THEN "yes (ver ${FFMPEG_LIBAVFORMAT_VERSION})" ELSE "no")
status("       \\- Use libavutil:"   USE_FFMPEG     THEN "yes (ver ${FFMPEG_LIBAVUTIL_VERSION})" ELSE "no")
status("       \\- Use libswscale:"  USE_FFMPEG     THEN "yes (ver ${FFMPEG_LIBSWSCALE_VERSION})" ELSE "no")
endif()
status("    Use Virtuose:"           USE_VIRTUOSE     THEN "yes" ELSE "no")
status("    Use qbdevice (built-in):" WITH_QBDEVICE   THEN "yes (ver ${QBDEVICE_VERSION})" ELSE "no")
status("    Use takktile2 (built-in):" WITH_TAKKTILE2 THEN "yes (ver ${TAKKTILE2_VERSION})" ELSE "no")
status("    Use pololu (built-in):"  WITH_POLOLU      THEN "yes (ver ${POLOLU_VERSION})" ELSE "no")
status("")
status("  GUI: ")
status("    Use X11:"                USE_X11          THEN "yes" ELSE "no")
status("    Use GTK2:"               USE_GTK2         THEN "yes (ver ${GTK2_VERSION})" ELSE "no")
status("    Use OpenCV:"             USE_OPENCV       THEN "yes (ver ${OpenCV_VERSION})" ELSE "no")
status("    Use GDI:"                USE_GDI          THEN "yes" ELSE "no")
status("    Use Direct3D:"           USE_DIRECT3D     THEN "yes" ELSE "no")
status("")
status("  Cameras: ")
status("    Use DC1394-2.x:"         USE_DC1394       THEN "yes (ver ${DC1394_VERSION})" ELSE "no")
status("    Use CMU 1394:"           USE_CMU1394      THEN "yes" ELSE "no")
status("    Use V4L2:"               USE_V4L2         THEN "yes (ver ${V4L2_VERSION})" ELSE "no")
status("    Use directshow:"         USE_DIRECTSHOW   THEN "yes" ELSE "no")
status("    Use OpenCV:"             USE_OPENCV       THEN "yes (ver ${OpenCV_VERSION})" ELSE "no")
status("    Use FLIR Flycapture:"    USE_FLYCAPTURE   THEN "yes" ELSE "no")
status("    Use Basler Pylon:"       USE_PYLON        THEN "yes (ver ${PYLON_VERSION})" ELSE "no")
status("    Use IDS uEye:"           USE_UEYE         THEN "yes (ver ${UEYE_VERSION})" ELSE "no")
status("")
status("  RGB-D sensors: ")
status("    Use Realsense2:"         USE_REALSENSE2   THEN "yes (ver ${REALSENSE2_VERSION})" ELSE "no")
status("    Use Occipital Structure:"          USE_OCCIPITAL_STRUCTURE    THEN "yes" ELSE "no")
status("    Use Kinect:"             USE_LIBFREENECT AND USE_LIBUSB_1 AND USE_THREADS THEN "yes" ELSE "no")
status("    \\- Use libfreenect:"    USE_LIBFREENECT  THEN "yes (ver ${LIBFREENECT_VERSION})" ELSE "no")
status("    \\- Use libusb-1:"       USE_LIBUSB_1     THEN "yes (ver ${LIBUSB_1_VERSION})" ELSE "no")
status("    \\- Use std::thread:"    USE_THREADS      THEN "yes" ELSE "no")
status("    Use PCL:"                USE_PCL          THEN "yes (ver ${PCL_VERSION})" ELSE "no")
status("    \\- Use VTK:"            VTK_FOUND        THEN "yes (ver ${VTK_VERSION})" ELSE "no")
status("")
status("  F/T sensors: ")
status("    Use atidaq (built-in):"  WITH_ATIDAQ      THEN "yes (ver ${ATIDAQ_VERSION})" ELSE "no")
status("    Use comedi:"             USE_COMEDI       THEN "yes (ver ${COMEDI_VERSION})" ELSE "no")
status("    Use IIT SDK:"            USE_FTIITSDK     THEN "yes" ELSE "no")
status("")
status("  Mocap: ")
status("    Use Qualisys:"           USE_QUALISYS     THEN "yes" ELSE "no")
status("    Use Vicon:"              USE_VICON        THEN "yes" ELSE "no")
status("")
status("  Detection: ")
status("    Use zbar:"                    USE_ZBAR                  THEN "yes (ver ${ZBAR_VERSION})" ELSE "no")
status("    Use dmtx:"                    USE_DMTX                  THEN "yes (ver ${DMTX_VERSION})" ELSE "no")
status("    Use AprilTag (built-in):"     WITH_APRILTAG             THEN "yes (ver ${APRILTAG_VERSION})" ELSE "no")
status("    \\- Use AprilTag big family:" WITH_APRILTAG_BIG_FAMILY  THEN "yes" ELSE "no")
status("")
status("  Misc: ")
status("    Use Clipper (built-in):"  WITH_CLIPPER     THEN "yes (ver ${CLIPPER_VERSION})" ELSE "no")
status("    Use pugixml (built-in):"  WITH_PUGIXML     THEN "yes (ver ${PUGIXML_VERSION})" ELSE "no")
status("    Use libxml2:"             USE_XML2         THEN "yes (ver ${LIBXML2_VERSION_STRING})" ELSE "no")
if(WIN32)
status("    \\- Use Iconv:"           USE_ICONV        THEN "yes (ver ${Iconv_VERSION})" ELSE "no")
endif()
if(VISP_HAVE_NLOHMANN_JSON_FROM_VTK)
status("    Use json (nlohmann vtk):"     USE_NLOHMANN_JSON THEN "yes (ver ${VTK_NLOHMANN_JSON_VERSION})" ELSE "no")
else()
status("    Use json (nlohmann system):"  USE_NLOHMANN_JSON THEN "yes (ver ${nlohmann_json_VERSION})" ELSE "no")
endif()
status("")
status("  Optimization: ")
status("    Use OpenMP:"             USE_OPENMP         THEN "yes (ver ${OpenMP_CXX_VERSION})" ELSE "no")
status("    Use std::thread:"        USE_THREADS        THEN "yes" ELSE "no")
status("    Use pthread:"            USE_PTHREAD        THEN "yes" ELSE "no")
status("    Use simdlib (built-in):" WITH_SIMDLIB       THEN "yes (ver ${SIMD_VERSION})" ELSE "no")
status("")
status("  DNN: ")
status("    Use CUDA Toolkit:"       USE_TENSORRT AND CUDA_FOUND  THEN "yes (ver ${CUDA_VERSION})" ELSE "no")
status("    Use TensorRT:"           USE_TENSORRT       THEN "yes (ver ${TENSORRT_VERSION})" ELSE "no")

# ========================== documentation ==========================
status("")
status("  Documentation: ")
status("    Use doxygen:"            DOXYGEN_FOUND    THEN "yes (ver ${DOXYGEN_VERSION})" ELSE "no")
status("    \\- Use mathjax:"        USE_MATHJAX      THEN "yes" ELSE "no")
if(DOXYGEN_AWESOME_DIR)
  status("    \\- Use doxygen-awesome:" "yes")
else()
  status("    \\- Use doxygen-awesome:" "no")
endif()

# ========================== samples and tests ==========================
status("")
status("  Tests and samples:")
status("    Use catch2 (built-in):"  WITH_CATCH2        THEN "yes (ver ${CATCH2_VERSION})" ELSE "no")
status("    Tests:"                  BUILD_TESTS        THEN "yes" ELSE "no")
status("    Apps:"                   BUILD_APPS         THEN "yes" ELSE "no")
status("    Demos:"                  BUILD_DEMOS        THEN "yes" ELSE "no")
status("    Examples:"               BUILD_EXAMPLES     THEN "yes" ELSE "no")
status("    Tutorials:"              BUILD_TUTORIALS    THEN "yes" ELSE "no")
status("    Dataset found:"          VISP_DATASET_FOUND THEN "yes (ver ${VISP_DATASET_VERSION} in ${VISP_DATASET_LOCATION})" ELSE "no")
if(APPS_FOUND)
  status("    Apps:"              BUILD_APPS  THEN "yes" ELSE "no")
endif()

# ========================== library dirs ==========================
status("")
status("  Library dirs:")
if(USE_EIGEN3)
  status("    Eigen3 dir:" "${Eigen3_DIR}")
endif()
if(USE_MKL)
  status("    MKL include dir:" "${MKL_INCLUDE_DIRS}")
endif()
if(USE_OPENBLAS)
  status("    OpenBLAS include dir:" "${OpenBLAS_INCLUDE_DIR}")
endif()
if(USE_OPENCV)
  status("    OpenCV dir:" "${OpenCV_DIR}")
endif()
if(USE_PCL)
  status("    PCL dir:" "${PCL_DIR}")
endif()
if(USE_PANDA3D)
  if(Panda3D_DIR)
    status("    Panda3D dir:" "${Panda3D_DIR}")
  elseif($ENV{Panda3D_DIR})
    status("    Panda3D dir:" "$ENV{Panda3D_DIR}")
  else()
    file(REAL_PATH "${Panda3D_INCLUDE_DIRS}/../.." Panda3D_DIR)
    status("    Panda3D dir:" "${Panda3D_DIR}")
  endif()
endif()
if(USE_YARP)
  status("    Yarp dir:" "${YARP_DIR}")
endif()
if(USE_OGRE)
  if(NOT ${OGRE_DIR} MATCHES "NOTFOUND")
    status("    Ogre dir:" "${OGRE_DIR}")
  else()
    status("    Ogre inc dir:" "${OGRE_INCLUDE_DIR}")
    status("    Ogre Main lib:" "${OGRE_LIBRARY_REL}")
    status("    Ogre plugin dir:" "${OGRE_PLUGIN_DIR_REL}")
  endif()
endif()

# ========================== auxiliary ==========================
status("")
status("  Install path:" "${CMAKE_INSTALL_PREFIX}")
status("")

status("==========================================================")

vp_finalize_status()
