# ----------------------------------------------------------------------------
# This program is free software, you can redistribute it and/or modify.
# Copyright (c) 2026 Huawei Technologies Co., Ltd.
# This file is a part of the CANN Open Software.
# Licensed under CANN Open Software License Agreement Version 2.0 (the "License").
# Please refer to the License for details. You may not use this file except in compliance with the License.
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
# See LICENSE in the root of the software repository for the full text of the License.
# ----------------------------------------------------------------------------

cmake_minimum_required(VERSION 3.16)
set(PKG_NAME ras)
set(CANN_3RD_LIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/third_party CACHE STRING "cann third party lib path")
include(cmake/third_party/fetch_cann_cmake.cmake)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${RULE_LAUNCH})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${RULE_LAUNCH})

project(${PKG_NAME} VERSION 1.0.0)

find_program(CCACHE_PROGRAM ccache)
option(ENABLE_CCACHE "Enable ccache compilation acceleration" ON)
if(ENABLE_CCACHE AND CCACHE_PROGRAM)
  set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
  set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
endif()

if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
  message(STATUS "compile project with library")
  option(BUILD_WITH_INSTALLED_DEPENDENCY_CANN_PKG
         "Build ops-ras with cann pkg" ON)
else()
  message(STATUS "compile project with src")
  option(BUILD_WITH_INSTALLED_DEPENDENCY_CANN_PKG
         "Build ops-ras with cann source" OFF)
endif()

if(UNIX)
  set(SYSTEM_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-linux)
endif()
set(OPS_RAS_DIR ${CMAKE_CURRENT_SOURCE_DIR})

# 外部传参
option(ENABLE_ASAN "Enable asan" OFF)
option(ENABLE_VALGRIND "Enable valgrind" OFF)
option(ENABLE_TEST "Enable test" OFF)
option(ENABLE_UT_EXEC "Enable exec ut" OFF)
option(ENABLE_BINARY "Enable build binary" OFF)
option(ENABLE_CUSTOM "Enable build custom" OFF)
option(ENABLE_PACKAGE "Enable build package" OFF)
option(ENABLE_EXPERIMENTAL "Enable experimental module" OFF)
option(ENABLE_COVERAGE "Enable coverage" OFF)
option(ENABLE_MSSANITIZER "Enable mssanitizer mode" OFF)
option(ENABLE_OOM "Enable oom mode" OFF)
option(ENABLE_DUMP_CCE "Enable dump_cce mode" OFF)
option(NO_AICPU "Disable aicpu targets" OFF)
option(NO_ACLNN "Disable ACLNN targets" OFF)
option(OP_HOST_UT "Enable ophost ut" OFF)
option(OP_API_UT "Enable opapi ut" OFF)
option(OP_GRAPH_UT "Enable graph ut" OFF)
option(OP_KERNEL_UT "Enable kernel ut" OFF)
option(OP_KERNEL_AICPU_UT "Enable aicpu kernel ut" OFF)
option(UT_TEST_ALL "Enable all ut" OFF)
option(DOWNLOAD_OPS_TEST_KIT "Download ops-test-kit repository" OFF)

set(RAS_SELECTED_EXAMPLE FALSE)
if(ASCEND_OP_NAME STREQUAL "add_example" OR ASCEND_OP_NAME STREQUAL "add_example_aicpu")
  set(RAS_SELECTED_EXAMPLE TRUE)
endif()

set(RAS_HAS_GRAPH_SOURCE FALSE)
if(RAS_SELECTED_EXAMPLE)
  set(RAS_HAS_GRAPH_SOURCE TRUE)
