cmake_minimum_required(VERSION 3.16)

project(kdl_wasm_wrapper LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(KDL_SOURCE_DIR "" CACHE PATH "Path to the Orocos KDL source tree")
if(KDL_SOURCE_DIR AND NOT EXISTS "${KDL_SOURCE_DIR}")
  message(FATAL_ERROR "KDL_SOURCE_DIR does not exist: ${KDL_SOURCE_DIR}")
endif()

set(EIGEN3_INCLUDE_DIR "" CACHE PATH "Path to the Eigen3 include directory")
if(KDL_SOURCE_DIR AND NOT EIGEN3_INCLUDE_DIR)
  find_path(EIGEN3_INCLUDE_DIR Eigen/Core PATH_SUFFIXES eigen3)
endif()
if(KDL_SOURCE_DIR AND NOT EIGEN3_INCLUDE_DIR AND EXISTS "/usr/include/eigen3/Eigen/Core")
  set(EIGEN3_INCLUDE_DIR "/usr/include/eigen3" CACHE PATH "Path to the Eigen3 include directory" FORCE)
endif()
if(KDL_SOURCE_DIR AND NOT EIGEN3_INCLUDE_DIR)
  message(FATAL_ERROR "Eigen3 include directory was not found")
endif()

set(KDL_WASM_SOURCES
  bindings/kdl_c_api.cpp
)

if(KDL_SOURCE_DIR)
  list(APPEND KDL_WASM_SOURCES
    "${KDL_SOURCE_DIR}/src/chain.cpp"
    "${KDL_SOURCE_DIR}/src/chainfksolverpos_recursive.cpp"
    "${KDL_SOURCE_DIR}/src/chainiksolverpos_lma.cpp"
    "${KDL_SOURCE_DIR}/src/chainjnttojacsolver.cpp"
    "${KDL_SOURCE_DIR}/src/frames.cpp"
    "${KDL_SOURCE_DIR}/src/jacobian.cpp"
    "${KDL_SOURCE_DIR}/src/jntarray.cpp"
    "${KDL_SOURCE_DIR}/src/joint.cpp"
    "${KDL_SOURCE_DIR}/src/rigidbodyinertia.cpp"
    "${KDL_SOURCE_DIR}/src/rotationalinertia.cpp"
    "${KDL_SOURCE_DIR}/src/segment.cpp"
    "${KDL_SOURCE_DIR}/src/utilities/utility.cxx"
  )
endif()

if(EMSCRIPTEN)
  add_executable(kdl ${KDL_WASM_SOURCES})
  target_compile_options(kdl PRIVATE "-fexceptions")
  if(KDL_SOURCE_DIR)
    target_include_directories(kdl PRIVATE "${KDL_SOURCE_DIR}/src" "${EIGEN3_INCLUDE_DIR}")
    target_compile_definitions(kdl PRIVATE KDL_WASM_HAS_OROCOS_KDL=1)
  endif()
  set_target_properties(kdl PROPERTIES OUTPUT_NAME "kdl" SUFFIX ".js")
  target_link_options(kdl PRIVATE
    "--no-entry"
    "-sMODULARIZE=1"
    "-sEXPORT_ES6=1"
    "-sEXPORT_NAME=createKdlModule"
    "-sENVIRONMENT=web,worker,node"
    "-sALLOW_MEMORY_GROWTH=1"
    "-fexceptions"
    "-sDISABLE_EXCEPTION_CATCHING=0"
    "-sEXPORTED_RUNTIME_METHODS=ccall,cwrap,UTF8ToString,stringToUTF8,lengthBytesUTF8,HEAPF64"
    "-sEXPORTED_FUNCTIONS=['_malloc','_free','_kdl_init','_kdl_create_robot','_kdl_destroy_robot','_kdl_get_robot_info','_kdl_fk','_kdl_fk_all_links','_kdl_jacobian','_kdl_ik','_kdl_plan_movej','_kdl_plan_movel','_kdl_plan_movec','_kdl_plan_path','_kdl_sample_trap','_kdl_last_error']"
  )
  add_custom_command(TARGET kdl POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
      "${CMAKE_CURRENT_SOURCE_DIR}/bindings/kdl.d.ts"
      "${CMAKE_CURRENT_BINARY_DIR}/kdl.d.ts"
  )
else()
  add_library(kdl SHARED ${KDL_WASM_SOURCES})
  if(KDL_SOURCE_DIR)
    target_include_directories(kdl PRIVATE "${KDL_SOURCE_DIR}/src" "${EIGEN3_INCLUDE_DIR}")
    target_compile_definitions(kdl PRIVATE KDL_WASM_HAS_OROCOS_KDL=1)
  endif()
endif()
