# Copyright 2026 Google LLC
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

CMAKE_MINIMUM_REQUIRED(VERSION 3.15 FATAL_ERROR)

PROJECT(ynnpack C CXX)

INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/..")

SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED YES)
SET(CMAKE_CXX_EXTENSIONS NO)

IF(NOT MSVC)
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
ENDIF()

# ---[ Options.
OPTION(YNNPACK_BUILD_TESTS "Build YNNPACK unit tests" ${XNNPACK_BUILD_TESTS})
OPTION(YNNPACK_BUILD_BENCHMARKS "Build YNNPACK benchmarks" ${XNNPACK_BUILD_BENCHMARKS})

IF(YNNPACK_BUILD_TESTS)
  ENABLE_TESTING()
ENDIF()

# ---[ Architecture detection.
IF(NOT YNNPACK_TARGET_PROCESSOR)
  IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^i[3-7]86$")
    SET(YNNPACK_TARGET_PROCESSOR "x86")
  ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64")
    SET(YNNPACK_TARGET_PROCESSOR "x86_64")
  ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^armv[5-8]")
    SET(YNNPACK_TARGET_PROCESSOR "arm")
  ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
    SET(YNNPACK_TARGET_PROCESSOR "arm64")
  ELSE()
    SET(YNNPACK_TARGET_PROCESSOR "generic")
  ENDIF()
ENDIF()

MESSAGE(STATUS "YNNPACK target processor: ${YNNPACK_TARGET_PROCESSOR}")

# ---[ ISA Options.
SET(YNN_X86_DEFAULT OFF)
IF(YNNPACK_TARGET_PROCESSOR MATCHES "^x86")
  SET(YNN_X86_DEFAULT ON)
ENDIF()

SET(YNN_ARM_DEFAULT OFF)
IF(YNNPACK_TARGET_PROCESSOR MATCHES "^arm")
  SET(YNN_ARM_DEFAULT ON)
ENDIF()

SET(YNN_ARM64_DEFAULT OFF)
IF(YNNPACK_TARGET_PROCESSOR STREQUAL "arm64")
  SET(YNN_ARM64_DEFAULT ON)
ENDIF()

# x86
OPTION(YNN_ENABLE_X86_SSE "Enable x86 SSE" ${YNN_X86_DEFAULT})
OPTION(YNN_ENABLE_X86_SSE2 "Enable x86 SSE2" ${YNN_ENABLE_X86_SSE})
OPTION(YNN_ENABLE_X86_SSE2_FMA "Enable x86 SSE2+FMA" ${YNN_ENABLE_X86_SSE2})
OPTION(YNN_ENABLE_X86_SSSE3 "Enable x86 SSSE3" ${YNN_ENABLE_X86_SSE})
OPTION(YNN_ENABLE_X86_SSE41 "Enable x86 SSE4.1" ${YNN_ENABLE_X86_SSE})
OPTION(YNN_ENABLE_X86_AVX "Enable x86 AVX" ${YNN_ENABLE_X86_SSE})
OPTION(YNN_ENABLE_X86_F16C "Enable x86 F16C" ${YNN_ENABLE_X86_AVX})
OPTION(YNN_ENABLE_X86_AVX2 "Enable x86 AVX2" ${YNN_ENABLE_X86_AVX})
OPTION(YNN_ENABLE_X86_FMA3 "Enable x86 FMA3" ${YNN_ENABLE_X86_AVX})
OPTION(YNN_ENABLE_X86_AVX512 "Enable x86 AVX512" ${YNN_ENABLE_X86_AVX})

IF(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND YNN_ENABLE_X86_AVX512)
  SET(YNN_X86_AVX512BF16_DEFAULT ON)
ELSE()
  SET(YNN_X86_AVX512BF16_DEFAULT OFF)
ENDIF()
OPTION(YNN_ENABLE_X86_AVX512BF16 "Enable x86 AVX512BF16" ${YNN_X86_AVX512BF16_DEFAULT})
OPTION(YNN_ENABLE_X86_AVX512FP16 "Enable x86 AVX512FP16" ${YNN_ENABLE_X86_AVX512})
OPTION(YNN_ENABLE_X86_AVX512VNNI "Enable x86 AVX512VNNI" ${YNN_ENABLE_X86_AVX512})

SET(YNN_X86_AMX_DEFAULT OFF)
IF(YNNPACK_TARGET_PROCESSOR STREQUAL "x86_64")
  SET(YNN_X86_AMX_DEFAULT ON)
ENDIF()
OPTION(YNN_ENABLE_X86_AMX "Enable x86 AMX" ${YNN_X86_AMX_DEFAULT})
OPTION(YNN_ENABLE_X86_AMXBF16 "Enable x86 AMXBF16" ${YNN_ENABLE_X86_AMX})
OPTION(YNN_ENABLE_X86_AMXFP16 "Enable x86 AMXFP16" ${YNN_ENABLE_X86_AMX})
OPTION(YNN_ENABLE_X86_AMXINT8 "Enable x86 AMXINT8" ${YNN_ENABLE_X86_AMX})

# Derived x86
IF(YNN_ENABLE_X86_F16C AND YNN_ENABLE_X86_FMA3)
  SET(YNN_X86_F16C_FMA3_DEFAULT ON)
ELSE()
  SET(YNN_X86_F16C_FMA3_DEFAULT OFF)
ENDIF()
OPTION(YNN_ENABLE_X86_F16C_FMA3 "Enable x86 F16C+FMA3" ${YNN_X86_F16C_FMA3_DEFAULT})