endif()
file(GLOB_RECURSE RAS_PRODUCT_GRAPH_SOURCES CONFIGURE_DEPENDS
  ${CMAKE_CURRENT_SOURCE_DIR}/reliability/*/op_graph/*_proto.h
  ${CMAKE_CURRENT_SOURCE_DIR}/experimental/reliability/*/op_graph/*_proto.h
)
if(RAS_PRODUCT_GRAPH_SOURCES)
  set(RAS_HAS_GRAPH_SOURCE TRUE)
endif()

file(GLOB_RECURSE RAS_ONNX_PLUGIN_SOURCES CONFIGURE_DEPENDS
  ${CMAKE_CURRENT_SOURCE_DIR}/common/src/framework/*_onnx_plugin.cpp
  ${CMAKE_CURRENT_SOURCE_DIR}/reliability/*/*_onnx_plugin.cpp
  ${CMAKE_CURRENT_SOURCE_DIR}/experimental/reliability/*/*_onnx_plugin.cpp
)
file(GLOB_RECURSE RAS_AICPU_SOURCES CONFIGURE_DEPENDS
  ${CMAKE_CURRENT_SOURCE_DIR}/reliability/*/op_kernel_aicpu/*.cpp
  ${CMAKE_CURRENT_SOURCE_DIR}/experimental/reliability/*/op_kernel_aicpu/*.cpp
)

set(RAS_NEEDS_PROTOBUF FALSE)
if(RAS_ONNX_PLUGIN_SOURCES OR RAS_AICPU_SOURCES OR ASCEND_OP_NAME STREQUAL "add_example_aicpu")
  set(RAS_NEEDS_PROTOBUF TRUE)
endif()
set(RAS_NEEDS_EIGEN FALSE)
if(RAS_AICPU_SOURCES OR ASCEND_OP_NAME STREQUAL "add_example_aicpu")
  set(RAS_NEEDS_EIGEN TRUE)
endif()
set(RAS_NEEDS_AICPU FALSE)
if(RAS_AICPU_SOURCES OR ASCEND_OP_NAME STREQUAL "add_example_aicpu")
  set(RAS_NEEDS_AICPU TRUE)
endif()
set(RAS_NEEDS_TILING_API FALSE)
if(RAS_SELECTED_EXAMPLE OR OP_HOST_UT OR UT_TEST_ALL)
  set(RAS_NEEDS_TILING_API TRUE)
endif()

if(ENABLE_TEST)
    set(DEFAULT_BUILD_TYPE "Debug")
else()
    set(DEFAULT_BUILD_TYPE "Release")
endif()

if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
    set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "Choose the build type: Release/Debug" FORCE)
endif()

set(BUILD_MODE
    ""
    CACHE STRING "build mode -O0/O1/O2")
set(ASCEND_COMPUTE_UNIT
    "ascend910b"
    CACHE STRING "soc that need to be compiled")
set(ASCEND_ALL_COMPUTE_UNIT
    "ascend310p;ascend910;ascend910b;ascend910_93;ascend950;ascend031;ascend035;ascend310b;ascend910_55;mc62cm12a;kirinx90;kirin9030"
    CACHE STRING "all soc list")
set(VENDOR_NAME
    "custom"
    CACHE STRING "vendor name")

if(NOT ${BUILD_MODE} STREQUAL "" AND NOT ${BUILD_MODE} STREQUAL "FALSE")
  set(COMPILE_OP_MODE ${BUILD_MODE})
else()
  if(ENABLE_TEST)
    set(COMPILE_OP_MODE "-O0")
  else()
    set(COMPILE_OP_MODE -O2)
  endif()
endif()

# Cmake Compile配置
set(CMAKE_CXX_STANDARD
    17
    CACHE STRING "c++17 is needed for this project")
include(cmake/third_party/opbase.cmake) # 放在dependencies.cmake前面
if(DOWNLOAD_OPS_TEST_KIT)
  include(cmake/third_party/ops_test_kit.cmake)
endif()
include(cmake/dependencies.cmake)
add_cann_third_party(json)
if(RAS_NEEDS_PROTOBUF)
  add_cann_third_party(abseil-cpp)
  add_cann_third_party(protobuf)
endif()
include(cmake/variables.cmake)
include(cmake/func.cmake)
include(cmake/opbuild.cmake)
if(RAS_NEEDS_EIGEN)
  add_cann_third_party(eigen)
endif()
include(cmake/intf_pub_linux.cmake)
include(cmake/modules/Finddlog.cmake)
include(version.cmake)

if(ENABLE_CUSTOM AND ENABLE_ASC_BUILD)
  include(cmake/custom_kernel.cmake)
endif()

init_cann_project()
if(BUILD_WITH_INSTALLED_DEPENDENCY_CANN_PKG)
  check_cann_pkg_build_deps("ops-ras")
endif()
add_cann_version_info_targets()

if(ENABLE_TEST)
  enable_testing()
  # ut common dependencies
  add_cann_third_party(gtest)
  include(cmake/intf_pub_llt_gccnative.cmake)
  include(cmake/ut.cmake)

  # op host ut
  if(UT_TEST_ALL OR OP_HOST_UT)
    set(OP_TILING_MODULE_NAME ${PKG_NAME}_op_tiling_ut)

    set(OP_INFERSHAPE_MODULE_NAME ${PKG_NAME}_op_infershape_ut)
  endif()

  # op api ut
  if(UT_TEST_ALL OR OP_API_UT)
    set(OP_API_MODULE_NAME ${PKG_NAME}_op_api_ut)
    set(OP_API_UT_COMMON_INC
        ${CMAKE_SOURCE_DIR}/tests/ut/op_api/op_api_ut_common/inc
        CACHE STRING "opapi ut common include path" FORCE)
  endif()

  # op graph ut
  if(UT_TEST_ALL OR OP_GRAPH_UT)
    include(cmake/gen_ops_info.cmake)
    include(cmake/symbol.cmake)
    set(OP_GRAPH_MODULE_NAME ${PKG_NAME}_op_graph_ut)
  endif()

  # op kernel ut
  if(UT_TEST_ALL OR OP_KERNEL_UT)
    set(UT_DONE OFF)
    include(cmake/gen_ops_info.cmake)
    set(OP_KERNEL_MODULE_NAME ${PKG_NAME}_op_kernel_ut)
  endif()
  add_subdirectory(tests/ut/common)
endif()

if(BUILD_WITH_INSTALLED_DEPENDENCY_CANN_PKG)
  add_subdirectory(common)
endif()

add_category_subdirectory()

if(ENABLE_TEST)
  add_subdirectory(tests/ut)
endif()

message(STATUS "Ops for this compilation contains: ${COMPILED_OPS}")

if(BUILD_WITH_INSTALLED_DEPENDENCY_CANN_PKG AND NOT ENABLE_TEST)
  include(cmake/gen_ops_info.cmake)
  gen_ops_info_and_python()

  include(cmake/symbol.cmake)
  if(ENABLE_CUSTOM)
    # custom package library setting and install
    gen_cust_symbol()
  else()
    gen_norm_symbol()
  endif()
  if(ENABLE_STATIC)
    include(cmake/static.cmake)
  endif()
endif()

if(ENABLE_PACKAGE)
  include(cmake/package.cmake)

  if(ENABLE_CUSTOM)
    pack_custom()
  else()
    pack_built_in()
  endif()
endif()