cmake_minimum_required(VERSION 3.28)

project(whalejs-duktape VERSION 2.2.0)


###############################################################################
# Configuration

set(WHLJS_DUKTAPE_PATH "" CACHE PATH "Path to Duktape source code")


###############################################################################
# Dependencies

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

find_package(Python2 REQUIRED)


###############################################################################
# Common

set(WHLJS_DUKTAPE_DEBUG_SRC_DIR "${CMAKE_BINARY_DIR}/duktape-debugger")
set(WHLJS_DUKTAPE_DEBUG_SRC_FILE "${WHLJS_DUKTAPE_DEBUG_SRC_DIR}/duktape.c")
set(WHLJS_DUKTAPE_NO_DEBUG_SRC_DIR "${CMAKE_BINARY_DIR}/duktape-no-debugger")
set(WHLJS_DUKTAPE_NO_DEBUG_SRC_FILE "${WHLJS_DUKTAPE_NO_DEBUG_SRC_DIR}/duktape.c")

set(WHLJS_DUKTAPE_COMMON_CONFIG_OPTIONS
  -D DUK_USE_FATAL_HANDLER
  -D DUK_USE_SYMBOL_BUILTIN
  -D DUK_USE_CPP_EXCEPTIONS
  --dll

  # Performance
  -D DUK_USE_ALLOW_UNDEFINED_BEHAVIOR
  -U DUK_USE_PREFER_SIZE
  -U DUK_USE_PACKED_TVAL
  -D DUK_USE_FASTINT
  -D DUK_USE_VALSTACK_UNSAFE
  -D DUK_USE_FAST_REFCOUNT_DEFAULT
  -D DUK_USE_JSON_STRINGIFY_FASTPATH
  -D DUK_USE_JSON_QUOTESTRING_FASTPATH
  -D DUK_USE_JSON_DECSTRING_FASTPATH
  -D DUK_USE_JSON_DECNUMBER_FASTPATH
  -D DUK_USE_JSON_EATWHITE_FASTPATH
  -D DUK_USE_BASE64_FASTPATH
  -D DUK_USE_HEX_FASTPATH
  -D DUK_USE_IDCHAR_FASTPATH
  -D DUK_USE_ARRAY_PROP_FASTPATH
  -D DUK_USE_ARRAY_FASTPATH
  -U DUK_USE_STRHASH_DENSE
  -D DUK_USE_STRHASH_SKIP_SHIFT=5
  -D DUK_USE_LITCACHE_SIZE=1024
  -D DUK_USE_REGEXP_CANON_WORKAROUND
  
  # Timing
  -D DUK_USE_MARK_AND_SWEEP
  -D DUK_USE_REFERENCE_COUNTING
  -U DUK_USE_VOLUNTARY_GC
)

if(WIN32)
  set(WHLJS_DUKTAPE_COMMON_CONFIG_OPTIONS
    ${WHLJS_DUKTAPE_COMMON_CONFIG_OPTIONS}
    -D DUK_USE_DATE_NOW_WINDOWS
  )
endif()

add_custom_command(
  OUTPUT "${WHLJS_DUKTAPE_NO_DEBUG_SRC_FILE}"
  WORKING_DIRECTORY "${WHLJS_DUKTAPE_PATH}/tools"
  COMMAND "${Python2_EXECUTABLE}" configure.py
          --output-directory "${WHLJS_DUKTAPE_NO_DEBUG_SRC_DIR}"
          ${WHLJS_DUKTAPE_COMMON_CONFIG_OPTIONS}
          -U DUK_USE_INTERRUPT_COUNTER
          -U DUK_USE_DEBUGGER_SUPPORT
          -U DUK_USE_DEBUGGER_INSPECT
)

add_custom_command(
  OUTPUT "${WHLJS_DUKTAPE_DEBUG_SRC_FILE}"
  WORKING_DIRECTORY "${WHLJS_DUKTAPE_PATH}/tools"
  COMMAND "${Python2_EXECUTABLE}" configure.py
          --output-directory "${WHLJS_DUKTAPE_DEBUG_SRC_DIR}"
          ${WHLJS_DUKTAPE_COMMON_CONFIG_OPTIONS}
          -D DUK_USE_INTERRUPT_COUNTER
          -D DUK_USE_DEBUGGER_SUPPORT
          -D DUK_USE_DEBUGGER_INSPECT
)

set(WHLJS_DUKTAPE_MODULE_NODE_DIR "${WHLJS_DUKTAPE_PATH}/extras/module-node")

set(WHLJS_DUKTAPE_COMMON_SRC_FILES
  "${WHLJS_DUKTAPE_MODULE_NODE_DIR}/duk_module_node.c"
)


