# Userspace components CMakeLists.txt

# Core library
add_library(mvgal_core STATIC
    core/fork_safe.c
    api/mvgal_api.c
    api/mvgal_ai.c
    api/mvgal_log.c
    daemon/gpu_manager.c
    daemon/config.c
    daemon/ipc.c
    execution/execution.c
    memory/memory.c
    memory/dmabuf.c
    memory/allocator.c
    memory/sync.c
    memory/mvgal_unified_heap.c
    memory/mvgal_p2p_dma.c
    power/power_manager.c
    power/power_curve.c
    scheduler/scheduler.c
    scheduler/load_balancer.c
    scheduler/workload_splitter.c
    scheduler/mvgal_ai_features.c
    scheduler/strategy/afr.c
    scheduler/strategy/sfr.c
    scheduler/strategy/task.c
    scheduler/strategy/compute_offload.c
    scheduler/strategy/hybrid.c
    transport/mvgal_transport.c
    network/mvgal_pool.c
    network/mvgal_discovery.c
    network/mvgal_remote.c
)

# GCC < 9: LTO plugin drops symbols from static archives when linking
# executables that consume mvgal_core.  Build archive objects with -fno-lto
# so the LTO plugin has no bytecode to misinterpret during linking.
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 9)
    target_compile_options(mvgal_core PRIVATE -fno-lto)
endif()

target_include_directories(mvgal_core
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}
        ${CMAKE_CURRENT_SOURCE_DIR}/../..
        ${MVGAL_INCLUDE_DIRS}
)

target_link_libraries(mvgal_core
    PRIVATE
        Threads::Threads
        ${DRM_IMPORTED_TARGET}
        ${PCI_IMPORTED_TARGET}
        ${UDEV_IMPORTED_TARGET}
        m
)

# Vulkan interception layer (optional)
if(MVGAL_BUILD_API AND (Vulkan_FOUND OR VULKAN_FOUND))
    set(_vk_srcs
        intercept/vulkan/vk_layer.c
        intercept/vulkan/mvgal_shader_translate.c
        intercept/vulkan/mvgal_barrier_translate.c
        intercept/vulkan/mvgal_cmd_dag.c
        intercept/vulkan/mvgal_shader_backend_amd.c
        intercept/vulkan/mvgal_shader_backend_nvidia.c
        intercept/vulkan/mvgal_shader_backend_intel.c
        intercept/vulkan/mvgal_shader_backend_mtt.c
    )

    if(MVGAL_ENABLE_SPIRV_OPT)
        list(APPEND _vk_srcs
            intercept/vulkan/mvgal_spirv_opt.cpp
            intercept/vulkan/mvgal_spirv_cross.cpp
        )
    endif()

    add_library(mvgal_vulkan_layer SHARED ${_vk_srcs})

    target_include_directories(mvgal_vulkan_layer
        PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}
            ${CMAKE_CURRENT_SOURCE_DIR}/../..
            ${Vulkan_INCLUDE_DIRS}
            ${MVGAL_INCLUDE_DIRS}
            ${CMAKE_CURRENT_BINARY_DIR}
            ${CMAKE_CURRENT_SOURCE_DIR}/../..
    )

    set_target_properties(mvgal_vulkan_layer PROPERTIES
        OUTPUT_NAME "VK_LAYER_MVGAL"
        VERSION ${PROJECT_VERSION}
        SOVERSION 1
    )

    target_link_options(mvgal_vulkan_layer
        PRIVATE
            -Wl,-Bsymbolic-functions
    )

    target_link_libraries(mvgal_vulkan_layer
        PRIVATE
            mvgal_core
            Threads::Threads
    )

    if(MVGAL_ENABLE_SPIRV_OPT)
        target_compile_definitions(mvgal_vulkan_layer PRIVATE MVGAL_ENABLE_SPIRV_OPT)
        target_link_libraries(mvgal_vulkan_layer
            PRIVATE
                spirv-tools::spirv-tools
                spirv-cross::spirv-cross
        )
    endif()

    file(GENERATE
        OUTPUT "$<TARGET_FILE_DIR:mvgal_vulkan_layer>/VK_LAYER_MVGAL.json"
        CONTENT [=[
{
  "file_format_version": "1.0.0",
  "layer": {
    "name": "VK_LAYER_MVGAL",
    "type": "GLOBAL",
    "library_path": "$<TARGET_FILE:mvgal_vulkan_layer>",
    "api_version": "1.3.0",
    "implementation_version": "2",
    "description": "MVGAL Vulkan interception layer for multi-vendor GPU aggregation",
    "functions": {
      "vkNegotiateLoaderLayerInterfaceVersion": "vkNegotiateLoaderLayerInterfaceVersion"
    },
    "enable_environment": {
      "MVGAL_VULKAN_ENABLE": "1"
    },
    "disable_environment": {
      "MVGAL_VULKAN_DISABLE": "1"
    }
  }
}
]=]
    )

    configure_file(
        "${CMAKE_CURRENT_SOURCE_DIR}/intercept/vulkan/manifest.json.in"
        "${CMAKE_CURRENT_BINARY_DIR}/VK_LAYER_MVGAL.json"
        @ONLY
    )

    install(
        TARGETS mvgal_vulkan_layer
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT runtime
    )

    install(
        FILES "${CMAKE_CURRENT_BINARY_DIR}/VK_LAYER_MVGAL.json"
        DESTINATION share/vulkan/implicit_layer.d
        COMPONENT runtime
    )