IF(YNN_ENABLE_X86_AVX2 AND YNN_ENABLE_X86_FMA3)
  SET(YNN_X86_AVX2_FMA3_DEFAULT ON)
ELSE()
  SET(YNN_X86_AVX2_FMA3_DEFAULT OFF)
ENDIF()
OPTION(YNN_ENABLE_X86_AVX2_FMA3 "Enable x86 AVX2+FMA3" ${YNN_X86_AVX2_FMA3_DEFAULT})

# ARM
OPTION(YNN_ENABLE_ARM_NEON "Enable ARM NEON" ${YNN_ARM_DEFAULT})
OPTION(YNN_ENABLE_ARM_NEONDOT "Enable ARM NEONDOT" ${YNN_ENABLE_ARM_NEON})
OPTION(YNN_ENABLE_ARM_NEONFMA "Enable ARM NEONFMA" ${YNN_ENABLE_ARM_NEON})
OPTION(YNN_ENABLE_ARM_NEONFP16 "Enable ARM NEONFP16" ${YNN_ENABLE_ARM_NEON})
OPTION(YNN_ENABLE_ARM_NEONFP16ARITH "Enable ARM NEONFP16ARITH" ${YNN_ENABLE_ARM_NEON})
OPTION(YNN_ENABLE_ARM_NEONBF16 "Enable ARM NEONBF16" ${YNN_ENABLE_ARM_NEON})

OPTION(YNN_ENABLE_ARM64 "Enable ARM64" ${YNN_ARM64_DEFAULT})
OPTION(YNN_ENABLE_ARM64_NEONI8MM "Enable ARM64 NEONI8MM" ${YNN_ENABLE_ARM64})
OPTION(YNN_ENABLE_ARM64_NEON "Enable ARM64 NEON" ${YNN_ENABLE_ARM64})
OPTION(YNN_ENABLE_ARM64_NEONFP8 "Enable ARM64 NEONFP8" OFF)
OPTION(YNN_ENABLE_ARM64_NEONFP8DOT4 "Enable ARM64 NEONFP8DOT4" OFF)
OPTION(YNN_ENABLE_ARM64_SME "Enable ARM64 SME" ${YNN_ENABLE_ARM64})
OPTION(YNN_ENABLE_ARM64_SME2 "Enable ARM64 SME2" ${YNN_ENABLE_ARM64_SME})

IF(YNN_ENABLE_ARM64 AND NOT APPLE)
  SET(YNN_ARM64_SVE_DEFAULT ON)
ELSE()
  SET(YNN_ARM64_SVE_DEFAULT OFF)
ENDIF()
OPTION(YNN_ENABLE_ARM64_SVE "Enable ARM64 SVE" ${YNN_ARM64_SVE_DEFAULT})

# Others
SET(YNN_HEXAGON_DEFAULT OFF)
IF(YNNPACK_TARGET_PROCESSOR STREQUAL "hexagon")
  SET(YNN_HEXAGON_DEFAULT ON)
ENDIF()
OPTION(YNN_ENABLE_HVX "Enable Hexagon HVX" ${YNN_HEXAGON_DEFAULT})

SET(YNN_WASM_DEFAULT OFF)
IF(YNNPACK_TARGET_PROCESSOR STREQUAL "wasm")
  SET(YNN_WASM_DEFAULT ON)
ENDIF()
OPTION(YNN_ENABLE_WASM_SIMD128 "Enable Wasm SIMD128" ${YNN_WASM_DEFAULT})

OPTION(YNN_ENABLE_CPUINFO "Enable cpuinfo" ON)

# ---[ Dependencies.
IF(NOT TARGET slinky_base)
  IF(XNNPACK_USE_SYSTEM_LIBS)
    FIND_PACKAGE(slinky REQUIRED)
  ELSE()
    SET(SLINKY_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
    IF(NOT DEFINED SLINKY_SOURCE_DIR)
      MESSAGE(STATUS "Downloading slinky to ${CMAKE_BINARY_DIR}/slinky-source (define SLINKY_SOURCE_DIR to avoid it)")
      CONFIGURE_FILE(cmake/DownloadSlinky.cmake "${CMAKE_BINARY_DIR}/slinky-download/CMakeLists.txt")
      EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
        WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/slinky-download")
      EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
        WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/slinky-download")
      SET(SLINKY_SOURCE_DIR "${CMAKE_BINARY_DIR}/slinky-source" CACHE STRING "slinky source directory")
    ENDIF()
    # Temporarily disable testing while adding slinky to avoid including its tests.
    INCLUDE_DIRECTORIES("${SLINKY_SOURCE_DIR}")
    ADD_SUBDIRECTORY("${SLINKY_SOURCE_DIR}" "${CMAKE_BINARY_DIR}/slinky")
  ENDIF()
ENDIF()

# ---[ Includes.
INCLUDE_DIRECTORIES(include)
INCLUDE_DIRECTORIES(.)

# ---[ Subdirectories.
ADD_SUBDIRECTORY(base)
ADD_SUBDIRECTORY(kernels)
ADD_SUBDIRECTORY(subgraph)
ADD_SUBDIRECTORY(xnnpack)

# ---[ Main library.
ADD_LIBRARY(ynnpack INTERFACE)
TARGET_INCLUDE_DIRECTORIES(ynnpack INTERFACE include)
TARGET_LINK_LIBRARIES(ynnpack INTERFACE ynnpack_subgraph)
