# Builds the Usakey JSI host object for Android.
#
# The binding itself is the C++ in ../cpp; this file adds the JNI entry point
# React Native's package glue calls to install it into the JavaScript runtime,
# and links the two libraries it needs: React Native's libjsi.so, which comes
# from the react-android AAR as a prefab package, and the Usakey C ABI static
# library cross-compiled for the same ABI.
#
# Paths are resolved relative to this package, not to a checkout of the SDK
# repository: in an application this directory is
# node_modules/@usakey/react-native/android, and the repository layout does not
# exist around it.
cmake_minimum_required(VERSION 3.22.1)
project(usakey-react-native LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

get_filename_component(USAKEY_PACKAGE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.." ABSOLUTE)

# The C ABI library and its headers, produced once per ABI by build-ffi.sh.
# They must come from the same source revision as the C++ in ../cpp;
# usakey_abi_check catches struct layout drift at load time but is not a
# substitute for matching revisions, which is why the headers are taken from
# the same directory as the library rather than from anywhere else.
if(NOT DEFINED USAKEY_FFI_DIR)
  message(FATAL_ERROR
    "set USAKEY_FFI_DIR to the directory build-ffi.sh wrote: it holds include/ "
    "and <abi>/libusakey_ffi.a")
endif()

if(NOT DEFINED USAKEY_FFI_LIB)
  set(USAKEY_FFI_LIB "${USAKEY_FFI_DIR}/${ANDROID_ABI}/libusakey_ffi.a")
endif()
if(NOT EXISTS "${USAKEY_FFI_LIB}")
  message(FATAL_ERROR "no C ABI library for ${ANDROID_ABI} at ${USAKEY_FFI_LIB}; run build-ffi.sh")
endif()

if(NOT DEFINED USAKEY_INCLUDE_DIR)
  set(USAKEY_INCLUDE_DIR "${USAKEY_FFI_DIR}/include")
endif()
foreach(header usakey.h usakey.hpp)
  if(NOT EXISTS "${USAKEY_INCLUDE_DIR}/${header}")
    message(FATAL_ERROR "${header} is missing from ${USAKEY_INCLUDE_DIR}; run build-ffi.sh")
  endif()
endforeach()

# React Native ships the JSI headers and libjsi.so inside the react-android
# AAR. `prefab true` in build.gradle unpacks them; this is the supported way to
# reach them, and it keeps the header and the library at the same version.
find_package(ReactAndroid REQUIRED CONFIG)

add_library(usakey-react-native SHARED
  "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/OnLoad.cpp"
  "${USAKEY_PACKAGE_DIR}/cpp/UsakeyHostObject.cpp"
)

target_include_directories(usakey-react-native PRIVATE
  "${USAKEY_PACKAGE_DIR}/cpp"
  "${USAKEY_INCLUDE_DIR}"
)

find_library(LOG_LIB log)
target_link_libraries(usakey-react-native
  ReactAndroid::jsi
  "${USAKEY_FFI_LIB}"
  "${LOG_LIB}"
)

# Export the JNI entry point and nothing else. See src/main/cpp/exports.map.
set(USAKEY_EXPORTS "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/exports.map")
target_link_options(usakey-react-native PRIVATE
  "-Wl,--exclude-libs,ALL"
  "-Wl,--version-script=${USAKEY_EXPORTS}"
)
set_target_properties(usakey-react-native PROPERTIES LINK_DEPENDS "${USAKEY_EXPORTS}")
