cmake_minimum_required(VERSION 3.22)
project(run_export CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# --------------------------------------------------------
# XNNPACK discovery
# --------------------------------------------------------
# Let user specify:
#   cmake -DXNNPACK_ROOT=/path/to/XNNPACK/build/local ..
# --------------------------------------------------------
set(XNNPACK_ROOT $ENV{XNNPACK_ROOT} CACHE PATH "Path to a prebuilt XNNPACK (build/local)")

set(XNNPACK_FOUND FALSE)
# set(XNNPACK_BUILD_LIBRARY ON)
set(XNNPACK_BUILD_TESTS OFF)
set(XNNPACK_BUILD_BENCHMARKS OFF)
set(XNNPACK_BUILD_ALL_MICROKERNELS ON)
set(XNNPACK_LIBRARY_TYPE static)


if (XNNPACK_ROOT)
    message(STATUS "Searching for XNNPACK in ${XNNPACK_ROOT}")

    # Find main XNNPACK include directory
    find_path(XNNPACK_MAIN_INCLUDE
        NAMES xnnpack.h
        PATHS ${XNNPACK_ROOT}/../../include
    )

    # pthreadpool headers
    find_path(PTHREADPOOL_INCLUDE
        NAMES pthreadpool.h
        PATHS ${XNNPACK_ROOT}/pthreadpool-source/include
    )

    # cpuinfo headers
    find_path(CPUINFO_INCLUDE
        NAMES cpuinfo.h
        PATHS ${XNNPACK_ROOT}/cpuinfo-source/include
    )

    find_library(XNNPACK_LIB
        NAMES XNNPACK
        PATHS ${XNNPACK_ROOT}
    )

    find_library(XNNPACK_MICROKERNELS_LIB
        NAMES xnnpack-microkernels-prod xnnpack-microkernels-all
        PATHS ${XNNPACK_ROOT}
    )

    find_library(PTHREADPOOL_LIB
        NAMES pthreadpool
        PATHS ${XNNPACK_ROOT}/pthreadpool
    )

    find_library(CPUINFO_LIB
        NAMES cpuinfo
        PATHS ${XNNPACK_ROOT}/cpuinfo
    )

    if (XNNPACK_MAIN_INCLUDE AND PTHREADPOOL_INCLUDE AND CPUINFO_INCLUDE
        AND XNNPACK_LIB AND PTHREADPOOL_LIB AND CPUINFO_LIB AND XNNPACK_MICROKERNELS_LIB)

        set(XNNPACK_FOUND TRUE)
        message(STATUS "XNNPACK_MAIN_INCLUDE = ${XNNPACK_MAIN_INCLUDE}")
        message(STATUS "PTHREADPOOL_INCLUDE = ${PTHREADPOOL_INCLUDE}")
        message(STATUS "CPUINFO_INCLUDE     = ${CPUINFO_INCLUDE}")
        message(STATUS "XNNPACK_LIB         = ${XNNPACK_LIB}")
        message(STATUS "XNNPACK_MICROKERNELS_LIB = ${XNNPACK_MICROKERNELS_LIB}")
        message(STATUS "PTHREADPOOL_LIB     = ${PTHREADPOOL_LIB}")
        message(STATUS "CPUINFO_LIB         = ${CPUINFO_LIB}")

        message(STATUS "Using prebuilt XNNPACK at ${XNNPACK_ROOT}")

    else()
        message(FATAL_ERROR "XNNPACK_ROOT provided but required files not found")
    endif()
endif()

# --------------------------------------------------------
# If not found → FetchContent fallback
# --------------------------------------------------------
if (NOT XNNPACK_FOUND)
    message(WARNING "XNNPACK not found locally → FetchContent")

    include(FetchContent)

    FetchContent_Declare(
        XNNPACK
        GIT_REPOSITORY https://github.com/google/XNNPACK.git
        GIT_TAG master
    )

    # Pull XNNPACK + its third-party deps (pthreadpool, cpuinfo, fxdiv)
    FetchContent_MakeAvailable(XNNPACK)
endif()

# --------------------------------------------------------
# Your project
# --------------------------------------------------------

file(GLOB_RECURSE PROJECT_SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/dnn/src/*.cpp
)

add_executable(run_export
    main.cpp
    ${PROJECT_SOURCES}
)

# Optional debugging
# add_compile_definitions(XNN_LOG_LEVEL=5)
# target_compile_definitions(run_export PRIVATE ENABLE_TIMING)
# target_compile_definitions(run_export PRIVATE SAVE_OUTPUTS)

# --------------------------------------------------------
# Local project include directories
# --------------------------------------------------------

target_include_directories(run_export PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/dnn
    ${CMAKE_CURRENT_SOURCE_DIR}/dnn/include
    ${CMAKE_CURRENT_SOURCE_DIR}
)

# --------------------------------------------------------
# Prebuilt XNNPACK import
# --------------------------------------------------------

if (XNNPACK_FOUND)

    # Build clean include list — NO quoting, NO semicolons, NO whitespace.
    set(XNNPACK_INCLUDE_DIRS
        "${XNNPACK_MAIN_INCLUDE}"
        "${PTHREADPOOL_INCLUDE}"
        "${CPUINFO_INCLUDE}"
    )

    # Same for dependent libs
    set(XNNPACK_DEP_LIBS
        "${PTHREADPOOL_LIB}"
        "${CPUINFO_LIB}"
        "${XNNPACK_MICROKERNELS_LIB}"
    )

    add_library(XNNPACK STATIC IMPORTED)

    set_target_properties(XNNPACK PROPERTIES
        IMPORTED_LOCATION "${XNNPACK_LIB}"
        INTERFACE_INCLUDE_DIRECTORIES "${XNNPACK_INCLUDE_DIRS}"
        INTERFACE_LINK_LIBRARIES "${XNNPACK_DEP_LIBS}"
    )

endif()

# --------------------------------------------------------
# Link application
# --------------------------------------------------------

target_link_libraries(run_export PRIVATE
    XNNPACK
    pthread
)