project(OMSimulatorLib)

if (ASAN)
  set(CMAKE_BUILD_TYPE Debug)
ENDIF()
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib/${HOST_SHORT}:$ORIGIN/")

IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.1)
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-local-addr")
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-type")
  if (ASAN)
    message(STATUS "AddressSanitizer enabled")
    add_compile_options("-fsanitize=address" "-fno-omit-frame-pointer")
    link_libraries("-fsanitize=address")
  ENDIF()
ENDIF()

# Export all symbols from the DLL on Windows
IF(WIN32 AND MSVC)
  set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
  add_definitions(-DBOOST_ALL_DYN_LINK)
ENDIF()

IF(OMTLM)
  set(OMTLM_SOURCES "TLM/")
  set(TLM_STRING "")
ELSE()
  set(OMTLM_SOURCES "DummyTLM/")
  set(TLM_STRING "-notlm")
ENDIF()

list(APPEND OMSIMULATORLIB_SOURCES BusConnector.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Clock.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Clocks.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Component.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ComponentFMUCS.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ComponentFMUME.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ComponentTable.cpp)
list(APPEND OMSIMULATORLIB_SOURCES CompositeModel.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ComRef.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Connection.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Connector.cpp)
list(APPEND OMSIMULATORLIB_SOURCES CSVReader.cpp)
list(APPEND OMSIMULATORLIB_SOURCES CSVWriter.cpp)
list(APPEND OMSIMULATORLIB_SOURCES DirectedGraph.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Element.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Flags.cpp)
list(APPEND OMSIMULATORLIB_SOURCES FMICompositeModel.cpp)
list(APPEND OMSIMULATORLIB_SOURCES FMISubModel.cpp)
list(APPEND OMSIMULATORLIB_SOURCES FMUInfo.cpp)
list(APPEND OMSIMULATORLIB_SOURCES FMUWrapper.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Identifier.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Logging.cpp)
list(APPEND OMSIMULATORLIB_SOURCES MatReader.cpp)
list(APPEND OMSIMULATORLIB_SOURCES MatVer4.cpp)
list(APPEND OMSIMULATORLIB_SOURCES MATWriter.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Model.cpp)
list(APPEND OMSIMULATORLIB_SOURCES OMSBoost.cpp)
list(APPEND OMSIMULATORLIB_SOURCES OMSimulator.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ResultReader.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ResultWriter.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Scope.cpp)
list(APPEND OMSIMULATORLIB_SOURCES SignalRef.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Solver.cpp)
list(APPEND OMSIMULATORLIB_SOURCES StepSizeConfiguration.cpp)
list(APPEND OMSIMULATORLIB_SOURCES System.cpp)
list(APPEND OMSIMULATORLIB_SOURCES SystemSC.cpp)
list(APPEND OMSIMULATORLIB_SOURCES SystemWC.cpp)
list(APPEND OMSIMULATORLIB_SOURCES Table.cpp)
IF(OMTLM)
  list(APPEND OMSIMULATORLIB_SOURCES ${OMTLM_SOURCES}/ExternalModel.cpp)
  list(APPEND OMSIMULATORLIB_SOURCES ${OMTLM_SOURCES}/SystemTLM.cpp)
  list(APPEND OMSIMULATORLIB_SOURCES ${OMTLM_SOURCES}/TLMBusConnector.cpp)
  list(APPEND OMSIMULATORLIB_SOURCES ${OMTLM_SOURCES}/TLMCompositeModel.cpp)
  list(APPEND OMSIMULATORLIB_SOURCES ${OMTLM_SOURCES}/TLMConnection.cpp)
  list(APPEND OMSIMULATORLIB_SOURCES ${OMTLM_SOURCES}/TLMInterface.cpp)
ENDIF()
list(APPEND OMSIMULATORLIB_SOURCES Variable.cpp)

list(APPEND OMSIMULATORLIB_SOURCES ssd/ConnectionGeometry.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ssd/ConnectorGeometry.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ssd/ElementGeometry.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ssd/SystemGeometry.cpp)
list(APPEND OMSIMULATORLIB_SOURCES ssd/Tags.cpp)

