project(runanywherecore)
# Must match core/VERSIONS::MIN_CMAKE_VERSION (3.24).
cmake_minimum_required(VERSION 3.24)

set(PACKAGE_NAME runanywherecore)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 20)

# =============================================================================
# 16KB Page Alignment for Android 15+ (API 35) Compliance
# Required starting November 1, 2025 for Google Play submissions
# =============================================================================
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384")

# Path to pre-built native libraries (downloaded from runanywhere-sdks)
set(JNILIB_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})

# Path to RAC headers (downloaded with native libraries into jniLibs)
set(RAC_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs/include)

# =============================================================================
# RACommons - Core SDK functionality (rac_* API)
# This is the ONLY native library in the core package
# RACommons is REQUIRED - it's downloaded via Gradle downloadNativeLibs task
# =============================================================================
if(NOT EXISTS "${JNILIB_DIR}/librac_commons.so")
    message(FATAL_ERROR "[RunAnywhereCore] RACommons not found for ${ANDROID_ABI} at ${JNILIB_DIR}/librac_commons.so\n"
                        "Run ./scripts/build/build-core-android.sh from the repo root or set reactNativeArchitectures to an ABI with staged natives.")
endif()

add_library(rac_commons SHARED IMPORTED)
set_target_properties(rac_commons PROPERTIES
    IMPORTED_LOCATION "${JNILIB_DIR}/librac_commons.so"
    IMPORTED_NO_SONAME TRUE
)
message(STATUS "[RunAnywhereCore] Found RACommons at ${JNILIB_DIR}/librac_commons.so")

# =============================================================================
# HTTP transport vtable: the OkHttp JNI adapter ships with librunanywhere_jni.so
# (built from core/src/jni/okhttp_transport_adapter.cpp).
# RN loads that lib at runtime in RunAnywhereCorePackage; no fork compiled here.
# =============================================================================
set(RAC_HAS_HTTP_TRANSPORT ON)
message(STATUS "[RunAnywhereCore] OkHttp HTTP transport adapter ENABLED (RAC_HAS_HTTP_TRANSPORT=1)")

# =============================================================================
# Source files - Core bridges only (no LLM/STT/TTS/VAD)
# =============================================================================
# Collect core bridge source files
file(GLOB BRIDGE_SOURCES CONFIGURE_DEPENDS "../cpp/bridges/*.cpp")
file(GLOB HYBRID_CORE_DOMAIN_SOURCES CONFIGURE_DEPENDS "../cpp/HybridRunAnywhereCore+*.cpp")

add_library(${PACKAGE_NAME} SHARED
    src/main/cpp/cpp-adapter.cpp
    ../cpp/AudioCaptureLevel.cpp
    ../cpp/HybridLLM.cpp
    ../cpp/HybridRunAnywhereCore.cpp
    ${HYBRID_CORE_DOMAIN_SOURCES}
    ../cpp/HybridVoiceAgent.cpp
    ${BRIDGE_SOURCES}
)

# =============================================================================
# Fix NitroModules prefab path for library modules
# The prefab config generated by AGP has incorrect paths when building library modules
# We need to create the NitroModules target BEFORE the autolinking.cmake runs
# =============================================================================
if(DEFINED REACT_NATIVE_NITRO_BUILD_DIR)
    # Find NitroModules.so in the app's build directory
    set(NITRO_LIBS_DIR "${REACT_NATIVE_NITRO_BUILD_DIR}/intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib/${ANDROID_ABI}")
    if(EXISTS "${NITRO_LIBS_DIR}/libNitroModules.so")
        message(STATUS "[RunAnywhereCore] Using NitroModules from app build: ${NITRO_LIBS_DIR}")
        add_library(react-native-nitro-modules::NitroModules SHARED IMPORTED)
        set_target_properties(react-native-nitro-modules::NitroModules PROPERTIES
            IMPORTED_LOCATION "${NITRO_LIBS_DIR}/libNitroModules.so"
        )
    endif()
endif()

# Add Nitrogen specs (this handles all React Native linking)
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/runanywherecore+autolinking.cmake)

# =============================================================================
# Include directories
# =============================================================================
include_directories(
    "src/main/cpp"
    # Local headers (rac_http_transport.h, etc.) searched BEFORE
    # jniLibs/include so our copy wins where needed.
    "../cpp"
    "../cpp/bridges"
    "${CMAKE_SOURCE_DIR}/include"
    # RAC API headers from runanywhere-commons (flat access)
    "${RAC_INCLUDE_DIR}"
    "${RAC_INCLUDE_DIR}/rac"
    "${RAC_INCLUDE_DIR}/rac/core"
    "${RAC_INCLUDE_DIR}/rac/core/capabilities"
    "${RAC_INCLUDE_DIR}/rac/features"
    "${RAC_INCLUDE_DIR}/rac/features/llm"
    "${RAC_INCLUDE_DIR}/rac/features/stt"
    "${RAC_INCLUDE_DIR}/rac/features/tts"
    "${RAC_INCLUDE_DIR}/rac/features/vad"
    "${RAC_INCLUDE_DIR}/rac/features/voice_agent"
    "${RAC_INCLUDE_DIR}/rac/features/rag"
    "${RAC_INCLUDE_DIR}/rac/features/platform"
    "${RAC_INCLUDE_DIR}/rac/backends"
    "${RAC_INCLUDE_DIR}/rac/infrastructure"
    "${RAC_INCLUDE_DIR}/rac/infrastructure/device"
    "${RAC_INCLUDE_DIR}/rac/infrastructure/download"
    "${RAC_INCLUDE_DIR}/rac/infrastructure/events"
    "${RAC_INCLUDE_DIR}/rac/infrastructure/model_management"
    "${RAC_INCLUDE_DIR}/rac/infrastructure/network"
    "${RAC_INCLUDE_DIR}/rac/infrastructure/extraction"
    "${RAC_INCLUDE_DIR}/rac/infrastructure/file_management"
    "${RAC_INCLUDE_DIR}/rac/infrastructure/storage"
    "${RAC_INCLUDE_DIR}/rac/infrastructure/telemetry"
)

# =============================================================================
# Linking
# =============================================================================
find_library(LOG_LIB log)

target_link_libraries(
    ${PACKAGE_NAME}
    ${LOG_LIB}
    android
    c++_shared
)

# Link RACommons - REQUIRED for core functionality
target_link_libraries(${PACKAGE_NAME} rac_commons)
target_compile_definitions(${PACKAGE_NAME} PRIVATE HAS_RACOMMONS=1)

# OkHttp adapter is always compiled in — commons v0.2.0+ is required and
# the bundled librac_commons.so always exports rac_http_transport_register.
target_compile_definitions(${PACKAGE_NAME} PRIVATE RAC_HAS_HTTP_TRANSPORT=1)

# 16KB page alignment - MUST be on target for Android 15+ compliance
target_link_options(${PACKAGE_NAME} PRIVATE
    -Wl,-z,max-page-size=16384
    -Wl,-z,common-page-size=16384)

# NOTE: No LlamaCPP or ONNX linking here
# Those are in @runanywhere/llamacpp and @runanywhere/onnx packages respectively
