# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# License); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2021, OPEN AI LAB
# Author: lswang@openailab.com
#

# set target name
IF (NOT DEFINED TENGINE_LITE_NAME)
    SET (TENGINE_LITE_NAME ${CMAKE_PROJECT_NAME} CACHE INTERNAL "" FORCE)
ENDIF()


# clear all var
UNSET (TENGINE_C_API_SOURCE)
UNSET (TENGINE_COMMON_DEFINES)
UNSET (TENGINE_COMMON_OPTIONS)
UNSET (TENGINE_COMMON_LINKER_OPTIONS)
UNSET (TENGINE_COMMON_LINK_LIBRARIES)
UNSET (TENGINE_SOURCE_FILES)
UNSET (TENGINE_HEADER_PATH)
UNSET (TENGINE_LINK_PATH)
UNSET (TENGINE_COMPILER_DEFINES)
UNSET (TENGINE_COMPILER_OPTIONS)
UNSET (TENGINE_LINKER_OPTIONS)
UNSET (TENGINE_LINK_LIBRARIES)
UNSET (TENGINE_ENABLED_OPENMP)


# common defines and options
IF (TENGINE_SYSTEM_MACOS)
    LIST (APPEND TENGINE_COMMON_DEFINES "MACOS")
ENDIF()

IF (OHOS)
    LIST (APPEND TENGINE_COMMON_DEFINES "_OHOS_")

    # OHOS 3.0.0.80 patch for ASM language
    IF (NOT DEFINED CMAKE_ASM_COMPILER_TARGET)
        SET (CMAKE_ASM_COMPILER_TARGET ${OHOS_LLVM})
    ENDIF()

    IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
        SET (CMAKE_BUILD_WITH_INSTALL_RPATH ON)
    ENDIF()
ENDIF()

#
IF (TENGINE_COMPILER_GCC OR TENGINE_COMPILER_CLANG)
    IF (${TENGINE_FULL_CHECK})
        # warning local redefined same name variable
        LIST (APPEND TENGINE_COMMON_OPTIONS "-Wshadow")
        LIST (APPEND TENGINE_COMMON_OPTIONS "-Wunreachable-code")
        #LIST (APPEND TENGINE_COMMON_OPTIONS "-Werror")

        # show all warnings
        LIST (APPEND TENGINE_COMMON_OPTIONS "-Wall")

        # more warning details
        LIST (APPEND TENGINE_COMMON_OPTIONS "-Wextra")

        # warning all unused part
        LIST (APPEND TENGINE_COMMON_OPTIONS "-Wunknown-pragmas")
        LIST (APPEND TENGINE_COMMON_OPTIONS "-Wunused-label")
        LIST (APPEND TENGINE_COMMON_OPTIONS "-Wunused-value")
        LIST (APPEND TENGINE_COMMON_OPTIONS "-Wunused-function")
        LIST (APPEND TENGINE_COMMON_OPTIONS "-Wunused-variable")

        # check memory issues
        LIST (APPEND TENGINE_COMMON_OPTIONS "-fsanitize=address")
        LIST (APPEND TENGINE_COMMON_OPTIONS "-fno-omit-frame-pointer")

        LIST (APPEND TENGINE_COMMON_LINKER_OPTIONS "-fsanitize=address")
    ENDIF()

    IF ((${CMAKE_BUILD_TYPE} MATCHES "Debug") OR (${CMAKE_BUILD_TYPE} MATCHES "DEBUG"))
        LIST (APPEND TENGINE_COMMON_OPTIONS "-g")
        LIST (APPEND TENGINE_COMMON_OPTIONS "-O0")
    ELSEIF (TENGINE_GENERATE_DEBUG_SYMBOL)
        LIST (APPEND TENGINE_COMMON_OPTIONS "-g")
    ENDIF()

    IF (${TENGINE_COVERAGE})
        LIST (APPEND TENGINE_COMMON_OPTIONS "-fprofile-arcs")
        LIST (APPEND TENGINE_COMMON_OPTIONS "-ftest-coverage")

        LIST (APPEND TENGINE_COMMON_LINK_LIBRARIES -coverage)
        LIST (APPEND TENGINE_COMMON_LINK_LIBRARIES -lgcov)
    ENDIF()

    IF (ANDROID)
        LIST (APPEND TENGINE_COMMON_LINK_LIBRARIES android)
        LIST (APPEND TENGINE_COMMON_LINK_LIBRARIES log)
    ELSEIF (OHOS)
        LIST (APPEND TENGINE_COMMON_LINK_LIBRARIES dl)
        LIST (APPEND TENGINE_COMMON_LINK_LIBRARIES m)
    ELSEIF (NOT MSVC)
        LIST (APPEND TENGINE_COMMON_LINK_LIBRARIES dl)
        LIST (APPEND TENGINE_COMMON_LINK_LIBRARIES m)
    ENDIF()
