# Phase 1 hardware validation executables. Each one proves a single native
# SDK is linkable and functional on this machine *before* core/src/backends
# depends on it in Phase 2 - see PHASE_PLAN.md Phase 1.
#
# Intel ships OpenVINO's Windows runtime built with MSVC. Mixing that with a
# MinGW-compiled application is unsafe at the linker/ABI level (different
# C++ standard library implementations, incompatible name mangling for any
# STL type crossing the boundary) - so anything in this directory must be
# configured with the MSVC generator, e.g.:
#   cmake -S . -B build -G "Visual Studio 17 2022" -A x64 -DSCAVENGER_BUILD_HARDWARE_TOOLS=ON
# See docs/DEVELOPMENT.md for the full setup (OpenVINO_DIR, VULKAN_SDK, etc.)

find_package(OpenVINO REQUIRED)

add_executable(ov_smoke_test ov_smoke_test.cpp)
target_link_libraries(ov_smoke_test PRIVATE openvino::runtime)

add_executable(ov_inference_smoke_test ov_inference_smoke_test.cpp)
target_link_libraries(ov_inference_smoke_test PRIVATE openvino::runtime)

add_executable(llama_smoke_test llama_smoke_test.cpp)
target_link_libraries(llama_smoke_test PRIVATE llama)

# scheduler_demo (Phase 2 commit 8) needs the real IBackend implementations
# under core/src/backends/, not just the raw SDKs above - only buildable
# when both flags are on (the common case; see docs/DEVELOPMENT.md).
# nlohmann_json (Phase 4 commit 3, extended for the image-generation
# benchmark below): the JSON trace/result schema shared with
# benchmarks/ollama_runner.py - a single FetchContent-ed header-only
# library (same pattern as Catch2/concurrentqueue above) rather than a
# hand-rolled parser, since the schema has nested objects/arrays and needs
# both directions (read the trace, write results) round-tripped exactly.
# Declared once here (rather than duplicated in each `if` block below)
# since SCAVENGER_BUILD_BACKENDS and SCAVENGER_BUILD_IMAGE_GEN can each
# independently need it.
if(SCAVENGER_BUILD_BACKENDS OR SCAVENGER_BUILD_IMAGE_GEN)
    include(FetchContent)
    FetchContent_Declare(
        nlohmann_json
        GIT_REPOSITORY https://github.com/nlohmann/json.git
        GIT_TAG v3.11.3
    )
    FetchContent_MakeAvailable(nlohmann_json)
endif()

if(SCAVENGER_BUILD_BACKENDS)
    add_executable(scheduler_demo scheduler_demo.cpp)
    target_link_libraries(scheduler_demo PRIVATE scavenger_core)

    add_executable(scavenger_bench scavenger_bench.cpp)
    target_link_libraries(scavenger_bench PRIVATE scavenger_core nlohmann_json::nlohmann_json)

    # chat_demo (Phase 4 commit 7) - bonus interactive REPL, outside strict
    # spec Phase 4 scope. Only needs scavenger_core (a single
    # LlamaVulkanBackend, no Scheduler) - see the file's own header comment.
    add_executable(chat_demo chat_demo.cpp)
    target_link_libraries(chat_demo PRIVATE scavenger_core)

    # chat_scheduler_demo (post-Phase-7) - interactive REPL through the real
    # two-device Scheduler with per-turn routing + telemetry metrics.
    add_executable(chat_scheduler_demo chat_scheduler_demo.cpp)
    target_link_libraries(chat_scheduler_demo PRIVATE scavenger_core)

    add_executable(scavenger_chat_bench scavenger_chat_bench.cpp)
    target_link_libraries(scavenger_chat_bench PRIVATE scavenger_core nlohmann_json::nlohmann_json)

    add_executable(scavenger_session_server scavenger_session_server.cpp)
    target_link_libraries(scavenger_session_server PRIVATE scavenger_core nlohmann_json::nlohmann_json)

    # embedding_bench (Phase 5, commit 5) - Tier 1 vs. Tier 2 comparison
    # through a real Scheduler with genuinely concurrent requests, the
    # closest faithful equivalent to "re-run the Phase 4 benchmark matrix
    # with Tier 2 enabled" for the code path Tier 2 actually touches (see
    # the file's own header comment for why this isn't literally
    # scavenger_bench.cpp with a flag). Builds fine under
    # SCAVENGER_BUILD_BACKENDS alone - it only calls
    # OpenVinoBackend::IsUsmActive()/the enable_usm_tensors constructor
    # arg, no direct OpenCL/ocl.hpp dependency - but the "Tier 2" run only
    # succeeds (rather than failing loudly, by design) when
    # SCAVENGER_ENABLE_TIER2_USM was also ON.
    add_executable(embedding_bench embedding_bench.cpp)
    target_link_libraries(embedding_bench PRIVATE scavenger_core nlohmann_json::nlohmann_json)