IF(OMTLM)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/Bstring.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/coordTransform.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/double3.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/double33.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/double33s.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/dsyevc3.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/dsyevq3.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/dsyevv3.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/dsytrd3.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/ErrorLog.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/3rdParty/misc/src/tostr.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Communication/TLMClientComm.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Communication/TLMCommUtil.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Interfaces/TLMInterface.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Interfaces/TLMInterface1D.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Interfaces/TLMInterface3D.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Interfaces/TLMInterfaceSignal.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Interfaces/TLMInterfaceSignalInput.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Interfaces/TLMInterfaceSignalOutput.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Logging/TLMErrorLog.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Parameters/ComponentParameter.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Plugin/PluginImplementer.cc)
  list(APPEND OMSIMULATORLIB_SOURCES ../../OMTLMSimulator/common/Plugin/TLMPlugin.cc)
ENDIF(OMTLM)

configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/Version.cpp" @ONLY)
list(APPEND OMSIMULATORLIB_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/Version.cpp")

include_directories(".")
include_directories("../../3rdParty/RegEx/")
include_directories(${FMILibrary_INCLUDEDIR})
include_directories(${CVODELibrary_INCLUDEDIR})
include_directories(${KINSOLLibrary_INCLUDEDIR})
include_directories(${PUGIXML_INCLUDEDIR})
include_directories(${Boost_INCLUDE_DIRS})
IF(OMTLM)
  include_directories(${OMTLMSIMULATORLIB_INCLUDEDIR})
  include_directories(${OMTLMSIMULATOR_INCLUDEDIR})
  include_directories(${OMTLMSIMULATOR_3RDPARTY_INCLUDEDIR})
ENDIF(OMTLM)
include_directories(${OMTLM_SOURCES})
include_directories(${CTPL_INCLUDEDIR})
include_directories(${MINIZIP_INCLUDEDIR})

link_directories(${FMILibrary_LIBRARYDIR})
link_directories(${CVODELibrary_LIBRARYDIR})
link_directories(${KINSOLLibrary_LIBRARYDIR})
link_directories(${Boost_LIBRARY_DIRS})
link_directories(${MINIZIP_LIBRARYDIR})
IF(OMTLM)
  link_directories(${OMTLMSIMULATORLIB_LIBRARYDIR})
ENDIF()

IF(Ceres_FOUND AND OMSYSIDENT)
  set(OMSYSIDENT_OPTION $<TARGET_OBJECTS:OMSysIdentObj>)
  set(CERES_OPTION ${CERES_LIBRARIES})
  add_definitions(-DWITH_OMSYSIDENT)
ENDIF()

# Shared library version
add_library(OMSimulatorLib_shared SHARED ${OMSYSIDENT_OPTION} ${OMSIMULATORLIB_SOURCES})
set_target_properties(OMSimulatorLib_shared PROPERTIES OUTPUT_NAME OMSimulator)
IF(WIN32 AND MSVC)
  target_link_libraries(OMSimulatorLib_shared fmilib sundials_kinsol sundials_cvode sundials_nvecserial minizip ${Boost_LIBRARIES} ${CERES_OPTION} ${OMTLM_LINKFLAGS})
ELSEIF(WIN32 AND MINGW)
  target_link_libraries(OMSimulatorLib_shared fmilib shlwapi sundials_kinsol sundials_cvode sundials_nvecserial minizip ${Boost_LIBRARIES} ${CERES_OPTION} ${OMTLM_LINKFLAGS})
ELSE()
  target_link_libraries(OMSimulatorLib_shared fmilib sundials_kinsol sundials_cvode sundials_nvecserial minizip ${Boost_LIBRARIES} ${CERES_OPTION} ${OMTLM_LINKFLAGS})
ENDIF()

install(TARGETS OMSimulatorLib_shared DESTINATION lib/${HOST_SHORT})
IF(WIN32)
  install(TARGETS OMSimulatorLib_shared DESTINATION bin)
ENDIF()

# Static library version
add_library(OMSimulatorLib STATIC ${OMSIMULATORLIB_SOURCES})
set_target_properties(OMSimulatorLib PROPERTIES OUTPUT_NAME OMSimulator)
set_target_properties(OMSimulatorLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
install(TARGETS OMSimulatorLib DESTINATION lib/${HOST_SHORT})
install(FILES OMSimulator.h Types.h DESTINATION include)

IF(APPLE)
  get_target_property(LN_OMSLIB OMSimulatorLib_shared OUTPUT_NAME)
  install(CODE "execute_process(COMMAND install_name_tool -id \"@rpath/lib${LN_OMSLIB}.dylib\" \"${CMAKE_INSTALL_PREFIX}/lib/${HOST_SHORT}/lib${LN_OMSLIB}.dylib\")")
ENDIF()