ENDIF()


# configure building
CONFIGURE_FILE(defines.h.in ${CMAKE_CURRENT_BINARY_DIR}/defines.h)


# add configurable module
ADD_SUBDIRECTORY (device)                                   # each device as a executable backend
ADD_SUBDIRECTORY (operator)                                 # operator framework and prototype
ADD_SUBDIRECTORY (scheduler)                                # base and advanced scheduler for different backend
ADD_SUBDIRECTORY (serializer)                               # multi-framework transform support


# collect all other source files
FILE (GLOB TENGINE_C_API_SOURCE     "${CMAKE_SOURCE_DIR}/source/api/*.c")
FILE (GLOB TENGINE_CXX_API_SOURCE   "${CMAKE_SOURCE_DIR}/source/api/*.cc")
AUX_SOURCE_DIRECTORY("${CMAKE_SOURCE_DIR}/source/executer"  TENGINE_EXECUTER_SOURCE)
#AUX_SOURCE_DIRECTORY("${CMAKE_SOURCE_DIR}/source/exporter"  TENGINE_EXPORTER_SOURCE)
AUX_SOURCE_DIRECTORY("${CMAKE_SOURCE_DIR}/source/graph"     TENGINE_GRAPH_SOURCE)
AUX_SOURCE_DIRECTORY("${CMAKE_SOURCE_DIR}/source/module"    TENGINE_MODULE_SOURCE)
AUX_SOURCE_DIRECTORY("${CMAKE_SOURCE_DIR}/source/optimizer" TENGINE_OPTIMIZER_SOURCE)
AUX_SOURCE_DIRECTORY("${CMAKE_SOURCE_DIR}/source/system"    TENGINE_SYSTEM_SOURCE)
AUX_SOURCE_DIRECTORY("${CMAKE_SOURCE_DIR}/source/utility"   TENGINE_UTILITY_SOURCE)


# add to src group for IDE
TENGINE_SOURCE_GROUP ("api"         ${TENGINE_CXX_API_SOURCE})
TENGINE_SOURCE_GROUP ("executer"    ${TENGINE_EXECUTER_SOURCE})
#TENGINE_SOURCE_GROUP ("exporter"    ${TENGINE_EXPORTER_SOURCE})
TENGINE_SOURCE_GROUP ("graph"       ${TENGINE_GRAPH_SOURCE})
TENGINE_SOURCE_GROUP ("module"      ${TENGINE_MODULE_SOURCE})
TENGINE_SOURCE_GROUP ("optimizer"   ${TENGINE_OPTIMIZER_SOURCE})
TENGINE_SOURCE_GROUP ("system"      ${TENGINE_SYSTEM_SOURCE})
TENGINE_SOURCE_GROUP ("utility"     ${TENGINE_UTILITY_SOURCE})


# collect all source files
IF (TENGINE_BUILD_CPP_API)
    LIST (APPEND TENGINE_SOURCE_FILES ${TENGINE_CXX_API_SOURCE})
ELSE()
    LIST (APPEND TENGINE_SOURCE_FILES ${TENGINE_C_API_SOURCE})
