# vim: set sw=2 ts=2 sts=2:
CMAKE_MINIMUM_REQUIRED(VERSION 3.18)

set(VERSION_REGEX "#define STOPT_VERSION")
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/StOpt/core/utils/version.h" VERSION_STRING REGEX ${VERSION_REGEX})
string(REGEX REPLACE ${VERSION_REGEX} "" VERSION_STRING "${VERSION_STRING}")
string(REGEX REPLACE " *\"" "" VERSION_STRING "${VERSION_STRING}")
MESSAGE(STATUS "StOpt version : ${VERSION_STRING}")
PROJECT(LIBRARY_STOPT  VERSION ${VERSION_STRING} LANGUAGES CXX)

# ------------------------------------------------------------------------------
# Wheel-friendly layout only when building Python wheels.
# On Windows we will also bundle vcpkg runtime DLLs next to the Python module.
# On Linux: behavior remains unchanged (no vcpkg logic is applied).
# ------------------------------------------------------------------------------
option(STOPT_PIP_LAYOUT "Install all native artifacts next to the Python module" OFF)

# For safety when linking static libs into shared modules
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# Compute the install destination for native artifacts:
# - For wheel layout: install to the Python package directory (passed as STOPT_PY_DEST).
# - Otherwise (system install): fall back to platform libdir.
IF (STOPT_PIP_LAYOUT)
  # Allow override from the build frontend (e.g., via -DSTOPT_PY_DEST=pystopt)
  if (NOT DEFINED STOPT_PY_DEST OR STOPT_PY_DEST STREQUAL "")
    set(STOPT_PY_DEST ".")
  endif()
  set(_PY_DEST "${STOPT_PY_DEST}")
ELSE()
  include(GNUInstallDirs)
  set(_PY_DEST "${CMAKE_INSTALL_LIBDIR}")
ENDIF()

SET(CMAKE_MODULE_PATH "${LIBRARY_STOPT_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}")

IF(NOT CMAKE_BUILD_TYPE)
  message(STATUS "Setting build type to 'Release' as none was specified.")
  SET(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)

# option for PYTHON
OPTION(BUILD_PYTHON "Build python bindings" ON)

# option for MPI
OPTION(BUILD_MPI "Build MPI test" ON)

# option for SDDP 
OPTION(BUILD_SDDP "Build SDDP test" OFF)

# option for DP for Cuts
OPTION(BUILD_DPCUTS "Build DP CUTS test" OFF)

OPTION(BUILD_CPACK "Build for CPACK" OFF)

OPTION(WITHCIBUILD OFF)

# option to test automatic differentiation
OPTION(BUILD_TEST_AUTODIFF OFF)

# option to use adept or stan (activate only if automatic differentiation)
OPTION(BUILD_TEST_ADEPT ON)
IF (BUILD_TEST_ADEPT)
  ADD_DEFINITIONS(-DADEPT )
ENDIF()
 
OPTION(BUILD_TEST_STANMATH ON)
IF (BUILD_TEST_STANMATH)
  ADD_DEFINITIONS(-DSTANMATH)
ENDIF()


# option for branching
OPTION(BUILD_BRANCHING "Build Branching test" OFF)
IF (BUILD_BRANCHING)
  IF (NOT BUILD_MPI)
    MESSAGE(FATAL_ERROR "MPI should be on for Branching")
  ENDIF()
  FIND_PACKAGE(Trng4 REQUIRED)
  INCLUDE_DIRECTORIES(SYSTEM ${TRNG4_INCLUDE_DIRS})
ENDIF()

# do we install C++ libs
OPTION(BUILD_SYSTEM_INSTALL "Install C++ libs in system prefix" OFF)

#option for building test
OPTION(BUILD_TEST "Build test " ON)

#option for testing long test cases
OPTION(BUILD_LONG_TEST "Add long tests to the testing module" OFF)
IF(BUILD_LONG_TEST)
  ADD_DEFINITIONS(-DUSE_LONG_TEST)
ENDIF(BUILD_LONG_TEST)

# Boost

IF (WIN32)
  # With vcpkg toolchain (-DCMAKE_TOOLCHAIN_FILE=.../vcpkg.cmake), CONFIG mode works.
  IF(BUILD_TEST)
    FIND_PACKAGE(Boost REQUIRED COMPONENTS unit_test_framework    timer chrono log thread )
    SET(BOOST_LIBS Boost::chrono  Boost::timer Boost::unit_test_framework Boost::log Boost::thread)
    IF (BOOST_VERSION VERSION_LESS 190000)
      FIND_PACKAGE(Boost REQUIRED COMPONENTS system)
      LIST(APPEND BOOST_LIBS Boost::system)
    ENDIF() 
  ENDIF()
  FIND_PACKAGE(Boost  REQUIRED COMPONENTS random serialization )
  LIST(APPEND BOOST_LIBS Boost::random Boost::serialization)
  FIND_PACKAGE(Threads REQUIRED)
ELSE(WIN32)
  
  # On most Linux systems, only the legacy FindBoost module is available.
  # Since CMake >= 4.0 removed FindBoost by default (CMP0167), force OLD behavior.
  IF (POLICY CMP0167)
    CMAKE_POLICY(SET CMP0167 OLD)
  ENDIF()

  IF(BUILD_TEST)
    FIND_PACKAGE(Boost COMPONENTS unit_test_framework    timer chrono log thread  REQUIRED)
    SET(BOOST_LIBS ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}  ${Boost_CHRONO_LIBRARY}  ${Boost_TIMER_LIBRARY}   ${Boost_LOG_LIBRARY} ${Boost_THREAD_LIBRARY} )
    IF (Boost_VERSION VERSION_LESS 190000)
      FIND_PACKAGE(Boost COMPONENTS system  REQUIRED)
      LIST(APPEND BOOST_LIBS ${Boost_SYSTEM_LIBRARY})
    ENDIF() 
  ENDIF()
  FIND_PACKAGE(Boost COMPONENTS  random serialization REQUIRED)
  LIST(APPEND BOOST_LIBS  ${Boost_SERIALIZATION_LIBRARY}  ${Boost_RANDOM_LIBRARY})
  INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS})
ENDIF(WIN32)
FIND_PACKAGE(Threads REQUIRED)
IF(BUILD_MPI)
  FIND_PACKAGE(MPI  REQUIRED)
  IF (WIN32)
    FIND_PACKAGE(Boost  REQUIRED COMPONENTS mpi )
    LIST(APPEND BOOST_LIBS Boost::mpi )
  ELSE(WIN32)
    FIND_PACKAGE(Boost COMPONENTS mpi REQUIRED )
    LIST(APPEND BOOST_LIBS ${Boost_MPI_LIBRARY})
    INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS})
    INCLUDE_DIRECTORIES(SYSTEM ${MPI_CXX_INCLUDE_PATH})
  ENDIF(WIN32)
  ADD_DEFINITIONS(-DUSE_MPI)
ENDIF(BUILD_MPI)


# ZLIB
FIND_PACKAGE(ZLIB REQUIRED)

# Compatibilité: ZLIB_INCLUDE_DIRS n'existe pas toujours, donc fallback
IF(NOT ZLIB_INCLUDE_DIRS AND ZLIB_INCLUDE_DIR)
  SET(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
ENDIF()

# Sécurité: s'assurer que l'inclusion est bien passée
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})

# Libs
SET(GENERS_EXTRA_LIBS ${GENERS_EXTRA_LIBS} ${ZLIB_LIBRARIES})

#bzip2
FIND_PACKAGE(BZip2 REQUIRED)

# --- Eigen exact 3.4.0 if AUTODIFF
IF(BUILD_TEST_AUTODIFF)
  FIND_PACKAGE(Eigen3 3.4.0 EXACT REQUIRED)
ELSE()
  FIND_PACKAGE(Eigen3 3.4.0 REQUIRED)
ENDIF(BUILD_TEST_AUTODIFF)
  

IF(TARGET Eigen3::Eigen)
  MESSAGE(STATUS "Eigen3 found via Target (Modern CMake)")

  GET_TARGET_PROPERTY(EIGEN3_INCLUDE_DIR
      Eigen3::Eigen
      INTERFACE_INCLUDE_DIRECTORIES
  )
ELSE()
  MESSAGE(STATUS "Eigen3 found via Variables (Classic)")
ENDIF()

# Normalisation variable version
IF(DEFINED EIGEN3_VERSION)
  set(STOPT_EIGEN_VERSION "${EIGEN3_VERSION}")
ELSEIF(DEFINED Eigen3_VERSION)
  set(STOPT_EIGEN_VERSION "${Eigen3_VERSION}")
ELSE()
  set(STOPT_EIGEN_VERSION "UNKNOWN")
ENDIF()

MESSAGE(STATUS "Eigen version: ${STOPT_EIGEN_VERSION}")
MESSAGE(STATUS "Eigen include dir: ${EIGEN3_INCLUDE_DIR}")
IF(BUILD_TEST_AUTODIFF)
  IF(NOT STOPT_EIGEN_VERSION STREQUAL "3.4.0")
    MESSAGE(FATAL_ERROR
      "Eigen version must be exactly 3.4.0, found ${STOPT_EIGEN_VERSION}"
  )
endif()
ENDIF(BUILD_TEST_AUTODIFF)

INCLUDE_DIRECTORIES(SYSTEM ${EIGEN3_INCLUDE_DIR})

# Add some extra delete[] and new[] operatros needed by boost to Eigen::PlainObjectBase
IF (APPLE)
  ADD_DEFINITIONS(-DEIGEN_PLAINOBJECTBASE_PLUGIN="StOpt/core/utils/eigenMemory.h")
ENDIF(APPLE)


INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})

IF (NOT MSVC)
 # Detect if the compiler supports C+11
 INCLUDE(CheckCXXCompilerFlag)
 CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
 CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
 CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
 CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
 IF(COMPILER_SUPPORTS_CXX17)
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
 ELSEIF(COMPILER_SUPPORTS_CXX14)
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
 ELSEIF(COMPILER_SUPPORTS_CXX11)
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 ELSEIF(COMPILER_SUPPORTS_CXX0X)
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
 ELSE()
  MESSAGE(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
 ENDIF()
 SET(PTHREAD_LIBRARY "-lpthread")
ELSE()
  IF(MSVC_VERSION LESS 1800)
    MESSAGE(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no decent C++11 support. Please use a different C++ compiler.")
  ENDIF()
  ADD_COMPILE_OPTIONS(/bigobj /EHsc)
ENDIF(NOT MSVC)

# Update flags according to the compiler
IF (${CMAKE_CXX_COMPILER_ID} MATCHES Clang)
   IF (APPLE)
     SET(CLANG_SANITIZE_FLAGS "")
  ELSE(APPLE)
     SET(CLANG_SANITIZE_FLAGS "")
  ENDIF(APPLE)
  SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}  -g -O0 ${CLANG_SANITIZE_FLAGS}")
  SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC -O3 -DNDEBUG  -DBOOST_DISABLE_ASSERTS")
  SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fPIC -O2 -DNDEBUG -g  -DBOOST_DISABLE_ASSERTS")
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wextra -Wfloat-equal -Wno-system-headers ")
ELSEIF (${CMAKE_CXX_COMPILER_ID} MATCHES GNU)
  IF (APPLE)
    SET(GCC_SANITIZE_FLAGS "")
  ELSE(APPLE)
    SET(GCC_SANITIZE_FLAGS "")
  ENDIF(APPLE)
  SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}  -g -O0 ")
  SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -DNDEBUG  -DBOOST_DISABLE_ASSERTS")
  SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O2 -DNDEBUG  -DBOOST_DISABLE_ASSERTS")
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-long-long -Winit-self -Wfloat-equal -Wsign-compare -pedantic -funroll-all-loops -ffast-math -fno-strict-aliasing -ftree-vectorize  -fPIC")
ELSEIF(${CMAKE_CXX_COMPILER_ID} MATCHES Intel)
  SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fpic -O1 -g -ftrapuv")
  SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fpic -O3 -DNDEBUG  -DBOOST_DISABLE_ASSERTS")
  SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fpic -O2 -DNDEBUG  -DBOOST_DISABLE_ASSERTS")