endif()

# OpenCL interception (optional)
if(MVGAL_BUILD_API AND OpenCL_FOUND)
    add_library(mvgal_opencl SHARED
        intercept/opencl/cl_intercept.c
    )
    set_target_properties(mvgal_opencl PROPERTIES
        VERSION ${PROJECT_VERSION}
        SOVERSION 1
    )

    target_include_directories(mvgal_opencl
        PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}
            ${CMAKE_CURRENT_SOURCE_DIR}/../..
            ${OpenCL_INCLUDE_DIRS}
            ${MVGAL_INCLUDE_DIRS}
    )

    target_link_libraries(mvgal_opencl
        PRIVATE
            mvgal_core
            ${OpenCL_LIBRARIES}
            Threads::Threads
            dl
    )

    install(
        TARGETS mvgal_opencl
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT runtime
    )
endif()

# D3D wrapper (Wine/Proton support)
if(MVGAL_BUILD_API)
    add_library(mvgal_d3d SHARED
        intercept/d3d/d3d_wrapper.c
    )
    set_target_properties(mvgal_d3d PROPERTIES
        VERSION ${PROJECT_VERSION}
        SOVERSION 1
    )

    target_include_directories(mvgal_d3d
        PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}
            ${CMAKE_CURRENT_SOURCE_DIR}/../..
            ${MVGAL_INCLUDE_DIRS}
    )

    target_link_libraries(mvgal_d3d
        PRIVATE
            mvgal_core
            Threads::Threads
            dl
    )

    install(
        TARGETS mvgal_d3d
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT runtime
    )
endif()

# Metal wrapper (macOS compatibility on Linux)
if(MVGAL_BUILD_API)
    add_library(mvgal_metal SHARED
        intercept/metal/metal_wrapper.c
    )
    set_target_properties(mvgal_metal PROPERTIES
        VERSION ${PROJECT_VERSION}
        SOVERSION 1
    )

    target_include_directories(mvgal_metal
        PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}
            ${CMAKE_CURRENT_SOURCE_DIR}/../..
            ${MVGAL_INCLUDE_DIRS}
    )

    target_link_libraries(mvgal_metal
        PRIVATE
            mvgal_core
            Threads::Threads
            dl
    )

    install(
        TARGETS mvgal_metal
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT runtime
    )
endif()

# WebGPU wrapper
if(MVGAL_BUILD_API)
    add_library(mvgal_webgpu SHARED
        intercept/webgpu/webgpu_wrapper.c
    )

    target_include_directories(mvgal_webgpu
        PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}
            ${CMAKE_CURRENT_SOURCE_DIR}/../..
            ${MVGAL_INCLUDE_DIRS}
    )

    target_link_libraries(mvgal_webgpu
        PRIVATE
            mvgal_core
            Threads::Threads
            dl
    )

    install(
        TARGETS mvgal_webgpu
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT runtime
    )
endif()

# SYCL backend
if(MVGAL_BUILD_API AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/sycl/CMakeLists.txt")
    add_subdirectory(sycl)
endif()

# WoW64 thunk layer (Wine/Proton support for 32-bit apps)
if(MVGAL_BUILD_API)
    add_library(mvgal_wow64 SHARED
        win32/wow64_thunk.c
    )
    set_target_properties(mvgal_wow64 PROPERTIES
        VERSION ${PROJECT_VERSION}
        SOVERSION 1
    )

    target_include_directories(mvgal_wow64
        PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}
            ${CMAKE_CURRENT_SOURCE_DIR}/../..
            ${MVGAL_INCLUDE_DIRS}
    )

    target_link_libraries(mvgal_wow64
        PRIVATE
            mvgal_core
            Threads::Threads
            dl
    )

    install(
        TARGETS mvgal_wow64
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT runtime
    )
endif()

# CUDA wrapper (experimental)
if(WITH_CUDA AND CUDAToolkit_FOUND)
    add_library(mvgal_cuda SHARED
        intercept/cuda/cuda_wrapper.c
    )

    target_include_directories(mvgal_cuda
        PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}
            ${CMAKE_CURRENT_SOURCE_DIR}/../..
            ${CUDAToolkit_INCLUDE_DIRS}
            ${MVGAL_INCLUDE_DIRS}
    )

    target_link_libraries(mvgal_cuda
        PRIVATE
            mvgal_core
            ${CUDAToolkit_LIBRARIES}
            Threads::Threads
            dl
    )

    install(
        TARGETS mvgal_cuda
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT runtime
    )
endif()

# Daemon
if(WITH_DAEMON)
    add_executable(mvgal-daemon
        daemon/main.c
        daemon/gpu_manager.c
        daemon/config.c
        daemon/ipc.c
    )

    target_include_directories(mvgal-daemon
        PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}
            ${CMAKE_CURRENT_SOURCE_DIR}/../..
            ${MVGAL_INCLUDE_DIRS}
    )

    target_link_libraries(mvgal-daemon
        PRIVATE
            mvgal_core
            Threads::Threads
            ${DRM_IMPORTED_TARGET}
            ${PCI_IMPORTED_TARGET}
            ${UDEV_IMPORTED_TARGET}
    )

    install(
        TARGETS mvgal-daemon
        RUNTIME DESTINATION sbin
        COMPONENT runtime
    )
endif()

# Install core library
install(
    TARGETS mvgal_core
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    COMPONENT development
)

# Install headers are handled in parent CMakeLists.txt