ENDIF()
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_DEVICE_SOURCE})
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_OPERATOR_SOURCE})
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_SCHEDULER_SOURCE})
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_SERIALIZER_SOURCE})
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_EXECUTER_SOURCE})
#LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_EXPORTER_SOURCE})
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_GRAPH_SOURCE})
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_MODULE_SOURCE})
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_OPTIMIZER_SOURCE})
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_SYSTEM_SOURCE})
LIST (APPEND TENGINE_SOURCE_FILES       ${TENGINE_UTILITY_SOURCE})


# add header file searching path
LIST (APPEND TENGINE_HEADER_PATH        "${CMAKE_SOURCE_DIR}/source")
LIST (APPEND TENGINE_HEADER_PATH        "${CMAKE_BINARY_DIR}/source")
LIST (APPEND TENGINE_HEADER_PATH        ${TENGINE_DEVICE_HEADER_PATH})
LIST (APPEND TENGINE_HEADER_PATH        ${TENGINE_OP_HEADER_PATH})
LIST (APPEND TENGINE_HEADER_PATH        ${TENGINE_SERIALIZER_HEADER_PATH})


#
LIST (APPEND TENGINE_LINK_PATH          ${TENGINE_DEVICE_LINK_PATH})


# add compiler defines
LIST (APPEND TENGINE_COMPILER_DEFINES   ${TENGINE_COMMON_DEFINES})
LIST (APPEND TENGINE_COMPILER_DEFINES   ${TENGINE_DEVICE_COMPILER_DEFINES})
LIST (APPEND TENGINE_COMPILER_DEFINES   ${TENGINE_OPERATOR_COMPILER_DEFINES})
LIST (APPEND TENGINE_COMPILER_DEFINES   ${TENGINE_SCHEDULER_COMPILER_DEFINES})
LIST (APPEND TENGINE_COMPILER_DEFINES   ${TENGINE_SERIALIZER_COMPILER_DEFINES})
LIST (APPEND TENGINE_COMPILER_DEFINES   ${TENGINE_EXECUTER_COMPILER_DEFINES})
LIST (APPEND TENGINE_COMPILER_DEFINES   ${TENGINE_EXPORTER_COMPILER_DEFINES})
LIST (APPEND TENGINE_COMPILER_DEFINES   ${TENGINE_OPTIMIZER_COMPILER_DEFINES})


# add compiler options
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_COMMON_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_DEVICE_COMPILER_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_OPERATOR_COMPILER_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_SCHEDULER_COMPILER_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_SERIALIZER_COMPILER_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_EXECUTER_COMPILER_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_EXPORTER_COMPILER_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_GRAPH_COMPILER_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_MODULE_COMPILER_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_OPTIMIZER_COMPILER_OPTIONS})
LIST (APPEND TENGINE_COMPILER_OPTIONS   ${TENGINE_UTILITY_COMPILER_OPTIONS})


# add linker options
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_COMMON_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_DEVICE_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_OPERATOR_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_SCHEDULER_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_SERIALIZER_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_EXECUTER_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_EXPORTER_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_GRAPH_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_MODULE_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_OPTIMIZER_LINKER_OPTIONS})
LIST (APPEND TENGINE_LINKER_OPTIONS     ${TENGINE_UTILITY_LINKER_OPTIONS})


# add link libraries
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_COMMON_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_DEVICE_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_OPERATOR_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_SCHEDULER_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_SERIALIZER_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_EXECUTER_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_EXPORTER_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_GRAPH_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_MODULE_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_OPTIMIZER_LINK_LIBRARIES})
LIST (APPEND TENGINE_LINK_LIBRARIES     ${TENGINE_UTILITY_LINK_LIBRARIES})