endif()

# image_demo/image_gen_bench (Phase 4 image-generation extension) need
# OpenVinoImageBackend specifically - independent of SCAVENGER_BUILD_BACKENDS
# above, same as core/src/backends/CMakeLists.txt's own gating.
if(SCAVENGER_BUILD_IMAGE_GEN)
    add_executable(image_demo image_demo.cpp)
    target_link_libraries(image_demo PRIVATE scavenger_core)

    add_executable(image_gen_bench image_gen_bench.cpp)
    target_link_libraries(image_gen_bench PRIVATE scavenger_core nlohmann_json::nlohmann_json)
endif()

# usm_spike (Phase 5, commit 1) - standalone Tier 1 (plain ov::Tensor) vs.
# Tier 2 (GPU Remote Tensor / USM) marshalling-overhead measurement. Needs
# plain OpenVINO (same find_package(OpenVINO REQUIRED) at the top of this
# file already provides it) plus the Khronos OpenCL C/C++ headers - fetched
# at the root CMakeLists.txt level (shared with SCAVENGER_ENABLE_TIER2_USM
# below it) since the OpenVINO SDK doesn't bundle them itself; see that
# file's comment for why.
if(SCAVENGER_BUILD_TIER2_SPIKE)
    add_executable(usm_spike usm_spike.cpp)
    target_link_libraries(usm_spike PRIVATE openvino::runtime OpenCL::Headers OpenCL::HeadersCpp OpenCL::OpenCL)

    # usm_copy_avoidance_check (Phase 5, commit 4) - per-phase (copy-in /
    # infer / copy-out) timing breakdown verifying *where* usm_spike's
    # measured win actually comes from, per spec §6.3's "confirm via
    # profiling/instrumented timing... don't trust the API's existence as
    # proof" instruction. Same flag/dependencies as usm_spike above.
    add_executable(usm_copy_avoidance_check usm_copy_avoidance_check.cpp)
    target_link_libraries(usm_copy_avoidance_check PRIVATE openvino::runtime OpenCL::Headers OpenCL::HeadersCpp OpenCL::OpenCL)
endif()

# tier3_vulkan_import_spike (Phase 6, commit 1, research-grade) - can
# llama.cpp's own Vulkan backend accept a buffer *this process* allocated,
# with zero ggml-vulkan.cpp patch? Only needs the `ggml`/`llama` targets
# third_party/llama.cpp already provides when SCAVENGER_BUILD_HARDWARE_TOOLS
# or SCAVENGER_BUILD_BACKENDS turned GGML_VULKAN on (see root CMakeLists.txt)
# - no OpenVINO/OpenCL dependency of its own, unlike the Tier 2 spikes above.
if(SCAVENGER_BUILD_HARDWARE_TOOLS OR SCAVENGER_BUILD_BACKENDS)
    add_executable(tier3_vulkan_import_spike tier3_vulkan_import_spike.cpp)
    target_link_libraries(tier3_vulkan_import_spike PRIVATE llama ggml)
endif()

# tier3_shared_buffer_spike (Phase 6, commit 5, research-grade) - the
# capstone attempt: import OpenVINO's *own* USM host-tensor pointer
# (core/src/backends/openvino_usm_pool.cpp's exact allocation) into
# llama.cpp's Vulkan backend, so it needs both stacks the two spikes above
# each needed independently: plain OpenVINO (SCAVENGER_BUILD_TIER2_SPIKE's
# find_package(OpenVINO REQUIRED) at the top of this file) + the fetched
# OpenCL C++ headers for ov/runtime/intel_gpu/ocl/ocl.hpp, and ggml/llama
# for the Vulkan import side.
if(SCAVENGER_BUILD_TIER2_SPIKE AND (SCAVENGER_BUILD_HARDWARE_TOOLS OR SCAVENGER_BUILD_BACKENDS))
    add_executable(tier3_shared_buffer_spike tier3_shared_buffer_spike.cpp)
    target_link_libraries(tier3_shared_buffer_spike PRIVATE llama ggml openvino::runtime OpenCL::Headers
                                                             OpenCL::HeadersCpp OpenCL::OpenCL)
endif()
