# Copyright (c) XXX, Inc. and its affiliates.
# All rights reserved.
#
# 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.5 FATAL_ERROR)

INCLUDE(GNUInstallDirs)

# ---[ Project and semantic versioning.
PROJECT(QNNPACK C CXX ASM)

# ---[ Options.
OPTION(QNNPACK_CUSTOM_THREADPOOL "Build QNNPACK for custom thread pool" OFF)
SET(QNNPACK_LIBRARY_TYPE "default" CACHE STRING "Type of library (shared, static, or default) to build")
SET_PROPERTY(CACHE QNNPACK_LIBRARY_TYPE PROPERTY STRINGS default static shared)
OPTION(QNNPACK_BUILD_TESTS "Build QNNPACK unit tests" ON)
OPTION(QNNPACK_BUILD_BENCHMARKS "Build QNNPACK benchmarks" ON)

# ---[ CMake options
IF(QNNPACK_BUILD_TESTS)
  ENABLE_TESTING()
ENDIF()

MACRO(NNPACK_TARGET_ENABLE_CXX11 target)
  IF(${CMAKE_VERSION} VERSION_LESS "3.1")
    IF(NOT MSVC)
      TARGET_COMPILE_OPTIONS(${target} PRIVATE -std=gnu++11)
    ENDIF()
  ELSE()
    SET_TARGET_PROPERTIES(${target} PROPERTIES
      CXX_STANDARD 11
      CXX_STANDARD_REQUIRED YES
      CXX_EXTENSIONS YES)
  ENDIF()
ENDMACRO()

# ---[ Build flags
IF(NOT CMAKE_SYSTEM_PROCESSOR)
  IF(NOT IOS)
    MESSAGE(WARNING "CMAKE_SYSTEM_PROCESSOR is not defined, automatic configuration may choose suboptimal options")
  ENDIF()