# Online report
IF (NOT MSVC)
    IF (TENGINE_ONLINE_REPORT)
        ADD_DEFINITIONS(-DTENGINE_ONLINE_REPORT=1)
        LIST (APPEND TENGINE_HEADER_PATH        "${CMAKE_SOURCE_DIR}/source/olreport/include/")
        FILE (GLOB_RECURSE TENGINE_ONLINE_REPORT_SRCS "${CMAKE_SOURCE_DIR}/source/olreport/*.c")
        LIST (APPEND TENGINE_SOURCE_FILES     ${TENGINE_ONLINE_REPORT_SRCS})
    ENDIF()
ENDIF()

# add static and shared target
ADD_LIBRARY (${TENGINE_LITE_NAME}-static STATIC ${TEngine_NEXT_LIB_SRCS})
ADD_LIBRARY (${TENGINE_LITE_NAME}        SHARED ${TEngine_NEXT_LIB_SRCS})


# add source files to each target
TARGET_SOURCES (${TENGINE_LITE_NAME}-static PRIVATE ${TENGINE_SOURCE_FILES})
TARGET_SOURCES (${TENGINE_LITE_NAME}        PRIVATE ${TENGINE_SOURCE_FILES})

# add header file search path
TARGET_INCLUDE_DIRECTORIES (${TENGINE_LITE_NAME}-static PRIVATE ${TENGINE_HEADER_PATH})
TARGET_INCLUDE_DIRECTORIES (${TENGINE_LITE_NAME}        PRIVATE ${TENGINE_HEADER_PATH})

# add link libraries search path
TARGET_LINK_DIRECTORIES (${TENGINE_LITE_NAME}-static PUBLIC ${TENGINE_LINK_PATH})
TARGET_LINK_DIRECTORIES (${TENGINE_LITE_NAME}        PUBLIC ${TENGINE_LINK_PATH})

# add defines
TARGET_COMPILE_DEFINITIONS (${TENGINE_LITE_NAME}-static PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:${TENGINE_COMPILER_DEFINES}>)
TARGET_COMPILE_DEFINITIONS (${TENGINE_LITE_NAME}        PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:${TENGINE_COMPILER_DEFINES}>)

# add options
TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}-static PUBLIC $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:${TENGINE_COMPILER_OPTIONS}>)
TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}        PUBLIC $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:${TENGINE_COMPILER_OPTIONS}>)

# add link options (target_LINKER_OPTIONS need CMake 3.13 at least)
TARGET_LINK_OPTIONS (${TENGINE_LITE_NAME}-static PUBLIC $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:${TENGINE_LINKER_OPTIONS}>)
TARGET_LINK_OPTIONS (${TENGINE_LITE_NAME}        PUBLIC $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:${TENGINE_LINKER_OPTIONS}>)

# add link libraries
TARGET_LINK_LIBRARIES (${TENGINE_LITE_NAME}-static PUBLIC  ${TENGINE_LINK_LIBRARIES})
TARGET_LINK_LIBRARIES (${TENGINE_LITE_NAME}        PUBLIC  ${TENGINE_LINK_LIBRARIES})



# default support openmp
IF(NOT (TENGINE_FORCE_SKIP_OPENMP) AND TENGINE_OPENMP)
    INCLUDE (${PROJECT_SOURCE_DIR}/cmake/libraries/openmp.cmake)
    TENGINE_CHECK_LIB_OPENMP (_has_openmp)
    IF (_has_openmp)
        TENGINE_USE_LIB_OPENMP (${TENGINE_LITE_NAME}-static ON)
        TENGINE_USE_LIB_OPENMP (${TENGINE_LITE_NAME}        OFF)
        IF(MSVC)
            SET_SOURCE_FILES_PROPERTIES(${TENGINE_SOURCE_FILES} PROPERTIES LANGUAGE CXX)
            TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}-static PRIVATE /std:c++latest)
            TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}        PRIVATE /std:c++latest)
        ENDIF()

        SET (TENGINE_ENABLED_OPENMP ${OpenMP_C_VERSION} CACHE INTERNAL "" FORCE)
    ENDIF()
ENDIF()
UNSET (_has_openmp)