###############################################################################
# duktape (Duktape without debugger support)

add_library(whalejs-duktape SHARED
  "${WHLJS_DUKTAPE_NO_DEBUG_SRC_FILE}"
  "${WHLJS_DUKTAPE_COMMON_SRC_FILES}"
)

add_library(whalejs::duktape ALIAS whalejs-duktape)

target_include_directories(whalejs-duktape
  PUBLIC
    "$<INSTALL_INTERFACE:include/no-debugger>"
    "$<BUILD_INTERFACE:${WHLJS_DUKTAPE_NO_DEBUG_SRC_DIR}>"
    "$<BUILD_INTERFACE:${WHLJS_DUKTAPE_MODULE_NODE_DIR}>"
)


###############################################################################
# duktape-dbg (Duktape with debugger support)

add_library(whalejs-duktape-dbg SHARED
  "${WHLJS_DUKTAPE_DEBUG_SRC_FILE}"
  "${WHLJS_DUKTAPE_COMMON_SRC_FILES}"
)

add_library(whalejs::duktape-dbg ALIAS whalejs-duktape-dbg)

target_include_directories(whalejs-duktape-dbg
  PUBLIC
    "$<INSTALL_INTERFACE:include/debugger>"
    "$<BUILD_INTERFACE:${WHLJS_DUKTAPE_DEBUG_SRC_DIR}>"
    "$<BUILD_INTERFACE:${WHLJS_DUKTAPE_MODULE_NODE_DIR}>"
)

target_compile_definitions(whalejs-duktape-dbg
  PUBLIC
    WHLJS_USE_DUKTAPE_DEBUGGER
)


###############################################################################
# Configure properties

set_source_files_properties(
  ${WHLJS_DUKTAPE_COMMON_SRC_FILES}
  ${WHLJS_DUKTAPE_DEBUG_SRC_FILE}
  ${WHLJS_DUKTAPE_NO_DEBUG_SRC_FILE}
  PROPERTIES LANGUAGE CXX
)

if(NOT ANDROID)
  set_target_properties(whalejs-duktape whalejs-duktape-dbg
    PROPERTIES
      PREFIX ""
      IMPORT_PREFIX ""
  )
endif()


###############################################################################
# Installation

set(PACKAGE_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
set(PACKAGE_TARGETS_NAME "${PROJECT_NAME}-targets")

set_target_properties(whalejs-duktape
  PROPERTIES
    EXPORT_NAME duktape
    WINDOWS_EXPORT_ALL_SYMBOLS TRUE
)

set_target_properties(whalejs-duktape-dbg
  PROPERTIES
    EXPORT_NAME duktape-dbg
    WINDOWS_EXPORT_ALL_SYMBOLS TRUE
)

install(
  TARGETS whalejs-duktape whalejs-duktape-dbg
  EXPORT ${PACKAGE_TARGETS_NAME}
  ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
  LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
  RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
  INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)

install(
  EXPORT ${PACKAGE_TARGETS_NAME}
  FILE "${PROJECT_NAME}-targets.cmake"
  NAMESPACE whalejs::
  DESTINATION "${PACKAGE_CONFIG_INSTALL_DIR}"
)

install(
  FILES
    "${WHLJS_DUKTAPE_DEBUG_SRC_DIR}/duk_config.h"
    "${WHLJS_DUKTAPE_DEBUG_SRC_DIR}/duk_source_meta.json"
    "${WHLJS_DUKTAPE_DEBUG_SRC_DIR}/duktape.h"
    "${WHLJS_DUKTAPE_MODULE_NODE_DIR}/duk_module_node.h"
  DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/debugger"
)

install(
  FILES
    "${WHLJS_DUKTAPE_NO_DEBUG_SRC_DIR}/duk_config.h"
    "${WHLJS_DUKTAPE_NO_DEBUG_SRC_DIR}/duk_source_meta.json"
    "${WHLJS_DUKTAPE_NO_DEBUG_SRC_DIR}/duktape.h"
    "${WHLJS_DUKTAPE_MODULE_NODE_DIR}/duk_module_node.h"
  DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/no-debugger"
)

write_basic_package_version_file(
  "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
  VERSION ${PROJECT_VERSION}
  COMPATIBILITY AnyNewerVersion
)

configure_package_config_file(
  "${CMAKE_CURRENT_LIST_DIR}/cmake/config.cmake.in"
  "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
  INSTALL_DESTINATION "${PACKAGE_CONFIG_INSTALL_DIR}"
)

install(
  FILES
    "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"

  DESTINATION
    "${PACKAGE_CONFIG_INSTALL_DIR}"
)