ENDIF()

# Find OpenMP
FIND_PACKAGE(OpenMP)
IF (OPENMP_CXX_FOUND)
  MESSAGE(STATUS "OpenMP found")
ENDIF()

# SERIALIZATION WITH RANDOM ACCESS
#INCLUDE_DIRECTORIES(SYSTEM ${ZLIB_INCLUDE_DIRS} ${BZIP2_INCLUDE_DIRS})
ADD_SUBDIRECTORY(geners-1.11.0)
SET(GENERS_LIB  geners)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/geners-1.11.0)


# Compile library for C++
INCLUDE_DIRECTORIES(SYSTEM ${PROJECT_SOURCE_DIR} )
SET(SOURCE_DIR_LIB1 ${PROJECT_SOURCE_DIR}/StOpt/regression)
SET(SOURCE_DIR_LIB2 ${PROJECT_SOURCE_DIR}/StOpt/core/utils)
SET(SOURCE_DIR_LIB3 ${PROJECT_SOURCE_DIR}/StOpt/sddp)
SET(SOURCE_DIR_LIB4 ${PROJECT_SOURCE_DIR}/StOpt/core/sparse)
SET(SOURCE_DIR_LIB5 ${PROJECT_SOURCE_DIR}/StOpt/core/grids)
SET(SOURCE_DIR_LIB6 ${PROJECT_SOURCE_DIR}/StOpt/semilagrangien)
SET(SOURCE_DIR_LIB7 ${PROJECT_SOURCE_DIR}/StOpt/dp)
SET(SOURCE_DIR_LIB8 ${PROJECT_SOURCE_DIR}/StOpt/core/parallelism)
SET(SOURCE_DIR_LIB9 ${PROJECT_SOURCE_DIR}/StOpt/tree)
SET(SOURCE_DIR_LIB10 ${PROJECT_SOURCE_DIR}/StOpt/cdf)
FILE(GLOB SOURCE  ${SOURCE_DIR_LIB1}/*.cpp ${SOURCE_DIR_LIB2}/*.cpp  ${SOURCE_DIR_LIB3}/*.cpp  ${SOURCE_DIR_LIB4}/*.cpp   ${SOURCE_DIR_LIB5}/*.cpp  ${SOURCE_DIR_LIB6}/*.cpp ${SOURCE_DIR_LIB7}/*.cpp  ${SOURCE_DIR_LIB8}/*.cpp ${SOURCE_DIR_LIB9}/*.cpp ${SOURCE_DIR_LIB10}/*.cpp  )
IF (WIN32)
  SET(SUFF "/Release")
  SET(EXTENSION ".exe")
  ADD_LIBRARY(StOpt STATIC ${SOURCE})
ELSE()
   ADD_LIBRARY(StOpt SHARED ${SOURCE})
 ENDIF()
# for pip
# Linux-only RPATH so that PyStOpt finds libStOpt/libgeners in the same folder.
if (UNIX AND NOT WIN32 AND NOT APPLE)
    SET_TARGET_PROPERTIES(StOpt PROPERTIES
      BUILD_RPATH "\$ORIGIN"
      INSTALL_RPATH "\$ORIGIN"
      )
endif()
# Keep keyword signature consistent
TARGET_INCLUDE_DIRECTORIES(StOpt PUBLIC ${PROJECT_SOURCE_DIR})
TARGET_LINK_LIBRARIES(StOpt PUBLIC geners)
TARGET_LINK_LIBRARIES(StOpt PRIVATE ${BOOST_LIBS} ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES} ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES})
IF (OPENMP_CXX_FOUND)
  TARGET_LINK_LIBRARIES(StOpt PRIVATE OpenMP::OpenMP_CXX)
ENDIF()


# Cross‑platform install (does not change Linux behavior, only unifies syntax)
INSTALL(TARGETS StOpt
  ARCHIVE DESTINATION ${_PY_DEST}
  LIBRARY DESTINATION ${_PY_DEST}
  RUNTIME DESTINATION ${_PY_DEST}
  )
# install headers
INSTALL(DIRECTORY StOpt
    COMPONENT headers
    DESTINATION "include"
    FILES_MATCHING
    PATTERN "*.h"
    ${INSTALL_PERMISSIONS_SRC}
  )


SET (STOPT_LIB StOpt)


IF(BUILD_PYTHON)
  SET(SOURCE_PYTHON ${PROJECT_SOURCE_DIR}/StOpt/python)
  
  SET(PYBIND11_FINDPYTHON ON)
  
  OPTION(
    STOPT_PREFER_PIP_PYBIND11
    "Prefer pybind11 from the active Python environment"
    OFF
    )

  IF(STOPT_PREFER_PIP_PYBIND11)
    
    # Mode wheel Python : on veut le Python actif, NumPy, et pybind11 pip.
    FIND_PACKAGE(Python COMPONENTS Interpreter Development.Module NumPy REQUIRED)
    
    EXECUTE_PROCESS(
      COMMAND "${Python_EXECUTABLE}" -m pybind11 --cmakedir
      OUTPUT_VARIABLE _PYBIND11_CMAKE_DIR
      OUTPUT_STRIP_TRAILING_WHITESPACE
      RESULT_VARIABLE _PYBIND11_CMAKE_DIR_RESULT
      ERROR_QUIET
      )
    
    IF(_PYBIND11_CMAKE_DIR_RESULT EQUAL 0 AND EXISTS "${_PYBIND11_CMAKE_DIR}")
      MESSAGE(STATUS "Using pybind11 from Python environment: ${_PYBIND11_CMAKE_DIR}")
      SET(pybind11_DIR "${_PYBIND11_CMAKE_DIR}" CACHE PATH "pybind11 CMake dir from Python environment" FORCE)
    ELSE()
      MESSAGE(FATAL_ERROR
        "STOPT_PREFER_PIP_PYBIND11=ON but pybind11 could not be found from Python environment. "
        "Command failed: ${Python_EXECUTABLE} -m pybind11 --cmakedir"
        )
    ENDIF()
    
    FIND_PACKAGE(pybind11 CONFIG REQUIRED)

  ELSE()

    # Mode par défaut : comportement historique.
    # Pas de NumPy demandé ici.
    FIND_PACKAGE(pybind11 CONFIG REQUIRED)
    FIND_PACKAGE(Python COMPONENTS Interpreter Development.Module REQUIRED)

  ENDIF()

  MESSAGE(STATUS "================ Python / pybind11 diagnostic ================")
  MESSAGE(STATUS "STOPT_PREFER_PIP_PYBIND11 = ${STOPT_PREFER_PIP_PYBIND11}")
  MESSAGE(STATUS "Python_EXECUTABLE          = ${Python_EXECUTABLE}")
  MESSAGE(STATUS "Python_VERSION             = ${Python_VERSION}")
  MESSAGE(STATUS "pybind11_VERSION           = ${pybind11_VERSION}")
  MESSAGE(STATUS "pybind11_DIR               = ${pybind11_DIR}")

  IF(STOPT_PREFER_PIP_PYBIND11)
    MESSAGE(STATUS "Python_NumPy_VERSION       = ${Python_NumPy_VERSION}")
    MESSAGE(STATUS "Python_NumPy_INCLUDE_DIRS  = ${Python_NumPy_INCLUDE_DIRS}")
  ENDIF()

  MESSAGE(STATUS "===============================================================")

  IF (BUILD_SDDP)
    ADD_DEFINITIONS(-DSDDPPYTHON)
  ENDIF(BUILD_SDDP)
  
  SET(STOPT_PY_SOURCES    ${SOURCE_PYTHON}/Pybind11StOpt.cpp ${SOURCE_PYTHON}/Pybind11StOptGrids.cpp  ${SOURCE_PYTHON}/Pybind11StOptReg.cpp ${SOURCE_PYTHON}/Pybind11StOptTree.cpp ${SOURCE_PYTHON}/Pybind11StOptGeners.cpp  ${SOURCE_PYTHON}/Pybind11StOptGlobal.cpp  ${SOURCE_PYTHON}/Pybind11StOptCDF.cpp  ${SOURCE_PYTHON}/Pybind11StOptSDDP.cpp )
  PYBIND11_ADD_MODULE(pystopt MODULE ${STOPT_PY_SOURCES})
  
  # FOR PIP
  # RPATH only on Linux (Windows does not use RPATH)
  IF (UNIX AND NOT WIN32 AND NOT APPLE)
    SET_TARGET_PROPERTIES(pystopt PROPERTIES
      BUILD_RPATH "\$ORIGIN"
      INSTALL_RPATH "\$ORIGIN"
      )
  ENDIF()
  
  # Make sure the link signature is keyword-only and geners is propagated
  TARGET_LINK_LIBRARIES(pystopt PUBLIC geners)
  TARGET_LINK_LIBRARIES(pystopt PRIVATE 
    pybind11::module  Python::Module ${STOPT_LIB}  ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES} ${BOOST_LIBS}
    ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES}
    $<$<BOOL:${OpenMP_CXX_FOUND}>:OpenMP::OpenMP_CXX>
    $<$<BOOL:${STOPT_ENABLE_MPI}>:MPI::MPI_CXX>)
  
  # Install the Python extension into the same folder as the other native libs
  INSTALL(TARGETS pystopt
    ARCHIVE DESTINATION ${_PY_DEST}
    LIBRARY DESTINATION ${_PY_DEST}
    RUNTIME DESTINATION ${_PY_DEST})
  
  if(APPLE)
    # Force  RPATH standards in CMake
    set(CMAKE_MACOSX_RPATH ON)
    set(CMAKE_SKIP_BUILD_RPATH  FALSE)
    set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
    set(CMAKE_INSTALL_RPATH "@loader_path")
    
    set_target_properties(StOpt PROPERTIES INSTALL_NAME_DIR "@rpath")
    set_target_properties(geners PROPERTIES INSTALL_NAME_DIR "@rpath")
    
    if(TARGET pystopt)
        set_target_properties(pystopt PROPERTIES INSTALL_RPATH "@loader_path")
      endif()
     
  endif()

ENDIF(BUILD_PYTHON)




IF(BUILD_TEST)
  # compile source for tests
  #INCLUDE_DIRECTORIES(SYSTEM ${PROJECT_SOURCE_DIR} ${BOOST_INCLUDE_DIRS})
  SET(SOURCE_DIR_TEST1 ${PROJECT_SOURCE_DIR}/test/c++/tools/dp )
  SET(SOURCE_DIR_TEST2 ${PROJECT_SOURCE_DIR}/test/c++/tools/semilagrangien/)
  SET(SOURCE_DIR_TEST3 ${PROJECT_SOURCE_DIR}/test/c++/tools/simulators/)
  SET(SOURCE_DIR_TEST4 ${PROJECT_SOURCE_DIR}/test/c++/tools/utils/)
  FILE(GLOB SOURCE_TEST  ${SOURCE_DIR_TEST1}/*.cpp ${SOURCE_DIR_TEST2}/*.cpp  ${SOURCE_DIR_TEST3}/*.cpp  ${SOURCE_DIR_TEST4}/*.cpp  )
  IF (WIN32)
    ADD_LIBRARY(StOptTest STATIC ${SOURCE_TEST})
  ELSE()
    ADD_LIBRARY(StOptTest SHARED ${SOURCE_TEST})
  ENDIF()
  IF(BUILD_MPI)
    TARGET_LINK_LIBRARIES(StOptTest ${STOPT_LIB} ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES} Boost::mpi  Boost::serialization ${GENERS_LIB})
  ELSE()
    TARGET_LINK_LIBRARIES(StOptTest  ${STOPT_LIB}  Boost::serialization ${GENERS_LIB})
  ENDIF()  
  SET (STOPTTEST_LIB StOptTest)
  #install test
  INSTALL(TARGETS StOptTest  COMPONENT libraries DESTINATION "lib")
  #install header for test
  INSTALL(DIRECTORY test
    DESTINATION "example"
    FILES_MATCHING
    PATTERN "*.py"
    PATTERN "*.cpp"
    PATTERN "*.h"
    ${INSTALL_PERMISSIONS_SRC}
    )  
  #test unit
  SET(SOURCE_UNIT_TEST  ${PROJECT_SOURCE_DIR}/test/c++/unit)
  SET(SOURCE_UNIT_TEST_GLOBAL  ${SOURCE_UNIT_TEST}/global)

  ADD_EXECUTABLE(testGlobal ${SOURCE_UNIT_TEST_GLOBAL}/testGlobal.cpp)
  TARGET_LINK_LIBRARIES(testGlobal ${STOPT_LIB}   ${GENERS_LIB} ${BOOST_LIBS}  )
  SET(SOURCE_UNIT_TEST_TREE  ${SOURCE_UNIT_TEST}/tree)
  ADD_EXECUTABLE(testTreeExpCond ${SOURCE_UNIT_TEST_TREE}/testTreeExpCond.cpp)
  TARGET_LINK_LIBRARIES(testTreeExpCond ${STOPT_LIB}   ${STOPTTEST_LIB}  ${GENERS_LIB} ${BOOST_LIBS})
  SET(SOURCE_UNIT_TEST_CDF  ${SOURCE_UNIT_TEST}/cdf)
  ADD_EXECUTABLE(testFastCDF ${SOURCE_UNIT_TEST_CDF}/testFastCDF.cpp)
  TARGET_LINK_LIBRARIES(testFastCDF ${STOPT_LIB}   ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testFastCDFOnSample ${SOURCE_UNIT_TEST_CDF}/testFastCDFOnSample.cpp)
  TARGET_LINK_LIBRARIES(testFastCDFOnSample ${STOPT_LIB}   ${GENERS_LIB}     ${BOOST_LIBS})
  SET(SOURCE_UNIT_TEST_REGRESSION  ${SOURCE_UNIT_TEST}/regression)
  ADD_EXECUTABLE(testLocalLinearRegression ${SOURCE_UNIT_TEST_REGRESSION}/testLocalLinearRegression.cpp)
  TARGET_LINK_LIBRARIES(testLocalLinearRegression ${STOPT_LIB}   ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testLocalConstRegression ${SOURCE_UNIT_TEST_REGRESSION}/testLocalConstRegression.cpp)
  TARGET_LINK_LIBRARIES(testLocalConstRegression ${STOPT_LIB}   ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testLocalDiscrLastDimRegression ${SOURCE_UNIT_TEST_REGRESSION}/testLocalDiscrLastDimRegression.cpp)
  TARGET_LINK_LIBRARIES(testLocalDiscrLastDimRegression ${STOPT_LIB}   ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testLocalKMeansRegression ${SOURCE_UNIT_TEST_REGRESSION}/testLocalKMeansRegression.cpp)
  TARGET_LINK_LIBRARIES(testLocalKMeansRegression ${STOPT_LIB}   ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testLocalSameSizeLinearRegression ${SOURCE_UNIT_TEST_REGRESSION}/testLocalSameSizeLinearRegression.cpp)
  TARGET_LINK_LIBRARIES(testLocalSameSizeLinearRegression ${STOPT_LIB}   ${GENERS_LIB}      ${BOOST_LIBS})
  ADD_EXECUTABLE(testLocalSameSizeConstRegression ${SOURCE_UNIT_TEST_REGRESSION}/testLocalSameSizeConstRegression.cpp)
  TARGET_LINK_LIBRARIES(testLocalSameSizeConstRegression ${STOPT_LIB}   ${GENERS_LIB}    ${BOOST_LIBS})
  ADD_EXECUTABLE(testSparseRegression ${SOURCE_UNIT_TEST_REGRESSION}/testSparseRegression.cpp)
  TARGET_LINK_LIBRARIES(testSparseRegression ${STOPT_LIB}   ${GENERS_LIB}  ${BOOST_LIBS})
  ADD_EXECUTABLE(testMultiVariateBasis ${SOURCE_UNIT_TEST_REGRESSION}/testMultiVariateBasis.cpp )
  TARGET_LINK_LIBRARIES(testMultiVariateBasis ${STOPT_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
  ADD_EXECUTABLE(testGlobalRegression ${SOURCE_UNIT_TEST_REGRESSION}/testGlobalRegression.cpp)
  TARGET_LINK_LIBRARIES(testGlobalRegression ${STOPT_LIB}   ${GENERS_LIB}      ${BOOST_LIBS} )
  ADD_EXECUTABLE(testLaplacianConstKernelRegression ${SOURCE_UNIT_TEST_REGRESSION}/testLaplacianConstKernelRegression.cpp)
  TARGET_LINK_LIBRARIES( testLaplacianConstKernelRegression ${STOPT_LIB}   ${GENERS_LIB}      ${BOOST_LIBS})
  ADD_EXECUTABLE(testLaplacianLinearKernelRegression ${SOURCE_UNIT_TEST_REGRESSION}/testLaplacianLinearKernelRegression.cpp)
  TARGET_LINK_LIBRARIES( testLaplacianLinearKernelRegression ${STOPT_LIB}   ${GENERS_LIB}      ${BOOST_LIBS})
  ADD_EXECUTABLE(testGridKernelRegression ${SOURCE_UNIT_TEST_REGRESSION}/testGridKernelRegression.cpp)
  TARGET_LINK_LIBRARIES(testGridKernelRegression ${STOPT_LIB}   ${GENERS_LIB}      ${BOOST_LIBS})
  ADD_EXECUTABLE(testLaplacianGridKernelRegression ${SOURCE_UNIT_TEST_REGRESSION}/testLaplacianGridKernelRegression.cpp)
  TARGET_LINK_LIBRARIES(testLaplacianGridKernelRegression ${STOPT_LIB}   ${GENERS_LIB}      ${BOOST_LIBS})
  ADD_EXECUTABLE(testGridAndRegressedValue ${SOURCE_UNIT_TEST_REGRESSION}/testGridAndRegressedValue.cpp)
  TARGET_LINK_LIBRARIES(testGridAndRegressedValue ${STOPT_LIB} ${GENERS_LIB}  ${BOOST_LIBS})
  ADD_EXECUTABLE(testDominanceKernel ${SOURCE_UNIT_TEST_REGRESSION}/testDominanceKernel.cpp)
  TARGET_LINK_LIBRARIES(testDominanceKernel  ${STOPT_LIB}   ${STOPTTEST_LIB}  ${GENERS_LIB} ${BOOST_LIBS}   )
  ADD_EXECUTABLE(testLaplacianKernel ${SOURCE_UNIT_TEST_REGRESSION}/testLaplacianKernel.cpp)
  TARGET_LINK_LIBRARIES(testLaplacianKernel  ${STOPT_LIB}   ${STOPTTEST_LIB}  ${GENERS_LIB} ${BOOST_LIBS}   )
  ADD_EXECUTABLE(testLocalCutsGridAdapt1D ${SOURCE_UNIT_TEST_REGRESSION}/testLocalCutsGridAdapt1D.cpp)
  TARGET_LINK_LIBRARIES(testLocalCutsGridAdapt1D  ${STOPT_LIB}   ${STOPTTEST_LIB}  ${GENERS_LIB} ${BOOST_LIBS}   )
  ADD_EXECUTABLE(testLocalCutsGridAdapt2D ${SOURCE_UNIT_TEST_REGRESSION}/testLocalCutsGridAdapt2D.cpp)
  TARGET_LINK_LIBRARIES(testLocalCutsGridAdapt2D  ${STOPT_LIB}   ${STOPTTEST_LIB}  ${GENERS_LIB} ${BOOST_LIBS}   )
    
  SET(SOURCE_UNIT_TEST_GRIDS ${SOURCE_UNIT_TEST}/grids)
  ADD_EXECUTABLE(testRegularSpaceGrid ${SOURCE_UNIT_TEST_GRIDS}/testRegularSpaceGrid.cpp)
  TARGET_LINK_LIBRARIES(testRegularSpaceGrid ${STOPT_LIB}   ${GENERS_LIB}  ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT})
  ADD_EXECUTABLE(testGrids ${SOURCE_UNIT_TEST_GRIDS}/testGrids.cpp)
  TARGET_LINK_LIBRARIES(testGrids ${STOPT_LIB}   ${GENERS_LIB}      ${BOOST_LIBS})
  ADD_EXECUTABLE(testGridAdap1D ${SOURCE_UNIT_TEST_GRIDS}/testGridAdap1D.cpp)
  TARGET_LINK_LIBRARIES(testGridAdap1D ${STOPT_LIB}   ${GENERS_LIB}      ${BOOST_LIBS})
  ADD_EXECUTABLE(testGridAdap2D ${SOURCE_UNIT_TEST_GRIDS}/testGridAdap2D.cpp)
  TARGET_LINK_LIBRARIES(testGridAdap2D ${STOPT_LIB}   ${GENERS_LIB}      ${BOOST_LIBS})
  ADD_EXECUTABLE(testGridsLegendre ${SOURCE_UNIT_TEST_GRIDS}/testGridsLegendre.cpp)
  TARGET_LINK_LIBRARIES(testGridsLegendre ${STOPT_LIB}   ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testGridsSparse ${SOURCE_UNIT_TEST_GRIDS}/testGridsSparse.cpp)
  TARGET_LINK_LIBRARIES(testGridsSparse ${STOPT_LIB}   ${GENERS_LIB}    ${BOOST_LIBS})
  ADD_EXECUTABLE(testLinearInterpolator ${SOURCE_UNIT_TEST_GRIDS}/testLinearInterpolator.cpp)
  TARGET_LINK_LIBRARIES(testLinearInterpolator ${STOPT_LIB} ${GENERS_LIB}    ${BOOST_LIBS})
  ADD_EXECUTABLE(testLegendreInterpolator ${SOURCE_UNIT_TEST_GRIDS}/testLegendreInterpolator.cpp)
  TARGET_LINK_LIBRARIES(testLegendreInterpolator ${STOPT_LIB}  ${GENERS_LIB}    ${BOOST_LIBS})
  ADD_EXECUTABLE(testSparseInterpolator ${SOURCE_UNIT_TEST_GRIDS}/testSparseInterpolator.cpp)
  TARGET_LINK_LIBRARIES(testSparseInterpolator ${STOPT_LIB}   ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testSparseHierarchization ${SOURCE_UNIT_TEST_GRIDS}/testSparseHierarchization.cpp)
  TARGET_LINK_LIBRARIES(testSparseHierarchization ${STOPT_LIB}   ${GENERS_LIB}    ${BOOST_LIBS})
  ADD_EXECUTABLE(testSparseDimensionAdaptive ${SOURCE_UNIT_TEST_GRIDS}/testSparseDimensionAdaptive.cpp)
  TARGET_LINK_LIBRARIES(testSparseDimensionAdaptive ${STOPT_LIB}   ${GENERS_LIB}    ${BOOST_LIBS})
  SET(SOURCE_UNIT_TEST_UTILS ${SOURCE_UNIT_TEST}/utils)
  ADD_EXECUTABLE(testNodeSplitting ${SOURCE_UNIT_TEST_UTILS}/testNodeSplitting.cpp)
  TARGET_LINK_LIBRARIES(testNodeSplitting ${STOPT_LIB}  ${GENERS_LIB} ${BOOST_LIBS})
  ADD_EXECUTABLE(testKDTree ${SOURCE_UNIT_TEST_UTILS}/testKDTree.cpp)
  TARGET_LINK_LIBRARIES(testKDTree ${STOPT_LIB}  ${GENERS_LIB} ${BOOST_LIBS})
  ADD_EXECUTABLE(testSerialization ${SOURCE_UNIT_TEST_UTILS}/testSerialization.cpp)
  TARGET_LINK_LIBRARIES(testSerialization ${STOPT_LIB}  ${GENERS_LIB} ${BOOST_LIBS})
  SET(SOURCE_UNIT_TEST_SPARSE  ${SOURCE_UNIT_TEST}/sparse)
  ADD_EXECUTABLE(testHierarchizationNoBound ${SOURCE_UNIT_TEST_SPARSE}/testHierarchizationNoBound.cpp)
  TARGET_LINK_LIBRARIES(testHierarchizationNoBound ${STOPT_LIB}  ${GENERS_LIB}    ${BOOST_LIBS})
  ADD_EXECUTABLE(testHierarchizationBound ${SOURCE_UNIT_TEST_SPARSE}/testHierarchizationBound.cpp)
  TARGET_LINK_LIBRARIES(testHierarchizationBound ${STOPT_LIB}  ${GENERS_LIB}    ${BOOST_LIBS})
  SET(SOURCE_UNIT_TEST_SDDP  ${SOURCE_UNIT_TEST}/sddp)
  ADD_EXECUTABLE(testSDDPTree  ${SOURCE_UNIT_TEST_SDDP}/testSDDPTree.cpp)
  TARGET_LINK_LIBRARIES(testSDDPTree  ${STOPT_LIB}  ${STOPTTEST_LIB}  ${GENERS_LIB}    ${MPI_CXX_LIBRARIES} ${BOOST_LIBS})
 
  #functional test
  SET(SOURCE_FUNC_TEST  ${PROJECT_SOURCE_DIR}/test/c++/functional)
  ADD_EXECUTABLE(testSwingOptimSimu  ${SOURCE_FUNC_TEST}/testSwingOptimSimu.cpp )
  TARGET_LINK_LIBRARIES(testSwingOptimSimu  ${STOPT_LIB} ${STOPTTEST_LIB}  ${GENERS_LIB}   ${BOOST_LIBS})
  ADD_EXECUTABLE(testSwingOptimSimuWithHedge  ${SOURCE_FUNC_TEST}/testSwingOptimSimuWithHedge.cpp )
  TARGET_LINK_LIBRARIES(testSwingOptimSimuWithHedge  ${STOPT_LIB} ${STOPTTEST_LIB}  ${GENERS_LIB}   ${BOOST_LIBS})
  ADD_EXECUTABLE(testAmericanOption ${SOURCE_FUNC_TEST}/testAmericanOption.cpp)
  TARGET_LINK_LIBRARIES(testAmericanOption ${STOPT_LIB}  ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testAmericanOptionTree ${SOURCE_FUNC_TEST}/testAmericanOptionTree.cpp)
  TARGET_LINK_LIBRARIES(testAmericanOptionTree ${STOPT_LIB}  ${STOPTTEST_LIB} ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testAmericanOptionCorrel ${SOURCE_FUNC_TEST}/testAmericanOptionCorrel.cpp)
  TARGET_LINK_LIBRARIES(testAmericanOptionCorrel ${STOPT_LIB}  ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testAmericanConvex ${SOURCE_FUNC_TEST}/testAmericanConvex.cpp)
  TARGET_LINK_LIBRARIES(testAmericanConvex ${STOPT_LIB}  ${GENERS_LIB}     ${BOOST_LIBS})
  ADD_EXECUTABLE(testAmericanOptionForSparse ${SOURCE_FUNC_TEST}/testAmericanOptionForSparse.cpp)
  TARGET_LINK_LIBRARIES(testAmericanOptionForSparse  ${STOPT_LIB}  ${GENERS_LIB}    ${BOOST_LIBS})
  ADD_EXECUTABLE(testGasStorage  ${SOURCE_FUNC_TEST}/testGasStorage.cpp )
  TARGET_LINK_LIBRARIES(testGasStorage  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}   )
  ADD_EXECUTABLE(testGasStorageMultiStage  ${SOURCE_FUNC_TEST}/testGasStorageMultiStage.cpp )
  TARGET_LINK_LIBRARIES(testGasStorageMultiStage   ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}   )
  ADD_EXECUTABLE(testGasStorageTree  ${SOURCE_FUNC_TEST}/testGasStorageTree.cpp )
  TARGET_LINK_LIBRARIES(testGasStorageTree  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}   )
  ADD_EXECUTABLE(testGasStorageGlobal  ${SOURCE_FUNC_TEST}/testGasStorageGlobal.cpp )
  TARGET_LINK_LIBRARIES(testGasStorageGlobal  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS}  )
  ADD_EXECUTABLE(testGasStorageKMeans  ${SOURCE_FUNC_TEST}/testGasStorageKMeans.cpp )
  TARGET_LINK_LIBRARIES(testGasStorageKMeans  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS}  )
  ADD_EXECUTABLE(testGasStorageKernel  ${SOURCE_FUNC_TEST}/testGasStorageKernel.cpp )
  TARGET_LINK_LIBRARIES(testGasStorageKernel  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS}  )
  ADD_EXECUTABLE(testGasStorageLaplacianConstKernel  ${SOURCE_FUNC_TEST}/testGasStorageLaplacianConstKernel.cpp )
  TARGET_LINK_LIBRARIES(testGasStorageLaplacianConstKernel  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS}  )
  ADD_EXECUTABLE(testGasStorageLaplacianLinearKernel  ${SOURCE_FUNC_TEST}/testGasStorageLaplacianLinearKernel.cpp )
  TARGET_LINK_LIBRARIES(testGasStorageLaplacianLinearKernel  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS}  )
  ADD_EXECUTABLE(testGasStorageLaplacianGridKernel  ${SOURCE_FUNC_TEST}/testGasStorageLaplacianGridKernel.cpp )
  TARGET_LINK_LIBRARIES(testGasStorageLaplacianGridKernel  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS}  )
  ADD_EXECUTABLE(testLake  ${SOURCE_FUNC_TEST}/testLake.cpp )
  TARGET_LINK_LIBRARIES(testLake  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS}   )
  ADD_EXECUTABLE(testLakeIid  ${SOURCE_FUNC_TEST}/testLakeIid.cpp )
  TARGET_LINK_LIBRARIES(testLakeIid  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}  )
  ADD_EXECUTABLE(testGasStorageVaryingCavity  ${SOURCE_FUNC_TEST}/testGasStorageVaryingCavity.cpp)
  TARGET_LINK_LIBRARIES(testGasStorageVaryingCavity  ${STOPT_LIB}   ${STOPTTEST_LIB}  ${GENERS_LIB}    ${BOOST_LIBS}  )
  ADD_EXECUTABLE(testSemiLagragian1  ${SOURCE_FUNC_TEST}/testSemiLagragian1.cpp  )
  TARGET_LINK_LIBRARIES(testSemiLagragian1  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
  ADD_EXECUTABLE(testSemiLagragian2 ${SOURCE_FUNC_TEST}/testSemiLagragian2.cpp  )
  TARGET_LINK_LIBRARIES(testSemiLagragian2  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
  ADD_EXECUTABLE(testSemiLagragian3 ${SOURCE_FUNC_TEST}/testSemiLagragian3.cpp )
  TARGET_LINK_LIBRARIES(testSemiLagragian3  ${STOPT_LIB}   ${STOPTTEST_LIB}  ${GENERS_LIB}   ${BOOST_LIBS})
  ADD_EXECUTABLE(testPortfolioMMModel ${SOURCE_FUNC_TEST}/testPortfolioMMModel.cpp)
  TARGET_LINK_LIBRARIES(testPortfolioMMModel  ${STOPT_LIB}   ${STOPTTEST_LIB}  ${GENERS_LIB} ${BOOST_LIBS}   )
  ADD_EXECUTABLE(testThermalAsset  ${SOURCE_FUNC_TEST}/testThermalAsset.cpp )
  TARGET_LINK_LIBRARIES(testThermalAsset  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}   )

  
  # for tests
  ENABLE_TESTING ()
  ADD_TEST(NAME MyTestForGlobal  COMMAND testGlobal)
  ADD_TEST(NAME MyTestForTreeExpCond  COMMAND testTreeExpCond)
  ADD_TEST(NAME MyTestForFastCDF COMMAND testFastCDF)
  ADD_TEST(NAME MyTestForFastCDFOnSample COMMAND testFastCDFOnSample)
  ADD_TEST(NAME MyTestForLinearRegression COMMAND testLocalLinearRegression)
  ADD_TEST(NAME MyTestForConstRegression COMMAND testLocalConstRegression)
  ADD_TEST(NAME MyTestForDiscrLastDimRegression COMMAND testLocalDiscrLastDimRegression)
  ADD_TEST(NAME MyTestForLocalKMeansRegression  COMMAND  testLocalKMeansRegression)
  ADD_TEST(NAME MyTestForSameSizeLinearRegression COMMAND testLocalSameSizeLinearRegression)
  ADD_TEST(NAME MyTestForSameSizeConstRegression COMMAND testLocalSameSizeConstRegression)
  ADD_TEST(NAME MyTestForGlobalARegression COMMAND testGlobalRegression)
  ADD_TEST(NAME MyTestForGridKernelRegression COMMAND testGridKernelRegression)
  ADD_TEST(NAME MyTestForLaplacianConstKernelRegression   COMMAND   testLaplacianConstKernelRegression)
  ADD_TEST(NAME MyTestForLaplacianLinearKernelRegression   COMMAND   testLaplacianLinearKernelRegression)
  ADD_TEST(NAME MyTestForDominanceKernel COMMAND testDominanceKernel)
  Add_TEST(NAME MyTestForLaplacianKernel COMMAND testLaplacianKernel)
  ADD_TEST(NAME MyTestForSparseRegression COMMAND testSparseRegression)
  ADD_TEST(NAME MyTestForGridAndRegressedValue COMMAND testGridAndRegressedValue)
  ADD_TEST(NAME MyTestForGrids COMMAND testGrids)
  ADD_TEST(NAME MyTestForGridsLegendre COMMAND testGridsLegendre)
  ADD_TEST(NAME MyTestForGridsSparse COMMAND testGridsSparse)
  ADD_TEST(NAME MyTestForLinearInterpolators COMMAND testLinearInterpolator)
  ADD_TEST(NAME MyTestForLegendreInterpolators COMMAND testLegendreInterpolator)
  ADD_TEST(NAME MyTestForRegularSpaceGrid COMMAND testRegularSpaceGrid)
  ADD_TEST(NAME MyTestForSparseGridsInterpolator COMMAND testSparseInterpolator)
  ADD_TEST(NAME MyTestForSparseDimensionAdaptive COMMAND testSparseDimensionAdaptive)
  ADD_TEST(NAME MyTestForAmericanOption COMMAND  testAmericanOption)
  ADD_TEST(NAME MyTestForAmericanOptionTree COMMAND  testAmericanOptionTree)
  ADD_TEST(NAME MyTestForAmericanConvex COMMAND  testAmericanConvex)
  ADD_TEST(NAME MyTestForAmericanOptionForSparse COMMAND  testAmericanOptionForSparse)
  ADD_TEST(NAME MyTestForNodeSplitting COMMAND  testNodeSplitting)
  ADD_TEST(NAME MyTestForKDTree COMMAND  testKDTree)
  ADD_TEST(NAME MyTestForGasStorage COMMAND testGasStorage)
  ADD_TEST(NAME MyTestForGasStorageTree COMMAND testGasStorageTree)
  ADD_TEST(NAME MyTestForGasStorageGlobal COMMAND testGasStorageGlobal)
  ADD_TEST(NAME MyTestForGasStorageKernel COMMAND testGasStorageKernel)
  ADD_TEST(NAME MyTestForGasStorageLaplacianConstKernel COMMAND testGasStorageLaplacianConstKernel)
  ADD_TEST(NAME MyTestForGasStorageLaplacianLinearKernel COMMAND testGasStorageLaplacianLinearKernel)
  ADD_TEST(NAME MyTestForGasStorageLaplacianGridKernel COMMAND testGasStorageLaplacianGridKernel)
  ADD_TEST(NAME MyTestForLake COMMAND testLake)
  ADD_TEST(NAME MyTestForGasStorageVaryingCavity COMMAND testGasStorageVaryingCavity)
  ADD_TEST(NAME MyTestForHierarchizationBound COMMAND testHierarchizationBound)
  ADD_TEST(NAME MyTestForHierarchizationNoBound COMMAND testHierarchizationNoBound)
  ADD_TEST(NAME MyTestForSparseHierarchization COMMAND  testSparseHierarchization)
  ADD_TEST(NAME MyTestForMultiVariateBasis COMMAND testMultiVariateBasis)
  ADD_TEST(NAME MyTestForSemiLagragian1 COMMAND testSemiLagragian1)
  ADD_TEST(NAME MyTestForSemiLagragian2 COMMAND testSemiLagragian2)
  ADD_TEST(NAME MyTestForPortfolioMMModel COMMAND testPortfolioMMModel)
  ADD_TEST(NAME MyTestForSDDPTree    COMMAND testSDDPTree)
  ADD_TEST(NAME MyTestForThermalAsset    COMMAND testThermalAsset)
  
  IF(BUILD_MPI)
    ADD_EXECUTABLE(testSwingOptimSimuND  ${SOURCE_FUNC_TEST}/testSwingOptimSimuND.cpp)
    TARGET_LINK_LIBRARIES(testSwingOptimSimuND  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}  ${BZIP2_LIBRARIES}  ${ZLIB_LIBRARIES}  ${BOOST_LIBS}   ${MPI_LIBRARIES}  ${ADD_LIB_OMP})
    ADD_EXECUTABLE(testSwingOption ${SOURCE_FUNC_TEST}/testSwingOption.cpp )
    TARGET_LINK_LIBRARIES(testSwingOption ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}   ${MPI_CXX_LIBRARIES})
    # Unit tests for MPI
    ADD_EXECUTABLE(testSDDP  ${SOURCE_UNIT_TEST_SDDP}/testSDDP.cpp)
    TARGET_LINK_LIBRARIES(testSDDP  ${STOPT_LIB}   ${GENERS_LIB}    ${MPI_CXX_LIBRARIES} ${BOOST_LIBS})
    SET(SOURCE_UNIT_TEST_PARALLELIZATION ${SOURCE_UNIT_TEST}/parallelism)
    ADD_EXECUTABLE(testParallelism ${SOURCE_UNIT_TEST_PARALLELIZATION}/testParallelism.cpp)
    TARGET_LINK_LIBRARIES(testParallelism ${STOPT_LIB}  ${GENERS_LIB}      ${BOOST_LIBS}  ${MPI_CXX_LIBRARIES})
    ADD_EXECUTABLE(testSwingOptimSimuMpi  ${SOURCE_FUNC_TEST}/testSwingOptimSimuMpi.cpp)
    TARGET_LINK_LIBRARIES(testSwingOptimSimuMpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS} ${MPI_CXX_LIBRARIES})
    ADD_EXECUTABLE(testSwingOptimSimuNDMpi  ${SOURCE_FUNC_TEST}/testSwingOptimSimuNDMpi.cpp)
    TARGET_LINK_LIBRARIES(testSwingOptimSimuNDMpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}  ${BOOST_LIBS}    ${MPI_CXX_LIBRARIES})
    ADD_EXECUTABLE(testLakeMpi  ${SOURCE_FUNC_TEST}/testLakeMpi.cpp )
    TARGET_LINK_LIBRARIES(testLakeMpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}  ${BOOST_LIBS}   )
    ADD_EXECUTABLE(testGasStorageMpi ${SOURCE_FUNC_TEST}/testGasStorageMpi.cpp  )
    TARGET_LINK_LIBRARIES(testGasStorageMpi  ${STOPT_LIB} ${STOPTTEST_LIB}  ${GENERS_LIB}   ${MPI_CXX_LIBRARIES} ${BOOST_LIBS} )
    ADD_EXECUTABLE(testGasStorageMultiStageMpi ${SOURCE_FUNC_TEST}/testGasStorageMultiStageMpi.cpp  )
    TARGET_LINK_LIBRARIES(testGasStorageMultiStageMpi  ${STOPT_LIB} ${STOPTTEST_LIB}  ${GENERS_LIB}   ${MPI_CXX_LIBRARIES} ${BOOST_LIBS} )
    ADD_EXECUTABLE(testGasStorageTreeMpi ${SOURCE_FUNC_TEST}/testGasStorageTreeMpi.cpp  )
    TARGET_LINK_LIBRARIES(testGasStorageTreeMpi  ${STOPT_LIB} ${STOPTTEST_LIB}  ${GENERS_LIB}   ${MPI_CXX_LIBRARIES} ${BOOST_LIBS} )
    ADD_EXECUTABLE(testGasStorageGlobalMpi ${SOURCE_FUNC_TEST}/testGasStorageGlobalMpi.cpp  )
    TARGET_LINK_LIBRARIES(testGasStorageGlobalMpi  ${STOPT_LIB} ${STOPTTEST_LIB}  ${GENERS_LIB}   ${MPI_CXX_LIBRARIES} ${BOOST_LIBS} )
    ADD_EXECUTABLE(testGasStorageVaryingCavityMpi  ${SOURCE_FUNC_TEST}/testGasStorageVaryingCavityMpi.cpp )
    TARGET_LINK_LIBRARIES(testGasStorageVaryingCavityMpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}  ${BOOST_LIBS}   )
    ADD_EXECUTABLE(testGasStorageSwitchCostMpi ${SOURCE_FUNC_TEST}/testGasStorageSwitchCostMpi.cpp )
    TARGET_LINK_LIBRARIES(testGasStorageSwitchCostMpi  ${STOPT_LIB}  ${STOPTTEST_LIB}  ${GENERS_LIB}     ${MPI_CXX_LIBRARIES} ${BOOST_LIBS})
    ADD_EXECUTABLE(testSemiLagragian1Mpi ${SOURCE_FUNC_TEST}/testSemiLagragian1Mpi.cpp )
    TARGET_LINK_LIBRARIES(testSemiLagragian1Mpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
    ADD_EXECUTABLE(testSemiLagragian2Mpi ${SOURCE_FUNC_TEST}/testSemiLagragian2Mpi.cpp  )
    TARGET_LINK_LIBRARIES(testSemiLagragian2Mpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
    ADD_EXECUTABLE(testSemiLagragian3Mpi ${SOURCE_FUNC_TEST}/testSemiLagragian3Mpi.cpp )
    TARGET_LINK_LIBRARIES(testSemiLagragian3Mpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
    # add compilation without adding to ctest (to long)
    ADD_EXECUTABLE(testSLNonEmissive ${SOURCE_FUNC_TEST}/testSLNonEmissive.cpp )
    TARGET_LINK_LIBRARIES(testSLNonEmissive  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}     ${BOOST_LIBS})
    ADD_EXECUTABLE(testDPNonEmissive ${SOURCE_FUNC_TEST}/testDPNonEmissive.cpp )
    TARGET_LINK_LIBRARIES(testDPNonEmissive  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
    ADD_EXECUTABLE(testOptionNIGL2 ${SOURCE_FUNC_TEST}/testOptionNIGL2.cpp)
    TARGET_LINK_LIBRARIES(testOptionNIGL2 ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
    ADD_EXECUTABLE(testThermalAssetMpi  ${SOURCE_FUNC_TEST}/testThermalAssetMpi.cpp )
    TARGET_LINK_LIBRARIES(testThermalAssetMpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}   )

    # proc for MPI
    SET(PROCS 1)
    IF (NOT WIN32)
      SET(MPIEXEC_PREFLAGS "--oversubscribe")
    ENDIF()
    ADD_TEST (NAME MyTestSwingOptimSimuMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS}  ${MPIEXEC_PREFLAGS}  ./bin${SUFF}/testSwingOptimSimuMpi${EXTENSION} ${MPIEXEC_POSTFLAGS})
    ADD_TEST(NAME MyTestForSDDPMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSDDP${EXTENSION}  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForLakeMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testLakeMpi${EXTENSION}   ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageMultiStageMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageMultiStageMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageTreeMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageTreeMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageGlobalMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageGlobalMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageVaryingCavityMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageVaryingCavityMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageSwitchCostMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageSwitchCostMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForSemiLagragian1Mpi COMMAND testSemiLagragian1Mpi)
    ADD_TEST(NAME MyTestForSemiLagragian2Mpi COMMAND testSemiLagragian2Mpi)
    ADD_TEST(NAME MyTestForSemiLagragian3Mpi COMMAND testSemiLagragian3Mpi)
    ADD_TEST(NAME MyTestForOptionNIGL2 COMMAND testOptionNIGL2)
    ADD_TEST(NAME MyTestForThermalAssetMpi    COMMAND testThermalAssetMpi)
    ADD_TEST(NAME MyTestForSwing  COMMAND testSwingOption )
    SET(PROCS 4)
    ADD_TEST (NAME MyTestForParallelism4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testParallelism  ${MPIEXEC_POSTFLAGS})
    ADD_TEST (NAME MyTestForSwing4core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSwingOption  ${MPIEXEC_POSTFLAGS})
    ADD_TEST (NAME MyTestSwingOptimSimuMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSwingOptimSimuMpi ${MPIEXEC_POSTFLAGS})
    ADD_TEST (NAME MyTestForSwingOptimSimuNDMpi4core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSwingOptimSimuNDMpi ${MPIEXEC_POSTFLAGS})
    ADD_TEST(NAME MyTestForSDDPMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSDDP  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForLakeMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testLakeMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageMultiStageMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageMultiStageMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageTreeMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageTreeMpi  ${MPIEXEC_POSTFLAGS}) 

    ADD_TEST(NAME MyTestForGasStorageGlobalMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageGlobalMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageVaryingCavityMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageVaryingCavityMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForGasStorageSwitchMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageSwitchCostMpi  ${MPIEXEC_POSTFLAGS}) 
    ADD_TEST(NAME MyTestForSemiLagragian1Mpi4core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSemiLagragian1Mpi ${MPIEXEC_POSTFLAGS} )
    ADD_TEST(NAME MyTestForSemiLagragian2Mpi4core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSemiLagragian2Mpi ${MPIEXEC_POSTFLAGS} )
    ADD_TEST(NAME MyTestForPortfolioMMModel4core  COMMAND  ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testPortfolioMMModel ${MPIEXEC_POSTFLAGS})
    ADD_TEST(NAME MyTestForOptionNIGL24core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testOptionNIGL2  ${MPIEXEC_POSTFLAGS})
    ADD_TEST(NAME MyTestForThermalAssetMpi4core    COMMAND  ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testThermalAssetMpi ${MPIEXEC_POSTFLAGS})
    IF(TEST_LONG_TESTS)
      ADD_TEST(NAME MyTestForSLNonEmissive4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSLNonEmissive ${MPIEXEC_POSTFLAGS} )
      ADD_TEST(NAME MyTestForDPNonEmissive4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testDPNonEmissive ${MPIEXEC_POSTFLAGS} )
    ENDIF(TEST_LONG_TESTS)
    
    SET(PROCS 8)
    ADD_TEST (NAME MyTestForParallelism8Core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testParallelism  ${MPIEXEC_POSTFLAGS})
    ADD_TEST (NAME MyTestForSwing8core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSwingOption  ${MPIEXEC_POSTFLAGS})
    ADD_TEST (NAME MyTestSwingOptimSimuMpi8core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSwingOptimSimuMpi ${MPIEXEC_POSTFLAGS})
    ADD_TEST (NAME MyTestForSwingOptimSimuNDMpi8core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSwingOptimSimuNDMpi ${MPIEXEC_POSTFLAGS})
    ADD_TEST(NAME MyTestForSemiLagragian1Mpi8core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSemiLagragian1Mpi ${MPIEXEC_POSTFLAGS} )
    ADD_TEST(NAME MyTestForSemiLagragian2Mpi8core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testSemiLagragian2Mpi ${MPIEXEC_POSTFLAGS} )
  ELSE(BUILD_MPI)
    ADD_EXECUTABLE(testSwingOptimSimuND  ${SOURCE_FUNC_TEST}/testSwingOptimSimuND.cpp)
    TARGET_LINK_LIBRARIES(testSwingOptimSimuND  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}  ${BZIP2_LIBRARIES}  ${ZLIB_LIBRARIES}   ${BOOST_LIBS}   ${ADD_LIB_OMP})
    ADD_EXECUTABLE(testSwingOption ${SOURCE_FUNC_TEST}/testSwingOption.cpp )
    TARGET_LINK_LIBRARIES(testSwingOption ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
    SET(SOURCE_UNIT_TEST_SDDP  ${SOURCE_UNIT_TEST}/sddp)
    ADD_EXECUTABLE(testSDDP  ${SOURCE_UNIT_TEST_SDDP}/testSDDP.cpp)
    TARGET_LINK_LIBRARIES(testSDDP  ${STOPT_LIB}   ${GENERS_LIB}   ${BOOST_LIBS})
    ADD_TEST (NAME MyTestForSwing  COMMAND testSwingOption)
    ADD_TEST (NAME MyTestForSDDP  COMMAND testSDDP)
  ENDIF(BUILD_MPI)
  
  ADD_TEST(NAME MyTestForSwingOptimSimuND  COMMAND testSwingOptimSimuND)
  ADD_TEST(NAME MyTestForSwingOptimSimu  COMMAND testSwingOptimSimu)
  
  # for test
  IF (BUILD_SDDP)
    FIND_PACKAGE(COIN)
    IF(NOT COIN_FOUND)
      MESSAGE(STATUS "COIN CLP OR OSI NOT FOUND")
    ENDIF(NOT COIN_FOUND)
    INCLUDE_DIRECTORIES(SYSTEM ${COIN_INCLUDE_DIRS})
    IF(BUILD_MPI)
      ADD_EXECUTABLE(testGasStorageSDDP ${SOURCE_FUNC_TEST}/testGasStorageSDDP.cpp)
      TARGET_LINK_LIBRARIES(testGasStorageSDDP   ${STOPT_LIB}  ${STOPTTEST_LIB} ${GENERS_LIB}       ${MPI_CXX_LIBRARIES} ${BOOST_LIBS}  ${PTHREAD_LIBRARY}  ${COIN_LIBRARIES}   )
      ADD_EXECUTABLE(testGasStorageSDDPTree ${SOURCE_FUNC_TEST}/testGasStorageSDDPTree.cpp)
      TARGET_LINK_LIBRARIES(testGasStorageSDDPTree   ${STOPT_LIB}  ${STOPTTEST_LIB} ${GENERS_LIB}       ${MPI_CXX_LIBRARIES} ${BOOST_LIBS}  ${PTHREAD_LIBRARY}  ${COIN_LIBRARIES}   )
      ADD_EXECUTABLE(testReservoirWithInflowsSDDP ${SOURCE_FUNC_TEST}/testReservoirWithInflowsSDDP.cpp)
      TARGET_LINK_LIBRARIES(testReservoirWithInflowsSDDP  ${STOPT_LIB} ${GENERS_LIB}   ${MPI_CXX_LIBRARIES} ${BOOST_LIBS}  ${PTHREAD_LIBRARY}  ${COIN_LIBRARIES}  )
      ADD_EXECUTABLE(testDemandSDDP ${SOURCE_FUNC_TEST}/testDemandSDDP.cpp)
      TARGET_LINK_LIBRARIES(testDemandSDDP  ${STOPT_LIB} ${GENERS_LIB}   ${MPI_CXX_LIBRARIES}   ${BOOST_LIBS}  ${PTHREAD_LIBRARY}   ${COIN_LIBRARIES})
      ADD_EXECUTABLE(testStorageWithInflowsSDDP ${SOURCE_FUNC_TEST}/testStorageWithInflowsSDDP.cpp)
      TARGET_LINK_LIBRARIES(testStorageWithInflowsSDDP  ${STOPT_LIB} ${GENERS_LIB}   ${MPI_CXX_LIBRARIES} ${BOOST_LIBS}  ${PTHREAD_LIBRARY}  ${COIN_LIBRARIES}      )
      ADD_EXECUTABLE(testStorageWithInflowsAndMarketSDDP ${SOURCE_FUNC_TEST}/testStorageWithInflowsAndMarketSDDP.cpp)
      TARGET_LINK_LIBRARIES(testStorageWithInflowsAndMarketSDDP  ${STOPT_LIB} ${GENERS_LIB}   ${MPI_CXX_LIBRARIES} ${BOOST_LIBS}  ${PTHREAD_LIBRARY}   ${COIN_LIBRARIES}    )
      SET(PROCS 1)
      ADD_TEST(NAME MyTestDemandSDDPMpi  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testDemandSDDP ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestGasStorageSDDPMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageSDDP ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestReservoirWithInflowsSDDPMpi  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testReservoirWithInflowsSDDP ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestStorageWithInflowsSDDPMpi  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testStorageWithInflowsSDDP ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestStorageWithInflowsAndMarketSDDPMpi  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testStorageWithInflowsAndMarketSDDP ${MPIEXEC_POSTFLAGS})
      SET(PROCS 2)
      ADD_TEST(NAME MyTestDemandSDDPMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testDemandSDDP ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestGasStorageSDDPMpi2core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageSDDP ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestGasStorageSDDPTreeMpi2core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageSDDPTree ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestReservoirWithInflowsSDDPMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testReservoirWithInflowsSDDP ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestStorageWithInflowsSDDPMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testStorageWithInflowsSDDP ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestStorageWithInflowsAndMarketSDDPMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testStorageWithInflowsAndMarketSDDP ${MPIEXEC_POSTFLAGS})
    ELSE(BUILD_MPI)
      ADD_EXECUTABLE(testGasStorageSDDP ${SOURCE_FUNC_TEST}/testGasStorageSDDP.cpp)
      TARGET_LINK_LIBRARIES(testGasStorageSDDP  ${STOPT_LIB}  ${STOPTTEST_LIB}  ${GENERS_LIB}      ${BOOST_LIBS}  ${PTHREAD_LIBRARY}  ${COIN_LIBRARIES})
      ADD_EXECUTABLE(testReservoirWithInflowsSDDP ${SOURCE_FUNC_TEST}/testReservoirWithInflowsSDDP.cpp)
      TARGET_LINK_LIBRARIES(testReservoirWithInflowsSDDP  ${STOPT_LIB} ${GENERS_LIB}   ${BOOST_LIBS}  ${PTHREAD_LIBRARY}  ${COIN_LIBRARIES}   )
      ADD_EXECUTABLE(testDemandSDDP ${SOURCE_FUNC_TEST}/testDemandSDDP.cpp)
      TARGET_LINK_LIBRARIES(testDemandSDDP  ${STOPT_LIB} ${GENERS_LIB} ${BOOST_LIBS}     ${PTHREAD_LIBRARY}   ${COIN_LIBRARIES})
      ADD_EXECUTABLE(testStorageWithInflowsSDDP ${SOURCE_FUNC_TEST}/testStorageWithInflowsSDDP.cpp)
      TARGET_LINK_LIBRARIES(testStorageWithInflowsSDDP  ${STOPT_LIB} ${GENERS_LIB} ${BOOST_LIBS}  ${PTHREAD_LIBRARY}  ${COIN_LIBRARIES}     )
      ADD_EXECUTABLE(testStorageWithInflowsAndMarketSDDP ${SOURCE_FUNC_TEST}/testStorageWithInflowsAndMarketSDDP.cpp)
      TARGET_LINK_LIBRARIES(testStorageWithInflowsAndMarketSDDP  ${STOPT_LIB} ${GENERS_LIB} ${BOOST_LIBS}  ${PTHREAD_LIBRARY}   ${COIN_LIBRARIES}     )
      ADD_TEST(NAME MyTestDemandSDDP  COMMAND ./bin${SUFF}/testDemandSDDP )
      ADD_TEST(NAME MyTestGasStorageSDDP COMMAND ./bin${SUFF}/testGasStorageSDDP)
      ADD_TEST(NAME MyTestReservoirWithInflowsSDDP  COMMAND  ./bin${SUFF}/testReservoirWithInflowsSDDP)
      ADD_TEST(NAME MyTestStorageWithInflowsSDDP  COMMAND  ./bin${SUFF}/testStorageWithInflowsSDDP)
      ADD_TEST(NAME MyTestStorageWithInflowsAndMarketSDDP COMMAND ./bin${SUFF}/testStorageWithInflowsAndMarketSDDP)

    ENDIF(BUILD_MPI)
  ENDIF(BUILD_SDDP)

  IF(BUILD_BRANCHING)
      SET(SOURCE_UNIT_TEST_BRANCHING  ${SOURCE_UNIT_TEST}/branching)
      ADD_EXECUTABLE(testBSCVAEuler ${SOURCE_UNIT_TEST_BRANCHING}/testBSCVAEuler.cpp)
      IF (WIN32)
        SET_TARGET_PROPERTIES(testBSCVAEuler PROPERTIES COMPILE_FLAGS "/Za")
      ENDIF(WIN32)
      TARGET_LINK_LIBRARIES(testBSCVAEuler   ${BOOST_LIBS}     ${MPI_CXX_LIBRARIES} ${TRNG4_LIBRARY})
      ADD_EXECUTABLE(testBSCVAExact ${SOURCE_UNIT_TEST_BRANCHING}/testBSCVAExact.cpp)
      IF (WIN32)
        SET_TARGET_PROPERTIES(testBSCVAExact PROPERTIES COMPILE_FLAGS "/Za")
      ENDIF(WIN32)
      TARGET_LINK_LIBRARIES(testBSCVAExact   ${BOOST_LIBS}      ${MPI_CXX_LIBRARIES} ${TRNG4_LIBRARY})
      ADD_EXECUTABLE(testHJBEuler ${SOURCE_UNIT_TEST_BRANCHING}/testHJBEuler.cpp)
      IF (WIN32)
        SET_TARGET_PROPERTIES(testHJBEuler PROPERTIES COMPILE_FLAGS "/Za")
      ENDIF(WIN32)
      TARGET_LINK_LIBRARIES(testHJBEuler   ${BOOST_LIBS}      ${MPI_CXX_LIBRARIES} ${TRNG4_LIBRARY})
      ADD_EXECUTABLE(testHJBExact ${SOURCE_UNIT_TEST_BRANCHING}/testHJBExact.cpp)
      IF (WIN32)
        SET_TARGET_PROPERTIES(testHJBExact PROPERTIES COMPILE_FLAGS "/Za")
      ENDIF(WIN32)
      TARGET_LINK_LIBRARIES(testHJBExact   ${BOOST_LIBS}      ${MPI_CXX_LIBRARIES} ${TRNG4_LIBRARY})
      ADD_EXECUTABLE(testHJBConst ${SOURCE_UNIT_TEST_BRANCHING}/testHJBConst.cpp)
      IF (WIN32)
        SET_TARGET_PROPERTIES(testHJBConst PROPERTIES COMPILE_FLAGS "/Za")
      ENDIF(WIN32)
      TARGET_LINK_LIBRARIES(testHJBConst   ${BOOST_LIBS}      ${MPI_CXX_LIBRARIES} ${TRNG4_LIBRARY})
      ADD_EXECUTABLE(testPortfolioEuler ${SOURCE_UNIT_TEST_BRANCHING}/testPortfolioEuler.cpp)
      IF (WIN32)
        SET_TARGET_PROPERTIES( testPortfolioEuler PROPERTIES COMPILE_FLAGS "/Za")
      ENDIF(WIN32)
      TARGET_LINK_LIBRARIES(testPortfolioEuler  ${BOOST_LIBS}      ${MPI_CXX_LIBRARIES} ${TRNG4_LIBRARY})
      ADD_EXECUTABLE(testPortfolioExact ${SOURCE_UNIT_TEST_BRANCHING}/testPortfolioExact.cpp)
      IF (WIN32)
        SET_TARGET_PROPERTIES( testPortfolioExact PROPERTIES COMPILE_FLAGS "/Za")
      ENDIF(WIN32)
      TARGET_LINK_LIBRARIES(testPortfolioExact   ${BOOST_LIBS}      ${MPI_CXX_LIBRARIES} ${TRNG4_LIBRARY})
      ADD_EXECUTABLE(testUD2UToy ${SOURCE_UNIT_TEST_BRANCHING}/testUD2UToy.cpp)
      IF (WIN32)
        SET_TARGET_PROPERTIES(testUD2UToy  PROPERTIES COMPILE_FLAGS "/Za")
      ENDIF(WIN32)
      TARGET_LINK_LIBRARIES(testUD2UToy   ${BOOST_LIBS}      ${MPI_CXX_LIBRARIES} ${TRNG4_LIBRARY})
      SET(PROCS 2)
      ADD_TEST(NAME MyTestSwitchingBSCVAEulerMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testBSCVAEuler ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestSwitchingBSCVAExactMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testBSCVAExact ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestSwitchingHJBEulerMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testHJBEuler ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestSwitchingHJBExactMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testHJBExact ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestSwitchingHJBConstMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testHJBConst ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestSwitchingPortfolioEulerMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testPortfolioEuler ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestSwitchingPortfolioExactMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testPortfolioExact ${MPIEXEC_POSTFLAGS})
      ADD_TEST(NAME MyTestSwitchingUD2UToyMpi2core  COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testUD2UToy ${MPIEXEC_POSTFLAGS})   
    ENDIF(BUILD_BRANCHING)

    IF (BUILD_DPCUTS)
      FIND_PACKAGE(COIN)
      IF(NOT COIN_FOUND)
        MESSAGE(STATUS "COIN CLP OR OSI NOT FOUND")
      ENDIF(NOT COIN_FOUND)
      INCLUDE_DIRECTORIES(SYSTEM ${COIN_INCLUDE_DIRS})
      ADD_EXECUTABLE(testGasStorageCut  ${SOURCE_FUNC_TEST}/testGasStorageCut.cpp )
      TARGET_LINK_LIBRARIES(testGasStorageCut  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}    ${COIN_LIBRARIES})
      ADD_TEST(NAME MyTestForGasStorageCut COMMAND testGasStorageCut)
      INCLUDE_DIRECTORIES(SYSTEM ${COIN_INCLUDE_DIRS})
      ADD_EXECUTABLE(testGasStorageCutGridAdapt1D  ${SOURCE_FUNC_TEST}/testGasStorageCutGridAdapt1D.cpp )
      TARGET_LINK_LIBRARIES(testGasStorageCutGridAdapt1D  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}    ${COIN_LIBRARIES})
      ADD_TEST(NAME MyTestForGasStorageCutGridAdapt1D COMMAND testGasStorageCutGridAdapt1D)
      ADD_EXECUTABLE(testGasStorageCutGridAdapt2D  ${SOURCE_FUNC_TEST}/testGasStorageCutGridAdapt2D.cpp )
      TARGET_LINK_LIBRARIES(testGasStorageCutGridAdapt2D  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}    ${COIN_LIBRARIES})
      ADD_TEST(NAME MyTestForGasStorageCutGridAdapt2D COMMAND testGasStorageCutGridAdapt2D)
      ADD_EXECUTABLE(testGasStorageTreeCut  ${SOURCE_FUNC_TEST}/testGasStorageTreeCut.cpp )
      TARGET_LINK_LIBRARIES(testGasStorageTreeCut  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}    ${COIN_LIBRARIES})
      ADD_TEST(NAME MyTestForGasStorageTreeCut COMMAND testGasStorageTreeCut)
       IF(BUILD_MPI)
        ADD_EXECUTABLE(testGasStorageCutMpi  ${SOURCE_FUNC_TEST}/testGasStorageCutMpi.cpp )
        TARGET_LINK_LIBRARIES(testGasStorageCutMpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}    ${BOOST_LIBS}    ${COIN_LIBRARIES})
        SET(PROCS 1)
        ADD_TEST(NAME MyTestForGasStorageCutMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageCutMpi  ${MPIEXEC_POSTFLAGS}) 
        SET(PROCS 4)
        ADD_TEST(NAME MyTestForGasStorageCutMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageCutMpi  ${MPIEXEC_POSTFLAGS})
        ADD_EXECUTABLE(testGasStorageTreeCutMpi  ${SOURCE_FUNC_TEST}/testGasStorageTreeCutMpi.cpp )
        TARGET_LINK_LIBRARIES(testGasStorageTreeCutMpi  ${STOPT_LIB}  ${STOPTTEST_LIB}   ${GENERS_LIB}  ${BOOST_LIBS}    ${COIN_LIBRARIES})
        SET(PROCS 1)
        ADD_TEST(NAME MyTestForGasStorageTreeCutMpi COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageTreeCutMpi  ${MPIEXEC_POSTFLAGS}) 
        SET(PROCS 4)
        ADD_TEST(NAME MyTestForGasStorageTreeCutMpi4core COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${PROCS} ${MPIEXEC_PREFLAGS} ./bin${SUFF}/testGasStorageTreeCutMpi  ${MPIEXEC_POSTFLAGS})
        
      ELSE(BUILD_MPI)
      ENDIF(BUILD_MPI)
    ENDIF(BUILD_DPCUTS)
 
  IF (BUILD_PYTHON)
    # compile test in python
    SET(SOURCE_PYTHON ${PROJECT_SOURCE_DIR}/test/c++/python)
    SET(STOPTTEST_PY_SOURCES     ${SOURCE_PYTHON}/Pybind11StOptTest.cpp ${SOURCE_PYTHON}/Pybind11Simulators.cpp ${SOURCE_PYTHON}/Pybind11Optimizers.cpp  ${SOURCE_PYTHON}/Pybind11Utils.cpp)
    IF (BUILD_SDDP)
      SET(STOPTTEST_PY_SOURCES ${STOPTTEST_PY_SOURCES}  ${SOURCE_PYTHON}/Pybind11SDDPUnitTest.cpp  ${SOURCE_PYTHON}/Pybind11SDDPOptimizers.cpp ${SOURCE_PYTHON}/Pybind11SDDPSimulators.cpp)
    ENDIF()
  
    PYBIND11_ADD_MODULE(pystopttest MODULE ${STOPTTEST_PY_SOURCES})
    TARGET_COMPILE_FEATURES(pystopttest PRIVATE cxx_std_17)
    TARGET_INCLUDE_DIRECTORIES(pystopttest PRIVATE ${Python_NumPy_INCLUDE_DIRS}  ${CMAKE_SOURCE_DIR}/StOpt)
    
    # Keep keyword signature; link the same way you link PyStOpt
    TARGET_LINK_LIBRARIES(pystopttest PRIVATE
      pybind11::module Python::Module
      ${STOPT_LIB} ${GENERS_LIB} ${BOOST_LIBS} ${STOPTTEST_LIB} ${COIN_LIBRARIES}
      $<$<BOOL:${OpenMP_CXX_FOUND}>:OpenMP::OpenMP_CXX>
      $<$<BOOL:${STOPT_ENABLE_MPI}>:MPI::MPI_CXX>
      )

    # Give the Linux loader the same RPATH policy as PyStOpt
    if (UNIX AND NOT WIN32 AND NOT APPLE)
      SET_TARGET_PROPERTIES(pystopttest PROPERTIES
        BUILD_RPATH "\$ORIGIN"
        INSTALL_RPATH "\$ORIGIN"
        )
    endif()

    # Install pystopttest next to PyStOpt and the shared libs (wheel-friendly)
    # Cross-platform: .so (Linux) / .pyd (Windows)
    INSTALL(TARGETS pystopttest
      ARCHIVE DESTINATION ${_PY_DEST}
      LIBRARY DESTINATION ${_PY_DEST}
      RUNTIME DESTINATION ${_PY_DEST}
      )


  ENDIF(BUILD_PYTHON)
ENDIF(BUILD_TEST)

# if AutoDiff
IF (BUILD_TEST_AUTODIFF)
  SET(SOURCE_TEST_AD  ${PROJECT_SOURCE_DIR}/test/c++/tools/utils/Tunnel.cpp ${PROJECT_SOURCE_DIR}/test/c++/tools/utils/Capa.cpp ${PROJECT_SOURCE_DIR}/test/c++/tools/dp/DynamicProgrammingStorage.cpp)
  IF (BUILD_TEST_ADEPT)
    SET(SOURCE_TEST_AD ${SOURCE_TEST_AD}  ${PROJECT_SOURCE_DIR}/test/c++/tools/autodiff/calculateSensiUsingControlAdept.cpp)
    # ADEPT
    SET(ADEPT_ROOT "" CACHE PATH "Path to Adept installation")

    MESSAGE(STATUS "ADEPT_ROOT = ${ADEPT_ROOT}")

    MESSAGE("ADD ${ADEPT_ROOT}")
    FIND_LIBRARY(ADEPT_LIBRARY
      NAMES adept
      HINTS ${ADEPT_ROOT}/lib ${ADEPT_ROOT}/lib64 /usr/local/lib /usr/lib
      )
    FIND_PATH(ADEPT_INCLUDE_DIR
      NAMES adept.h
      HINTS ${ADEPT_ROOT}/include /usr/local/include /usr/include
      )
    
    if(NOT ADEPT_INCLUDE_DIR OR NOT ADEPT_LIBRARY)
      MESSAGE(FATAL_ERROR "Adept not found. Set -DADEPT_ROOT=/path/to/prefix or use option B (ExternalProject).")
    endif()
    INCLUDE_DIRECTORIES(SYSTEM ${ADEPT_INCLUDE_DIR})

    ADD_LIBRARY(Adept::Adept INTERFACE IMPORTED)

    TARGET_INCLUDE_DIRECTORIES(Adept::Adept INTERFACE ${ADEPT_INCLUDE_DIR})

    TARGET_LINK_LIBRARIES(Adept::Adept INTERFACE ${ADEPT_LIBRARY})
    
  ENDIF(BUILD_TEST_ADEPT)
  
  IF (BUILD_TEST_STANMATH)
    SET(SOURCE_TEST_AD ${SOURCE_TEST_AD}  ${PROJECT_SOURCE_DIR}/test/c++/tools/autodiff/calculateSensiUsingControlStan.cpp)
    # TBB
    FIND_PACKAGE(TBB REQUIRED MODULE)
    MESSAGE(STATUS "TBB_FOUND        = ${TBB_FOUND}")
    MESSAGE(STATUS "TBB_INCLUDE_DIR  = ${TBB_INCLUDE_DIR}")
    MESSAGE(STATUS "TBB_INCLUDE_DIRS = ${TBB_INCLUDE_DIRS}")
    MESSAGE(STATUS "TBB_LIBRARY      = ${TBB_LIBRARY}")
    MESSAGE(STATUS "TBB_LIBRARIES    = ${TBB_LIBRARIES}")
    
    # ========
    # sundials
    # ========
    FIND_PACKAGE(SUNDIALS REQUIRED)
    INCLUDE_DIRECTORIES(SYSTEM ${SUNDIALS_INCLUDE_DIR})
    
    
    # =========
    # STAN MATH 
    # =========
    FIND_PACKAGE(StanMath QUIET CONFIG)
    
    if(STANMATH_FOUND)
      message(STATUS "Found StanMath via find_package")
    else()
      message(STATUS "StanMathConfig.cmake not found, using STAN_MATH_ROOT fallback")
      
      set(STAN_MATH_ROOT "" CACHE PATH "Path to stan-math root directory")
      
      if(NOT STAN_MATH_ROOT)
        MESSAGE(FATAL_ERROR
          "StanMath was not found. Please set STAN_MATH_ROOT or CMAKE_PREFIX_PATH.\n"
          "Example:\n"
          "  cmake -DSTAN_MATH_ROOT=/home/c97830/LOGICIELS/stan-math .."
          )
      endif()
      
      FIND_PATH(STAN_MATH_INCLUDE_DIR
        NAMES stan/math.hpp
        PATHS
        ${STAN_MATH_ROOT}
        ${STAN_MATH_ROOT}/include
        NO_DEFAULT_PATH
        )

      if(NOT STAN_MATH_INCLUDE_DIR)
        MESSAGE(FATAL_ERROR
          "Could not find stan/math.hpp under STAN_MATH_ROOT=${STAN_MATH_ROOT}"
          )
      endif()
      
      ADD_LIBRARY(StanMath::StanMath INTERFACE IMPORTED)
      
      TARGET_INCLUDE_DIRECTORIES(StanMath::StanMath
        INTERFACE
        ${STAN_MATH_INCLUDE_DIR}
        )
    endif()
    INCLUDE_DIRECTORIES(SYSTEM ${STAN_MATH_INCLUDE_DIR})
    
    # ---- Options Stan ----
    ADD_DEFINITIONS(
      -DSTAN_NO_RANGE_CHECKS
      -DSTAN_THREADS
      -D_REENTRANT
      )
    

    ADD_EXECUTABLE(testAutoDiff  ${PROJECT_SOURCE_DIR}/test/c++/functional/testStorageAutoDiff.cpp  ${SOURCE_TEST_AD})
    
    TARGET_INCLUDE_DIRECTORIES(testAutoDiff PRIVATE  ${SUNDIALS_INCLUDE_DIR} ${ADEPT_INCLUDE_DIR})
    TARGET_LINK_LIBRARIES(testAutoDiff  PRIVATE   ${STOPT_LIB}   ${GENERS_LIB}   ${BOOST_LIBS}  ${BZIP2_LIBRARIES}  ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES}  ${PTHREAD_LIBRARY}  TBB::tbb ${SUNDIALS_LIBRARIES}  Adept::Adept)
  ELSE(BUILD_TEST_STANMATH)
    ADD_EXECUTABLE(testAutoDiff  ${PROJECT_SOURCE_DIR}/test/c++/testStorageAutoDiff.cpp  ${SOURCE_TEST_AD})
    TARGET_INCLUDE_DIRECTORIES(testAutoDiff PRIVATE ${ADEPT_INCLUDE_DIR}) 
    TARGET_LINK_LIBRARIES(testAutoDiff  PRIVATE  ${STOPT_LIB}    ${GENERS_LIB}  ${BOOST_LIBS}  ${BZIP2_LIBRARIES}  ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES}   ${PTHREAD_LIBRARY}  Adept::Adept)
  ENDIF(BUILD_TEST_STANMATH)
  IF (OPENMP_CXX_FOUND)
    TARGET_LINK_LIBRARIES(testAutoDiff PRIVATE OpenMP::OpenMP_CXX)
  ENDIF()   
  ADD_TEST(NAME MyTestAutoDiff  COMMAND ./bin${SUFF}/testAutoDiff)
 ENDIF(BUILD_TEST_AUTODIFF)

# ------------------------------------------------------------------------------
# Windows-only: bundle vcpkg runtime DLLs next to the Python module
# (No effect on Linux.)
# Requires configuring with the vcpkg toolchain, e.g.:
#   -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
# ------------------------------------------------------------------------------
IF (WIN32 AND STOPT_PIP_LAYOUT)
  IF (DEFINED VCPKG_INSTALLED_DIR AND DEFINED VCPKG_TARGET_TRIPLET)
    MESSAGE(STATUS "vcpkg triplet: ${VCPKG_TARGET_TRIPLET}")
    FILE(GLOB _VCPKG_DLLS
      "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/*.dll"
    )
    IF (_VCPKG_DLLS)
      INSTALL(FILES ${_VCPKG_DLLS} DESTINATION ${_PY_DEST})
    ELSE()
      MESSAGE(WARNING "No vcpkg runtime DLLs found under bin/. "
                      "Ensure dependencies are built as dynamic or needed.")
    ENDIF()
  ELSE()
    MESSAGE(STATUS "Skipping vcpkg DLL bundling: vcpkg toolchain variables not set.")
  ENDIF()
ENDIF()



IF(BUILD_SYSTEM_INSTALL)
    INSTALL(TARGETS StOpt COMPONENT libraries DESTINATION "lib")
    INSTALL(TARGETS geners COMPONENT libraries DESTINATION "lib")
    INSTALL(DIRECTORY StOpt DESTINATION "include" FILES_MATCHING PATTERN "*.h")
    INSTALL(DIRECTORY geners DESTINATION "include" FILES_MATCHING PATTERN "*.hh")
ENDIF()
  


# CPACK
IF (WIN32 AND BUILD_CPACK )
  INCLUDE(InstallRequiredSystemLibraries)
  MESSAGE("RUNTIME" ${CMAKE_INSTALL_SYSTEM})
  INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} COMPONENT libraries DESTINATION "lib")
  IF(MSVC_VERSION EQUAL 1800)
    INSTALL(FILES "${MSVC12_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC120.OPENMP/vcomp120.dll"  COMPONENT Libraries DESTINATION "lib" )
  ENDIF()
  IF (BUILD_MPI)
    STRING(REGEX REPLACE "\\.lib" ".dll"  BOOST_MPI_DLL ${Boost_MPI_LIBRARY_RELEASE})
    INSTALL(FILES ${BOOST_MPI_DLL} COMPONENT Libraries DESTINATION "lib" )
    MESSAGE("CMAKE_LIBRARY_PATH" , ${CMAKE_SYSTEM_LIBRARY_PATH})
    STRING(REGEX REPLACE "\\.lib" ".dll"  MPI_DLL ${MPI_CXX_LIBRARIES})
    INSTALL(FILES ${MPI_DLL}  COMPONENT Libraries DESTINATION "lib" )
  ENDIF(BUILD_MPI)
  STRING(REGEX REPLACE "\\.lib" ".dll"  BOOST_SERIALIZATION_DLL ${Boost_SERIALIZATION_LIBRARY_RELEASE})
  INSTALL(FILES ${BOOST_SERIALIZATION_DLL} COMPONENT Libraries DESTINATION "lib" )
  FIND_PATH( ZLIB_DLL_DIR
    zlib.dll
    )
  IF( ZLIB_DLL_DIR)
    MESSAGE( "ZLIB DIRECTORY DLL FOUND")
  ELSE()
    MESSAGE( FATAL_ERROR "ZLIB DIRECTORY DLL NOT FOUND" )
  ENDIF()
  FILE(GLOB ZLIB_DLL ${ZLIB_DLL_DIR}/zlib.dll)
  INSTALL(FILES ${ZLIB_DLL} COMPONENT Libraries DESTINATION "lib" )
  FIND_PATH( BZIP2_DLL_DIR
    libbz2.dll
    )
  IF( BZIP2_DLL_DIR)
    MESSAGE( "BZIP2 DIRECTORY DLL FOUND")
  ELSE()
    MESSAGE( FATAL_ERROR "BZIP2 DIRECTORY DLL NOT FOUND" )
  ENDIF()
  FILE(GLOB BZIP2_DLL ${BZIP2_DLL_DIR}/libbz2.dll)
  INSTALL(FILES ${BZIP2_DLL} COMPONENT Libraries DESTINATION "lib" )
ENDIF(WIN32 AND BUILD_CPACK )

SET(CPACK_MONOLITHIC_INSTALL 1)
SET(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1)
SET(CPACK_RPM_COMPONENT_INSTALL ON)
SET(CPACK_DEB_COMPONENT_INSTALL ON)
SET(CPACK_PACKAGE_NAME "StOpt")
SET(CPACK_PACKAGE_VENDOR "FiME")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "StOpt library")
SET(CPACK_PACKAGE_VERSION "${STOPT_MAJOR_VERSION}.${STOPT_MINOR_VERSION}")
SET(CPACK_PACKAGE_VERSION_MAJOR "${STOPT_MAJOR_VERSION}")
SET(CPACK_PACKAGE_VERSION_MINOR "${STOPT_MINOR_VERSION}")
SET(CPACK_PACKAGE_CONTACT "Xavier Warin : Xavier.Warin@edf.fr")
IF(BUILD_PYTHON)
  IF(BUILD_MPI)
    SET(CPACK_PACKAGE_NAME "StOptPythonWithMpi${PYTHON_VERSION_STRING}${CMAKE_SYSTEM}")
  ELSE()
    SET(CPACK_PACKAGE_NAME "StOptPython${PYTHON_VERSION_STRING}${CMAKE_SYSTEM}")
  ENDIF(BUILD_MPI)
ELSE()
  IF(BUILD_MPI)
    SET(CPACK_PACKAGE_NAME "StOptWithMpi${CMAKE_SYSTEM}")
  ELSE()
    SET(CPACK_PACKAGE_NAME "StOpt${CMAKE_SYSTEM}")
  ENDIF(BUILD_MPI)
ENDIF(BUILD_PYTHON)

# This must always be last!
INCLUDE(CPack)