# pthread
IF (NOT OHOS)
	INCLUDE (${PROJECT_SOURCE_DIR}/cmake/libraries/pthread.cmake)
	TENGINE_CHECK_LIB_PTHREAD (_has_pthread)
	IF (_has_pthread)
		TENGINE_USE_LIB_PTHREAD (${TENGINE_LITE_NAME}-static ON)
		TENGINE_USE_LIB_PTHREAD (${TENGINE_LITE_NAME}        OFF)
	ENDIF()
	UNSET (_has_pthread)
ENDIF()


#
IF (TENGINE_COMPILER_GCC OR TENGINE_COMPILER_CLANG)
    # linking time optimization
    IF ((NOT ANDROID) AND (NOT OHOS))
        #TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-flto>)
    ENDIF()

    TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}-static PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fdata-sections>)
    TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}-static PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-ffunction-sections>)

    TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}        PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fdata-sections>)
    TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}        PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-ffunction-sections>)
    #TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}        PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wl,--gc-sections>)

    IF (NOT TENGINE_ENABLE_ALL_SYMBOL)
        TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fvisibility=hidden>)
        TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fvisibility=hidden>)
    ENDIF()

    # it seems will lead to some error
    #ADD_COMPILE_OPTIONS ($<$<COMPILE_LANGUAGE:CXX>:-Wl,-rpath,'$ORIGIN:/lib>)

    #SET_TARGET_PROPERTIES(${TENGINE_LITE_NAME}-static PROPERTIES LINK_FLAGS "-Wl,--exclude-libs,ALL")
ENDIF()


# if toolchain need options
IF (TENGINE_TOOLCHAIN_FLAG)
    MESSAGE("TENGINE_TOOLCHAIN_FLAG=${TENGINE_TOOLCHAIN_FLAG}")
    MESSAGE("TENGINE_TARGET_PROCESSOR=${TENGINE_TARGET_PROCESSOR}")
    FOREACH(_OPT ${TENGINE_TOOLCHAIN_FLAG})
        MESSAGE("_OPT=${_OPT}")
        TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}-static PRIVATE $<$<NOT:$<COMPILE_LANGUAGE:CUDA>>:${_OPT}>)
        TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}        PRIVATE $<$<NOT:$<COMPILE_LANGUAGE:CUDA>>:${_OPT}>)
    ENDFOREACH()
ENDIF()

IF (TENGINE_TOOLCHAIN_ASM_FLAG)
    FOREACH(_OPT ${TENGINE_TOOLCHAIN_ASM_FLAG})
        TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}-static PRIVATE $<$<COMPILE_LANGUAGE:ASM>:${_OPT}>)
        TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}        PRIVATE $<$<COMPILE_LANGUAGE:ASM>:${_OPT}>)
    ENDFOREACH()
ENDIF()

IF (TENGINE_TOOLCHAIN_C_FLAG)
    FOREACH(_OPT ${TENGINE_TOOLCHAIN_C_FLAG})
        TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}-static PRIVATE $<$<COMPILE_LANGUAGE:C>:${_OPT}>)
        TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}        PRIVATE $<$<COMPILE_LANGUAGE:C>:${_OPT}>)
    ENDFOREACH()
ENDIF()

IF (TENGINE_TOOLCHAIN_CXX_FLAG)
    FOREACH(_OPT ${TENGINE_TOOLCHAIN_CXX_FLAG})
        TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}-static PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${_OPT}>)
        TARGET_COMPILE_OPTIONS(${TENGINE_LITE_NAME}        PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${_OPT}>)
    ENDFOREACH()
ENDIF()


# cuda above option
IF (TENGINE_ENABLE_CUDA)
    IF (TENGINE_ENV_HAS_CXX14)
        SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}-static PROPERTY CUDA_STANDARD 14)
        SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}        PROPERTY CUDA_STANDARD 14)
    ELSE()
        SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}-static PROPERTY CUDA_STANDARD 11)
        SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}        PROPERTY CUDA_STANDARD 11)
    ENDIF()
    SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}-static PROPERTY CUDA_STANDARD_REQUIRED ON)
    SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}        PROPERTY CUDA_STANDARD_REQUIRED ON)

    #TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}-static PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-fPIC>)
    #TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}        PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-fPIC>)