ELSEIF(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|x86_64|armv5te|armv7-a|armv7l|aarch64)$")
  MESSAGE(FATAL_ERROR "Unrecognized CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
ENDIF()

IF(NOT CMAKE_SYSTEM_NAME)
  MESSAGE(FATAL_ERROR "CMAKE_SYSTEM_NAME not defined")
ELSEIF(NOT CMAKE_SYSTEM_NAME MATCHES "^(Darwin|Linux|Android)$")
  MESSAGE(FATAL_ERROR "Unrecognized CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
ENDIF()

# ---[ Download deps
SET(CONFU_DEPENDENCIES_SOURCE_DIR "${CMAKE_SOURCE_DIR}/deps"
  CACHE PATH "Confu-style dependencies source directory")
SET(CONFU_DEPENDENCIES_BINARY_DIR "${CMAKE_BINARY_DIR}/deps"
  CACHE PATH "Confu-style dependencies binary directory")

IF(NOT DEFINED CLOG_SOURCE_DIR)
  SET(CLOG_SOURCE_DIR "${PROJECT_SOURCE_DIR}/deps/clog")
ENDIF()

IF(NOT DEFINED CPUINFO_SOURCE_DIR)
  MESSAGE(STATUS "Downloading cpuinfo to ${CONFU_DEPENDENCIES_SOURCE_DIR}/cpuinfo (define CPUINFO_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadCpuinfo.cmake "${CONFU_DEPENDENCIES_BINARY_DIR}/cpuinfo-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/cpuinfo-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/cpuinfo-download")
  SET(CPUINFO_SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/cpuinfo" CACHE STRING "cpuinfo source directory")
ENDIF()

IF(NOT DEFINED FP16_SOURCE_DIR)
  MESSAGE(STATUS "Downloading FP16 to ${CONFU_DEPENDENCIES_SOURCE_DIR}/fp16 (define FP16_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadFP16.cmake "${CONFU_DEPENDENCIES_BINARY_DIR}/fp16-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/fp16-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/fp16-download")
  SET(FP16_SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/fp16" CACHE STRING "FP16 source directory")
ENDIF()

IF(NOT DEFINED FXDIV_SOURCE_DIR)
  MESSAGE(STATUS "Downloading FXdiv to ${CONFU_DEPENDENCIES_SOURCE_DIR}/fxdiv (define FXDIV_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadFXdiv.cmake "${CONFU_DEPENDENCIES_BINARY_DIR}/fxdiv-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/fxdiv-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/fxdiv-download")
  SET(FXDIV_SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/fxdiv" CACHE STRING "FXdiv source directory")
ENDIF()

IF(NOT DEFINED PSIMD_SOURCE_DIR)
  MESSAGE(STATUS "Downloading PSimd to ${CONFU_DEPENDENCIES_SOURCE_DIR}/psimd (define PSIMD_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadPSimd.cmake "${CONFU_DEPENDENCIES_BINARY_DIR}/psimd-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/psimd-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/psimd-download")
  SET(PSIMD_SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/psimd" CACHE STRING "PSimd source directory")
ENDIF()

IF(NOT DEFINED PTHREADPOOL_SOURCE_DIR)
  MESSAGE(STATUS "Downloading pthreadpool to ${CONFU_DEPENDENCIES_SOURCE_DIR}/pthreadpool (define PTHREADPOOL_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadPThreadPool.cmake "${CONFU_DEPENDENCIES_BINARY_DIR}/pthreadpool-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/pthreadpool-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/pthreadpool-download")
  SET(PTHREADPOOL_SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/pthreadpool" CACHE STRING "pthreadpool source directory")
ENDIF()

IF(QNNPACK_BUILD_TESTS AND NOT DEFINED GOOGLETEST_SOURCE_DIR)
  MESSAGE(STATUS "Downloading Google Test to ${CONFU_DEPENDENCIES_SOURCE_DIR}/googletest (define GOOGLETEST_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadGoogleTest.cmake "${CONFU_DEPENDENCIES_BINARY_DIR}/googletest-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/googletest-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/googletest-download")
  SET(GOOGLETEST_SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/googletest" CACHE STRING "Google Test source directory")
ENDIF()

IF(QNNPACK_BUILD_BENCHMARKS AND NOT DEFINED GOOGLEBENCHMARK_SOURCE_DIR)
  MESSAGE(STATUS "Downloading Google Benchmark to ${CONFU_DEPENDENCIES_SOURCE_DIR}/googlebenchmark (define GOOGLEBENCHMARK_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadGoogleBenchmark.cmake "${CONFU_DEPENDENCIES_BINARY_DIR}/googlebenchmark-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/googlebenchmark-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CONFU_DEPENDENCIES_BINARY_DIR}/googlebenchmark-download")
  SET(GOOGLEBENCHMARK_SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/googlebenchmark" CACHE STRING "Google Benchmark source directory")
ENDIF()

# ---[ NNPACK library
SET(QNNPACK_INIT_SRCS src/init.c)
SET(QNNPACK_OPERATOR_SRCS
  src/convolution.c
  src/deconvolution.c
  src/fully-connected.c)

SET(QNNPACK_PSIMD_UKERNELS
  src/sgemm/6x8-psimd.c)

SET(QNNPACK_ARM_NEON_UKERNELS
  src/q8gemm/4x8-neon.c
  src/q8gemm/4x-sumrows-neon.c
  src/q8gemm/4x8c2-xzp-neon.c
  src/q8gemm/8x8-neon.c
  src/q8gemm/6x4-neon.c
  src/q8conv/4x8-neon.c
  src/q8conv/8x8-neon.c
  src/q8dw/9c8-neon.c
  src/sgemm/5x8-neon.c
  src/sgemm/6x8-neon.c)

SET(QNNPACK_AARCH32_ASM_UKERNELS
  src/q8gemm/4x8-aarch32-neon.S
  src/q8gemm/4x8c2-xzp-aarch32-neon.S
  src/q8conv/4x8-aarch32-neon.S
  src/hgemm/8x8-aarch32-neonfp16arith.S)

SET(QNNPACK_AARCH64_ASM_UKERNELS
  src/q8gemm/8x8-aarch64-neon.S
  src/q8conv/8x8-aarch64-neon.S)

SET(QNNPACK_X86_SSE2_UKERNELS
  src/q8gemm/2x4c8-sse2.c
  src/q8gemm/4x4c2-sse2.c
  src/q8conv/4x4c2-sse2.c
  src/q8dw/9c8-sse2.c)

SET(QNNPACK_UKERNELS ${QNNPACK_PSIMD_UKERNELS})
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "armv")
  LIST(APPEND QNNPACK_UKERNELS ${QNNPACK_ARM_NEON_UKERNELS})
  LIST(APPEND QNNPACK_UKERNELS ${QNNPACK_AARCH32_ASM_UKERNELS})
ENDIF()
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)$")
  LIST(APPEND QNNPACK_UKERNELS ${QNNPACK_ARM_NEON_UKERNELS})
  LIST(APPEND QNNPACK_UKERNELS ${QNNPACK_AARCH64_ASM_UKERNELS})
ENDIF()
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|AMD64|x86_64)$")
  LIST(APPEND QNNPACK_UKERNELS ${QNNPACK_X86_SSE2_UKERNELS})
ENDIF()

IF(QNNPACK_LIBRARY_TYPE STREQUAL "default")
  ADD_LIBRARY(qnnpack ${QNNPACK_INIT_SRCS} ${QNNPACK_OPERATOR_SRCS} ${QNNPACK_UKERNELS})
ELSEIF(QNNPACK_LIBRARY_TYPE STREQUAL "shared")
  ADD_LIBRARY(qnnpack SHARED ${QNNPACK_INIT_SRCS} ${QNNPACK_OPERATOR_SRCS} ${QNNPACK_UKERNELS})
ELSEIF(QNNPACK_LIBRARY_TYPE STREQUAL "static")
  ADD_LIBRARY(qnnpack STATIC ${QNNPACK_INIT_SRCS} ${QNNPACK_OPERATOR_SRCS} ${QNNPACK_UKERNELS})
ELSE()
  MESSAGE(FATAL_ERROR "Unsupported NNPACK library type \"${QNNPACK_LIBRARY_TYPE}\". Must be \"static\", \"shared\", or \"default\"")
ENDIF()
SET_TARGET_PROPERTIES(qnnpack PROPERTIES
  C_STANDARD 99
  C_EXTENSIONS YES)
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "armv")
  SET_PROPERTY(SOURCE ${QNNPACK_ARM_NEON_UKERNELS} APPEND_STRING PROPERTY COMPILE_FLAGS " -marm -mfpu=neon ")
ENDIF()
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|AMD64|x86_64)$")
  SET_PROPERTY(SOURCE ${QNNPACK_X86_SSE2_UKERNELS} APPEND_STRING PROPERTY COMPILE_FLAGS " -msse2 ")
ENDIF()
SET_PROPERTY(SOURCE ${QNNPACK_INIT_SRCS} APPEND_STRING PROPERTY COMPILE_FLAGS " -Os ")
IF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
  SET_PROPERTY(SOURCE ${QNNPACK_OPERATOR_SRCS} APPEND_STRING PROPERTY COMPILE_FLAGS " -O2 ")
ENDIF()
TARGET_INCLUDE_DIRECTORIES(qnnpack PUBLIC include)
TARGET_INCLUDE_DIRECTORIES(qnnpack PRIVATE src)
SET_TARGET_PROPERTIES(qnnpack PROPERTIES PUBLIC_HEADER include/qnnpack.h)

# ---[ Configure clog
IF(NOT TARGET clog)
  SET(CLOG_BUILD_TESTS OFF CACHE BOOL "")
  SET(CLOG_RUNTIME_TYPE "${CPUINFO_RUNTIME_TYPE}" CACHE STRING "")
  ADD_SUBDIRECTORY(
    "${CLOG_SOURCE_DIR}"
    "${CONFU_DEPENDENCIES_BINARY_DIR}/clog")
  # We build static version of clog but a dynamic library may indirectly depend on it
  SET_PROPERTY(TARGET clog PROPERTY POSITION_INDEPENDENT_CODE ON)
ENDIF()
TARGET_LINK_LIBRARIES(qnnpack PRIVATE clog)

# ---[ Configure cpuinfo
IF(NOT TARGET cpuinfo)
  SET(CPUINFO_BUILD_TOOLS OFF CACHE BOOL "")
  SET(CPUINFO_BUILD_UNIT_TESTS OFF CACHE BOOL "")
  SET(CPUINFO_BUILD_MOCK_TESTS OFF CACHE BOOL "")
  SET(CPUINFO_BUILD_BENCHMARKS OFF CACHE BOOL "")
  ADD_SUBDIRECTORY(
    "${CPUINFO_SOURCE_DIR}"
    "${CONFU_DEPENDENCIES_BINARY_DIR}/cpuinfo")
ENDIF()
TARGET_LINK_LIBRARIES(qnnpack PRIVATE cpuinfo)

# ---[ Configure pthreadpool
IF(NOT TARGET pthreadpool)
  SET(PTHREADPOOL_BUILD_TESTS OFF CACHE BOOL "")
  SET(PTHREADPOOL_BUILD_BENCHMARKS OFF CACHE BOOL "")
  ADD_SUBDIRECTORY(
    "${PTHREADPOOL_SOURCE_DIR}"
    "${CONFU_DEPENDENCIES_BINARY_DIR}/pthreadpool")
ENDIF()
IF(QNNPACK_CUSTOM_THREADPOOL)
  # Depend on pthreadpool interface, but not on implementation.
  # This is used when NNPACK user (e.g. Caffe2) provides its own threadpool implementation.
  TARGET_LINK_LIBRARIES(qnnpack PUBLIC pthreadpool_interface)
ELSE()
  TARGET_LINK_LIBRARIES(qnnpack PUBLIC pthreadpool)
ENDIF()

# ---[ Configure FXdiv
IF(NOT TARGET fxdiv)
  SET(FXDIV_BUILD_TESTS OFF CACHE BOOL "")
  SET(FXDIV_BUILD_BENCHMARKS OFF CACHE BOOL "")
  ADD_SUBDIRECTORY(
    "${FXDIV_SOURCE_DIR}"
    "${CONFU_DEPENDENCIES_BINARY_DIR}/fxdiv")
ENDIF()
TARGET_LINK_LIBRARIES(qnnpack PRIVATE fxdiv)

# ---[ Configure psimd
IF(NOT TARGET psimd)
  ADD_SUBDIRECTORY(
    "${PSIMD_SOURCE_DIR}"
    "${CONFU_DEPENDENCIES_BINARY_DIR}/psimd")
ENDIF()
TARGET_LINK_LIBRARIES(qnnpack PRIVATE psimd)

# ---[ Configure FP16
IF(NOT TARGET fp16)
  SET(FP16_BUILD_TESTS OFF CACHE BOOL "")
  SET(FP16_BUILD_BENCHMARKS OFF CACHE BOOL "")
  ADD_SUBDIRECTORY(
    "${FP16_SOURCE_DIR}"
    "${CONFU_DEPENDENCIES_BINARY_DIR}/fp16")
ENDIF()
TARGET_LINK_LIBRARIES(qnnpack PRIVATE fp16)

INSTALL(TARGETS qnnpack
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

# ---[ QNNPACK unit tests
IF(QNNPACK_BUILD_TESTS)
  # ---[ Build google test
  IF(NOT TARGET gtest)
    SET(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
    ADD_SUBDIRECTORY(
      "${GOOGLETEST_SOURCE_DIR}"
      "${CONFU_DEPENDENCIES_BINARY_DIR}/googletest")
  ENDIF()

  # ---[ Build unit tests for high-level functionality
  ADD_EXECUTABLE(convolution-test test/convolution.cc)
  SET_TARGET_PROPERTIES(convolution-test PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(convolution-test PRIVATE src test)
  TARGET_LINK_LIBRARIES(convolution-test PRIVATE qnnpack cpuinfo gtest gtest_main)
  ADD_TEST(convolution-test convolution-test)

  ADD_EXECUTABLE(deconvolution-test test/deconvolution.cc)
  SET_TARGET_PROPERTIES(deconvolution-test PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(deconvolution-test PRIVATE src test)
  TARGET_LINK_LIBRARIES(deconvolution-test PRIVATE qnnpack cpuinfo gtest gtest_main)
  ADD_TEST(deconvolution-test deconvolution-test)

  ADD_EXECUTABLE(fully-connected-test test/fully-connected.cc)
  SET_TARGET_PROPERTIES(fully-connected-test PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(fully-connected-test PRIVATE src test)
  TARGET_LINK_LIBRARIES(fully-connected-test PRIVATE qnnpack cpuinfo gtest gtest_main)
  ADD_TEST(fully-connected-test fully-connected-test)

  # ---[ Build unit tests for micro-kernels
  ADD_EXECUTABLE(q8gemm-test test/q8gemm.cc)
  SET_TARGET_PROPERTIES(q8gemm-test PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(q8gemm-test PRIVATE src test)
  TARGET_LINK_LIBRARIES(q8gemm-test PRIVATE qnnpack cpuinfo fp16 gtest gtest_main)
  ADD_TEST(q8gemm-test q8gemm-test)

  ADD_EXECUTABLE(q8conv-test test/q8conv.cc)
  SET_TARGET_PROPERTIES(q8conv-test PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(q8conv-test PRIVATE src test)
  TARGET_LINK_LIBRARIES(q8conv-test PRIVATE qnnpack cpuinfo fp16 gtest gtest_main)
  ADD_TEST(q8conv-test q8conv-test)

  ADD_EXECUTABLE(q8dw-test test/q8dw.cc)
  SET_TARGET_PROPERTIES(q8dw-test PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(q8dw-test PRIVATE src test)
  TARGET_LINK_LIBRARIES(q8dw-test PRIVATE qnnpack cpuinfo fp16 gtest gtest_main)
  ADD_TEST(q8dw-test q8dw-test)

  ADD_EXECUTABLE(hgemm-test test/hgemm.cc)
  SET_TARGET_PROPERTIES(hgemm-test PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(hgemm-test PRIVATE src test)
  TARGET_LINK_LIBRARIES(hgemm-test PRIVATE qnnpack cpuinfo fp16 gtest gtest_main)
  ADD_TEST(hgemm-test hgemm-test)

  ADD_EXECUTABLE(sgemm-test test/sgemm.cc)
  SET_TARGET_PROPERTIES(sgemm-test PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(sgemm-test PRIVATE src test)
  TARGET_LINK_LIBRARIES(sgemm-test PRIVATE qnnpack cpuinfo fp16 gtest gtest_main)
  ADD_TEST(sgemm-test sgemm-test)
ENDIF()

# ---[ QNNPACK micro-benchmarks
IF(QNNPACK_BUILD_BENCHMARKS)
  # ---[ Build google benchmark
  IF(NOT TARGET benchmark)
    SET(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "")
    ADD_SUBDIRECTORY(
      "${GOOGLEBENCHMARK_SOURCE_DIR}"
      "${CONFU_DEPENDENCIES_BINARY_DIR}/googlebenchmark")
  ENDIF()

  ADD_EXECUTABLE(convolution-bench bench/convolution.cc)
  SET_TARGET_PROPERTIES(convolution-bench PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_LINK_LIBRARIES(convolution-bench PRIVATE qnnpack benchmark)

  ADD_EXECUTABLE(q8gemm-bench bench/q8gemm.cc)
  SET_TARGET_PROPERTIES(q8gemm-bench PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(q8gemm-bench PRIVATE src)
  TARGET_COMPILE_DEFINITIONS(q8gemm-bench PRIVATE QNNPACK_BENCHMARK_GEMMLOWP=0)
  TARGET_LINK_LIBRARIES(q8gemm-bench PRIVATE qnnpack cpuinfo fp16 benchmark)

  ADD_EXECUTABLE(hgemm-bench bench/hgemm.cc)
  SET_TARGET_PROPERTIES(hgemm-bench PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(hgemm-bench PRIVATE src)
  TARGET_LINK_LIBRARIES(hgemm-bench PRIVATE qnnpack cpuinfo fp16 benchmark)

  ADD_EXECUTABLE(sgemm-bench bench/sgemm.cc)
  SET_TARGET_PROPERTIES(sgemm-bench PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO)
  TARGET_INCLUDE_DIRECTORIES(sgemm-bench PRIVATE src)
  TARGET_LINK_LIBRARIES(sgemm-bench PRIVATE qnnpack cpuinfo benchmark)
ENDIF()
