cmake_minimum_required(VERSION 3.12)
# OBJC/OBJCXX only exist on Apple (Metal path) — enabling them unconditionally
# breaks CMake configure on Linux/Windows runners.
project(axim_gpu LANGUAGES CXX)
if(APPLE)
    enable_language(OBJC OBJCXX)
endif()

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# ─────────────────────────────────────────────────────────────
# Vendor-neutral GPU backend selection (no CUDA anywhere):
#   macOS  → Metal (Objective-C++ source, -framework Metal)
#   Linux  → Vulkan (libaxim_gpu.so; requires Vulkan SDK at build time)
#   Windows→ Vulkan (axim_gpu.dll; requires Vulkan SDK at build time)
#
# AXIM_FORCE_VULKAN=ON builds the Vulkan path on macOS too (MoltenVK:
# Vulkan-on-Metal) — used to dry-run the Linux CI pipeline locally.
#   cmake -S backend_gpu -B build-vk -DAXIM_FORCE_VULKAN=ON
# ─────────────────────────────────────────────────────────────

option(AXIM_FORCE_VULKAN "Build the Vulkan backend even on macOS (MoltenVK)" OFF)

if(APPLE AND NOT AXIM_FORCE_VULKAN)
    add_library(axim_metal SHARED src/axim_metal.mm)
    target_compile_options(axim_metal PRIVATE -O3 -fobjc-arc)
    target_include_directories(axim_metal PUBLIC include)
    target_link_libraries(axim_metal PRIVATE
        "-framework Metal"
        "-framework Foundation"
    )
    set_target_properties(axim_metal PROPERTIES
        OUTPUT_NAME "axim_metal"
        PREFIX "lib"
    )
    message(STATUS "AximOS GPU backend: Metal (Apple silicon)")
else()
    # Linux / Windows — Vulkan SPIR-V path (Nvidia / AMD / Intel)
    find_package(Vulkan QUIET)
    if(Vulkan_FOUND)
        # SPIR-V runtime executor (VkInstance → VkDevice → dispatch → readback)
        # Sources are guarded by #ifdef AXIM_BUILD_VULKAN — always define it
        # in this branch (we only get here when Vulkan was found).
        add_library(axim_vk_executor STATIC src/axim_vulkan_executor.cpp)
        target_compile_options(axim_vk_executor PRIVATE -O3)
        target_compile_definitions(axim_vk_executor PRIVATE AXIM_BUILD_VULKAN)
        target_include_directories(axim_vk_executor PUBLIC include ${Vulkan_INCLUDE_DIRS})
        target_link_libraries(axim_vk_executor PUBLIC ${Vulkan_LIBRARIES})

        add_library(axim_gpu SHARED src/axim_gpu_vulkan.cpp)
        target_compile_options(axim_gpu PRIVATE -O3)
        target_compile_definitions(axim_gpu PRIVATE AXIM_BUILD_VULKAN)
        target_include_directories(axim_gpu PUBLIC include ${Vulkan_INCLUDE_DIRS})
        target_link_libraries(axim_gpu PRIVATE axim_vk_executor ${Vulkan_LIBRARIES})
        set_target_properties(axim_gpu PROPERTIES
            OUTPUT_NAME "axim_gpu"
            PREFIX "lib"
        )

        # Executed (not merely compiled) on CI: runs axim_add.spv through the
        # full Vulkan path on Lavapipe software Vulkan — no physical GPU needed.
        add_executable(axim_vk_selftest test_vulkan_executor.cpp)
        target_compile_options(axim_vk_selftest PRIVATE -O3)
        target_compile_definitions(axim_vk_selftest PRIVATE AXIM_BUILD_VULKAN)
        target_include_directories(axim_vk_selftest PRIVATE include ${Vulkan_INCLUDE_DIRS})
        target_link_libraries(axim_vk_selftest PRIVATE axim_vk_executor ${Vulkan_LIBRARIES})

        message(STATUS "AximOS GPU backend: Vulkan (${Vulkan_VERSION})")
    else()
        message(WARNING
            "Vulkan SDK not found — libaxim_gpu will NOT be built. "
            "AximOS will fall back to the CPU SIMD backend on this host. "
            "Install the Vulkan SDK (https://vulkan.lunarg.com) and re-run CMake.")
    endif()
endif()