#    TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}-static PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-flto>)
#    TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}        PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-flto>)

    TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}-static PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-Werror=cross-execution-space-call>)
    TARGET_COMPILE_OPTIONS (${TENGINE_LITE_NAME}        PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-Werror=cross-execution-space-call>)


    IF (${CMAKE_MINOR_VERSION} GREATER 17)
        IF (TENGINE_TARGET_PROCESSOR MATCHES "ARM")
            SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}-static PROPERTY CUDA_ARCHITECTURES 53 62 72)
            SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}        PROPERTY CUDA_ARCHITECTURES 53 62 72)
        ELSE()
            SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}-static PROPERTY CUDA_ARCHITECTURES 50 52 61 70 75)
            SET_PROPERTY(TARGET ${TENGINE_LITE_NAME}        PROPERTY CUDA_ARCHITECTURES 50 52 61 70 75)
        ENDIF()
    ENDIF()
ENDIF()

# deal with depends

FOREACH(_var ${TENGINE_DEVICE_DEPENDS_FORWARD})
    ADD_DEPENDENCIES(${TENGINE_LITE_NAME}-static ${_var})
    ADD_DEPENDENCIES(${TENGINE_LITE_NAME}        ${_var})
ENDFOREACH()

# debug macro information
IF (TENGINE_DEBUG_MEM_STAT)
    TARGET_COMPILE_DEFINITIONS(${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:CONFIG_MEM_STAT>)
ENDIF()
IF (TENGINE_DEBUG_DATA)
    TARGET_COMPILE_DEFINITIONS(${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:DEBUG_DATA>)
ENDIF()

IF (TENGINE_DEBUG_TIME)
    TARGET_COMPILE_DEFINITIONS(${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:DEBUG_TIME>)
ENDIF()

IF (TENGINE_LITE_VERSION)
    TARGET_COMPILE_DEFINITIONS(${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:TENGINE_LITE_VERSION=${TENGINE_LITE_VERSION}>)
ENDIF()

IF (TENGINE_VERSION_POSTFIX)
    TARGET_COMPILE_DEFINITIONS(${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:TENGINE_VERSION_POSTFIX=${TENGINE_VERSION_POSTFIX}>)
ENDIF()


#TARGET_COMPILE_DEFINITIONS(${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:CONFIG_DISABLE_PARAM_ACCESS>)
#TARGET_COMPILE_DEFINITIONS(${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:CONFIG_INTERN_ALLOCATOR>)
#TARGET_COMPILE_DEFINITIONS(${TENGINE_LITE_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:CONFIG_TENGINE_SERIALIZER>)

SET_PROPERTY(TARGET ${CMAKE_PROJECT_NAME}-static PROPERTY FOLDER "libtengine-lite")
SET_PROPERTY(TARGET ${CMAKE_PROJECT_NAME} PROPERTY FOLDER "libtengine-lite")

# install tengine libraries
INSTALL (TARGETS ${CMAKE_PROJECT_NAME}-static DESTINATION lib)
INSTALL (TARGETS ${CMAKE_PROJECT_NAME}        DESTINATION lib)

IF (TENGINE_STANDALONE_HCL)
    INSTALL (TARGETS ${TENGINE_STANDALONE_HCL_LIB_NAME} DESTINATION lib)
ENDIF()

# install header files
INSTALL (FILES ${CMAKE_SOURCE_DIR}/source/api/c_api.h DESTINATION include/tengine)
INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/defines.h  DESTINATION include/tengine)

IF (TENGINE_BUILD_CPP_API)
    INSTALL (FILES ${CMAKE_SOURCE_DIR}/source/api/cpp_api.h DESTINATION include/tengine)
ENDIF()
