# ----------------------------------------------------------------------------------------------------------- # Copyright (c) 2025 Huawei Technologies Co., Ltd. # This program is free software, you can redistribute it and/or modify it under the terms and conditions of # 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. # ----------------------------------------------------------------------------------------------------------- ######################################################################################################################## # 预定义变量 ######################################################################################################################## # 缓存所有算子 UTest 场景 OpApi 动态库相关信息 set(_OpsTestUt_OpApiSources "" CACHE INTERNAL "" FORCE) # Sources set(_OpsTestUt_OpApiPrivateIncludesExt "" CACHE INTERNAL "" FORCE) # PrivateIncludesExt set(_OpsTestUt_OpApiLinkLibrariesExt "" CACHE INTERNAL "" FORCE) # LinkLibrariesExt add_library(_OpsTestUt_OpApi_Wno INTERFACE) target_compile_options(_OpsTestUt_OpApi_Wno INTERFACE $<$:-Wno-mismatched-tags> $<$:-Wno-format-signedness> -Wno-extra -Wno-redundant-decls ) add_definitions(-DNOT_DYNAMIC_COMPILE) # 缓存所有算子 UTest 场景 OpProto 动态库相关信息 set(_OpsTestUt_OpProtoSources "" CACHE INTERNAL "" FORCE) # Sources set(_OpsTestUt_OpProtoPrivateIncludesExt "" CACHE INTERNAL "" FORCE) # PrivateIncludesExt set(_OpsTestUt_OpProtoLinkLibrariesExt "" CACHE INTERNAL "" FORCE) # LinkLibrariesExt # 缓存所有算子 UTest 场景 OpTiling 动态库相关信息 set(_OpsTestUt_OpTilingSources "" CACHE INTERNAL "" FORCE) # Sources set(_OpsTestUt_OpTilingPrivateIncludesExt "" CACHE INTERNAL "" FORCE) # PrivateIncludesExt set(_OpsTestUt_OpTilingLinkLibrariesExt "" CACHE INTERNAL "" FORCE) # LinkLibrariesExt add_library(_OpsTestUt_OpTiling_Wno INTERFACE) target_compile_options(_OpsTestUt_OpTiling_Wno INTERFACE $<$:-Wno-unused-private-field> $<$:-Wno-redundant-move> -Wno-shadow $<$:-Wno-format-signedness> -Wno-extra ) # 缓存当前算子 UTest 场景 OpKernel 目标 set(_OpsTestUt_OpKernelLibraries "" CACHE INTERNAL "" FORCE) # LinkLibrariesExt add_library(_OpsTestUt_OpKernel_Wno INTERFACE) target_compile_options(_OpsTestUt_OpKernel_Wno INTERFACE -Wno-undef -Wno-cast-qual -Wno-shadow -Wno-sign-compare -Wno-unused-macros -Wno-unused-variable $<$:-Wno-unused-but-set-variable> $<$:$<$:-Wno-unused-but-set-variable>> $<$:-Wno-duplicated-branches> -Wno-extra -Wno-float-conversion -Wno-parentheses ) # 缓存当前算子 UTest 场景 UTestCommon 目标 set(_OpsTestUt_UTestCommonLibrary "" CACHE INTERNAL "" FORCE) # 缓存所有算子 UTest 场景 UTest用例 动态库相关信息 set(_OpsTestUt_UTestCaseLibraries "" CACHE INTERNAL "" FORCE) set(_OpsTestUt_UTestAclnnCaseLibraries "" CACHE INTERNAL "" FORCE) add_library(_OpsTestUt_UTestCaseStatic_Wno INTERFACE) target_compile_options(_OpsTestUt_UTestCaseStatic_Wno INTERFACE $<$:-Wno-vla> ) # GTest 版本兼容性保证 add_library(_OpsTestUt_GTest_Wno INTERFACE) target_compile_options(_OpsTestUt_GTest_Wno INTERFACE -Wno-undef ) ######################################################################################################################## # 编译方法 ######################################################################################################################## # Level1, 添加算子 OpApi 动态库 #[[ 调用参数: one_value_keywords: SUB_SYSTEM : 必选参数, 用于指定算子所属子系统, 如 transformer BRIEF : 必选参数, 用于指定算子缩略名(建议以大驼峰命名, 与算子实际名称无强制对应关系), 如 Fag/Fas/Fa SNAKE : 必选参数, 用于指定算子全名, 如 flash_attention_score_grad multi_value_keywords: SOURCES_EXT : 可选参数, 额外源文件 PRIVATE_INCLUDES_EXT : 可选参数, 额外头文件搜索路径 PRIVATE_LINK_LIBRARIES_EXT : 可选参数, 额外链接库 备注说明: 本函数提供编译算子对应 opapi.so 的功能. 下面介绍在调用本函数时所需了解的一些背景知识和注意事项. 1. 本函数假设算子对应 OpApi 的源文件位于 'src/${SUB_SYSTEM}/${SNAKE}/op_host' 路径, 并自动添加以下内容: a) 源文件: ${SNAKE}.cpp, aclnn_${SNAKE}.cpp b) 头文件搜索路径: 'src/${SUB_SYSTEM}/${SNAKE}/op_host' 2. 若算子 '需要额外的源文件’ 或 ‘源文件不满足上述约定的默认路径', 则可通过 SOURCES_EXT 参数指定 '额外的源文件'; 3. 若算子 '需要额外头文件搜索路径’ 或 ‘本函数现有实现的头文件搜索路径设置不满足', 则可通过 PRIVATE_INCLUDES_EXT 参数指定 '额外的头文件搜索路径'; 参数 PRIVATE_LINK_LIBRARIES_EXT 设置逻辑同理; ]] function(OpsTest_Level1_AddOpApiShared) cmake_parse_arguments( TMP "" "SUB_SYSTEM;BRIEF;SNAKE" "SOURCES_EXT;PRIVATE_INCLUDES_EXT;PRIVATE_LINK_LIBRARIES_EXT" "" ${ARGN} ) get_filename_component(_L0_Src "${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE}/op_host/${TMP_SNAKE}.cpp" REALPATH) if (NOT EXISTS "${_L0_Src}") set(_L0_Src) endif () get_filename_component(_L2_Src "${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE}/op_host/aclnn_${TMP_SNAKE}.cpp" REALPATH) if (NOT EXISTS "${_L2_Src}") set(_L2_Src) endif () get_filename_component(_Inc "${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE}/op_host/" REALPATH) if (NOT EXISTS "${_Inc}") set(_Inc) endif () set(_Sources ${TMP_SOURCES_EXT} ${_L0_Src} ${_L2_Src}) list(REMOVE_DUPLICATES _Sources) if (_Sources) set(_PrivateIncludeDirs ${TMP_PRIVATE_INCLUDES_EXT} ${_Inc}) list(REMOVE_DUPLICATES _PrivateIncludeDirs) set(_OpsTestUt_OpApiSources ${_OpsTestUt_OpApiSources} ${_Sources} CACHE INTERNAL "" FORCE) set(_OpsTestUt_OpApiPrivateIncludesExt ${_OpsTestUt_OpApiPrivateIncludesExt} ${_PrivateIncludeDirs} CACHE INTERNAL "" FORCE) set(_OpsTestUt_OpApiLinkLibrariesExt ${_OpsTestUt_OpApiLinkLibrariesExt} ${TMP_PRIVATE_LINK_LIBRARIES_EXT} CACHE INTERNAL "" FORCE) endif () endfunction() # 私有函数, 外部不可直接调用, 用于实际生成 OpApi 动态库 #[[ ]] function(OpsTest_AddOpApiShared) list(REMOVE_DUPLICATES _OpsTestUt_OpApiSources) list(REMOVE_DUPLICATES _OpsTestUt_OpApiPrivateIncludesExt) list(REMOVE_DUPLICATES _OpsTestUt_OpApiLinkLibrariesExt) if ("${_OpsTestUt_OpApiSources}" STREQUAL "") return() endif () set(_Target ${UTest_NamePrefix}_OpApi) add_library(${_Target} SHARED) target_sources(${_Target} PRIVATE ${_OpsTestUt_OpApiSources} ) target_include_directories(${_Target} PRIVATE ${OPAPI_INCLUDE} ${_OpsTestUt_OpApiPrivateIncludesExt} ${ASCEND_CANN_PACKAGE_PATH}/runtime/pkg_inc ${ASCEND_CANN_PACKAGE_PATH}/runtime/pkg_inc/profiling ) target_compile_options(${_Target} PRIVATE $<$:-std=gnu++1z> ) target_compile_definitions(${_Target} PRIVATE ACLNN_LOG_FMT_CHECK LOG_CPP PROCESS_LOG ) target_link_libraries(${_Target} PRIVATE -Wl,--whole-archive ${_OpsTestUt_OpApiLinkLibrariesExt} $ $ -Wl,--no-whole-archive PRIVATE $<$:$> nnopbase profapi ge_common_base ascend_dump ascendalog dl ) set(_UTest_OpApiLibrary ${_Target} PARENT_SCOPE) endfunction() # Level1, 添加算子 OpProto 动态库 #[[ 调用参数: one_value_keywords: SUB_SYSTEM : 必选参数, 用于指定算子所属子系统, 如 transformer BRIEF : 必选参数, 用于指定算子缩略名(建议以大驼峰命名, 与算子实际名称无强制对应关系), 如 Fag/Fas/Fa SNAKE : 必选参数, 用于指定算子全名, 如 flash_attention_score_grad multi_value_keywords: SOURCES_EXT : 可选参数, 额外源文件 PRIVATE_INCLUDES_EXT : 可选参数, 额外头文件搜索路径 PRIVATE_LINK_LIBRARIES_EXT : 可选参数, 额外链接库 备注说明: 本函数提供编译算子对应 OpProto.so 的功能. 下面介绍在调用本函数时所需了解的一些背景知识和注意事项. 1. 本函数假设算子对应 OpProto 的源文件位于 'src/${SUB_SYSTEM}/${SNAKE}/op_host' 路径, 并自动添加以下内容: a) 源文件: ${SNAKE}_proto.cpp b) 头文件搜索路径: 'src/${SUB_SYSTEM}/${SNAKE}/op_host' 2. 若算子 '需要额外的源文件’ 或 ‘源文件不满足上述约定的默认路径', 则可通过 SOURCES_EXT 参数指定 '额外的源文件'; 3. 若算子 '需要额外头文件搜索路径’ 或 ‘本函数现有实现的头文件搜索路径设置不满足', 则可通过 PRIVATE_INCLUDES_EXT 参数指定 '额外的头文件搜索路径'; 参数 PRIVATE_LINK_LIBRARIES_EXT 设置逻辑同理; ]] function(OpsTest_Level1_AddOpProtoShared) cmake_parse_arguments( TMP "" "SUB_SYSTEM;BRIEF;SNAKE" "SOURCES_EXT;PRIVATE_INCLUDES_EXT;PRIVATE_LINK_LIBRARIES_EXT" "" ${ARGN} ) get_filename_component(_Src "${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE}/op_host/${TMP_SNAKE}_proto.cpp" REALPATH) if (NOT EXISTS "${_Src}") set(_Src) endif () get_filename_component(_Inc "${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE}/op_host/" REALPATH) if (NOT EXISTS "${_Inc}") set(_Inc) endif () set(_Sources ${TMP_SOURCES_EXT} ${_Src}) list(REMOVE_DUPLICATES _Sources) if (_Sources) set(_PrivateIncludeDirs ${TMP_PRIVATE_INCLUDES_EXT} ${_Inc}) list(REMOVE_DUPLICATES _PrivateIncludeDirs) set(_OpsTestUt_OpProtoSources ${_OpsTestUt_OpProtoSources} ${_Sources} CACHE INTERNAL "" FORCE) set(_OpsTestUt_OpProtoPrivateIncludesExt ${_OpsTestUt_OpProtoPrivateIncludesExt} ${_PrivateIncludeDirs} CACHE INTERNAL "" FORCE) set(_OpsTestUt_OpProtoLinkLibrariesExt ${_OpsTestUt_OpProtoLinkLibrariesExt} ${TMP_PRIVATE_LINK_LIBRARIES_EXT} CACHE INTERNAL "" FORCE) endif () endfunction() # 私有函数, 外部不可直接调用, 用于实际生成 OpProto 动态库 #[[ ]] function(OpsTest_AddOpProtoShared) list(REMOVE_DUPLICATES _OpsTestUt_OpProtoSources) list(REMOVE_DUPLICATES _OpsTestUt_OpProtoPrivateIncludesExt) list(REMOVE_DUPLICATES _OpsTestUt_OpProtoLinkLibrariesExt) if ("${_OpsTestUt_OpProtoSources}" STREQUAL "") return() endif () set(_Target ${UTest_NamePrefix}_OpProto) add_library(${_Target} SHARED) target_sources(${_Target} PRIVATE ${_OpsTestUt_OpProtoSources} ) target_include_directories(${_Target} PRIVATE ${OPBASE_INC_DIRS} ${_OpsTestUt_OpProtoPrivateIncludesExt} ) target_compile_options(${_Target} PRIVATE $<$:-std=gnu++1z> ) target_compile_definitions(${_Target} PRIVATE LOG_CPP PROCESS_LOG ) target_link_libraries(${_Target} PRIVATE -Wl,--whole-archive ${_OpsTestUt_OpProtoLinkLibrariesExt} $ $ $<$:$> $<$:$> -Wl,--no-whole-archive ascendalog ) set(_UTest_OpProtoLibrary ${_Target} PARENT_SCOPE) endfunction() # Level1, 添加算子 OpTiling 动态库 #[[ 调用参数: one_value_keywords: SUB_SYSTEM : 必选参数, 用于指定算子所属子系统, 如 transformer BRIEF : 必选参数, 用于指定算子缩略名(建议以大驼峰命名, 与算子实际名称无强制对应关系), 如 Fag/Fas/Fa SNAKE : 必选参数, 用于指定算子全名, 如 flash_attention_score_grad multi_value_keywords: SOURCES_EXT : 可选参数, 额外源文件 PRIVATE_INCLUDES_EXT : 可选参数, 额外头文件搜索路径 PRIVATE_LINK_LIBRARIES_EXT : 可选参数, 额外链接库 备注说明: 本函数提供编译算子对应 OpTiling.so 的功能. 下面介绍在调用本函数时所需了解的一些背景知识和注意事项. 1. 本函数假设算子对应 OpTiling 的源文件位于 'src/${SUB_SYSTEM}/${SNAKE}/op_host/${SNAKE}_tiling.cpp/.cc' 路径; 2. 若算子 '需要额外的源文件’ 或 ‘源文件不满足上述约定的默认路径', 则可通过 SOURCES_EXT 参数指定 '额外的源文件'; 3. 若算子 '需要额外头文件搜索路径’ 或 ‘本函数现有实现的头文件搜索路径设置不满足', 则可通过 PRIVATE_INCLUDES_EXT 参数指定 '额外的头文件搜索路径'; 参数 PRIVATE_LINK_LIBRARIES_EXT 设置逻辑同理; ]] function(OpsTest_Level1_AddOpTilingShared) cmake_parse_arguments( TMP "" "SUB_SYSTEM;BRIEF;SNAKE" "SOURCES_EXT;PRIVATE_INCLUDES_EXT;PRIVATE_LINK_LIBRARIES_EXT" "" ${ARGN} ) file(GLOB _Src1 "${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE}/op_host/${TMP_SNAKE}_tiling.cc") file(GLOB _Src2 "${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE}/op_host/${TMP_SNAKE}_tiling.cpp") list(APPEND _Sources ${TMP_SOURCES_EXT} ${_Src1} ${_Src2}) list(REMOVE_DUPLICATES _Sources) get_filename_component(_Inc "${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE}/op_host/" REALPATH) if (NOT EXISTS "${_Inc}") set(_Inc) endif () if (_Sources) set(_PrivateIncludeDirs ${TMP_PRIVATE_INCLUDES_EXT} ${_Inc}) list(REMOVE_DUPLICATES _PrivateIncludeDirs) set(_OpsTestUt_OpTilingSources ${_OpsTestUt_OpTilingSources} ${_Sources} CACHE INTERNAL "" FORCE) set(_OpsTestUt_OpTilingPrivateIncludesExt ${_OpsTestUt_OpTilingPrivateIncludesExt} ${_PrivateIncludeDirs} CACHE INTERNAL "" FORCE) set(_OpsTestUt_OpTilingLinkLibrariesExt ${_OpsTestUt_OpTilingLinkLibrariesExt} ${TMP_PRIVATE_LINK_LIBRARIES_EXT} CACHE INTERNAL "" FORCE) endif () endfunction() # 私有函数, 外部不可直接调用, 用于实际生成 OpTiling 动态库 #[[ ]] function(OpsTest_AddOpTilingShared) list(REMOVE_DUPLICATES _OpsTestUt_OpTilingSources) list(REMOVE_DUPLICATES _OpsTestUt_OpTilingPrivateIncludesExt) list(REMOVE_DUPLICATES _OpsTestUt_OpTilingLinkLibrariesExt) set(_Target ${UTest_NamePrefix}_OpTiling) add_library(${_Target} SHARED) target_sources(${_Target} PRIVATE ${_OpsTestUt_OpTilingSources} ${OPS_ADV_DIR}/tests/ut/framework_special/stubs/tiling/tiling_templates_registry.cpp ) target_include_directories(${_Target} PRIVATE ${OPBASE_INC_DIRS} ${_OpsTestUt_OpTilingPrivateIncludesExt} ${OPS_TRANSFORMER_DIR}/common/include ) target_compile_definitions(${_Target} PRIVATE OP_TILING_LIB LOG_CPP PROCESS_LOG ) target_compile_options(${_Target} PRIVATE $<$:-std=c++11> ) target_link_libraries(${_Target} PRIVATE -Wl,--as-needed -Wl,--no-whole-archive ${_OpsTestUt_OpTilingLinkLibrariesExt} $ $ $ $<$:$> $<$:$> graph graph_base exe_graph platform register ascendalog tiling_api c_sec ) set(_UTest_OpTilingLibrary ${_Target} PARENT_SCOPE) endfunction() # Level1, 添加算子 Kernel 静态库 #[[ 调用参数: one_value_keywords: SUB_SYSTEM : 必选参数, 用于指定算子所属子系统, 如 transformer BRIEF : 必选参数, 用于指定算子缩略名(建议以大驼峰命名, 与算子实际名称无强制对应关系), 如 Fag/Fas/Fa SNAKE : 必选参数, 用于指定算子全名, 如 flash_attention_score_grad multi_value_keywords: SOURCES_EXT : 可选参数, 额外源文件 TILING_DATA_DEF_H : 可选参数, 算子 Kernel 所需 TilingData 定义头文件 PRIVATE_INCLUDES_EXT : 可选参数, 额外头文件搜索路径 PRIVATE_COMPILE_DEFINITIONS_EXT : 可选参数, 额外编译宏 备注说明: 本函数提供编译算子对应 kernel.a 的功能. 下面介绍在调用本函数时所需了解的一些背景知识和注意事项. 1. 本函数假设算子对应 Kernel 的源文件位于 'src/${SUB_SYSTEM}/${SNAKE}/${SNAKE}.cpp' 路径; 2. 若算子 '需要额外的源文件’ 或 ‘源文件不满足上述约定的默认路径', 则可通过 SOURCES_EXT 参数指定 '额外的源文件'; 3. 当前 Ascend C 融合算子 Kernel 一般需要多个(>2) TilingData 定义头文件, 如 flash_attention_score 算子需要 data_copy_transpose_tiling_def.h 和 flash_attention_score_tiling.h; - 在 NPU 编译时, 编译框架使用 ccec 编译器并使用 -include 编译选项注入所需的多个 TilingData 定义头文件 至 Kernel 源文件; - 但 CPU 编译时, CMake 早期版本在处理 -include 选项时有 Bug(只第一个 -include 指定的头文件生效). 故本框架通过新增一个 {BRIEF}_tiling_data.h, 再在该文件中 include 所需的多个 TilingData 定义头文件, 再通过 -include 编译选项注入 {BRIEF}_tiling_data.h 的方式规避 CPU 编译时 CMake 不能处理多个 -include 选项的 Bug; 4. PRIVATE_COMPILE_DEFINITIONS_EXT 设置格式如下: optional{KernelCtrlParam func suffix} optional{OtherCompileDefinitions}} 其中 KernelCtrlParam 用于指定 Kernel 编译控制参数, func 为标识 Kernel 原始入口函数名, suffix 为标识当前 Kernel 二进制及 Kernel 入口函数后缀; 其设置逻辑如下: 4.0 KernelCtrlParam 内 func, suffix 必需按序设置; 4.1 当不设置 KernelCtrlParam 时, 仅会编译一个 Kernel.a 并以 OtherCompileDefinitions 设置编译 Definitions(如设置); 4.2 若当设置 KernelCtrlParam 时, 本函数会按 KernelCtrlParam 个数逐个编译 Kernel.a, 并以 KernelCtrlParam 间 OtherCompileDefinitions 设置编译宏定义; 并将 func 重命名为 {func}_{suffix}; 4.3 KernelCtrlParam 内 func 支持指定多个, 指定多个时 func 之间用','间隔; ]] function(OpsTest_Level1_AddOpKernelStatic) cmake_parse_arguments( TMP "" "SUB_SYSTEM;BRIEF;SNAKE" "SOURCES_EXT;TILING_DATA_DEF_H;PRIVATE_INCLUDES_EXT;PRIVATE_COMPILE_DEFINITIONS_EXT" "" ${ARGN} ) # 生成 Kernel 所需的结构体表示的对应 tiling.h string(TOLOWER ${TMP_BRIEF} tmp_brief) set(_tmp_files ${TMP_TILING_DATA_DEF_H}) list(REMOVE_DUPLICATES _tmp_files) set(_ori_files) set(_define_py ${OPS_ADV_DIR}/cmake/scripts/utest/gen_tiling_data_stub.py) foreach (_tmp ${_tmp_files}) if (EXISTS ${_tmp}) list(APPEND _ori_files "-s=${_tmp}") else () message(FATAL_ERROR "${_tmp} not exist.") endif () endforeach () # 生成目标根目录 get_filename_component(_OpsTest_GenDir "${CMAKE_CURRENT_BINARY_DIR}/gen" REALPATH) get_filename_component(_OpsTest_GenDirInc "${_OpsTest_GenDir}/inc" REALPATH) execute_process( COMMAND ${HI_PYTHON} ${_define_py} "-o=${tmp_brief}" ${_ori_files} "-d=${_OpsTest_GenDirInc}" ) set(_Target ${UTest_NamePrefix}_${TMP_BRIEF}_OpTilingDataDef) add_library(${_Target} INTERFACE) target_include_directories(${_Target} INTERFACE ${_OpsTest_GenDirInc} ${OPS_ADV_UTILS_KERNEL_INC}) # 编译变量处理 set(_TargetPrefix ${UTest_NamePrefix}_${TMP_BRIEF}_OpKernel) aux_source_directory(${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE} _Sources) list(APPEND _Sources ${TMP_SOURCES_EXT}) set(_PrivateIncludeDirectories ${_OpsTest_GenDirInc} ${TMP_PRIVATE_INCLUDES_EXT} /${SYSTEM_PREFIX}/ascendc/include/basic_api /${SYSTEM_PREFIX}/ascendc/include/basic_api/impl /${SYSTEM_PREFIX}/ascendc/include/basic_api/interface /tools/tikicpulib/lib/include /include/ascendc /x86_64-linux/include/ascendc/highlevel_api /pkg_inc/runtime/runtime /runtime/pkg_inc ) get_filename_component(_Inc "${OPS_ADV_DIR}/${TMP_SUB_SYSTEM}/${TMP_SNAKE}" REALPATH) if (EXISTS "${_Inc}") list(APPEND _PrivateIncludeDirectories ${_Inc}) endif () set(_PrivateCompileOptions -include ${_OpsTest_GenDirInc}/tiling/${tmp_brief}/tiling_stub.h ) set(_PrivateLinkLibraries -Wl,--as-needed -Wl,--no-whole-archive c_sec $ $ ) # 多 Kernel 处理 set(_OpKernelLibraries) list(FIND TMP_PRIVATE_COMPILE_DEFINITIONS_EXT KernelCtrlParam _GrpIdx) if ("${_GrpIdx}" STREQUAL "-1") # 不存在多 Kernel 配置时, 不添加后缀, 编译一个 Kernel.a set(_Target ${_TargetPrefix}) add_library(${_Target} STATIC) target_sources(${_Target} PRIVATE ${_Sources}) target_include_directories(${_Target} PRIVATE ${_PrivateIncludeDirectories}) target_compile_definitions(${_Target} PRIVATE ${TMP_PRIVATE_COMPILE_DEFINITIONS_EXT}) target_compile_options(${_Target} PRIVATE ${_PrivateCompileOptions}) target_link_libraries(${_Target} PUBLIC tikicpulib::${OPS_ADV_UTEST_OPS_TEST_ASCEND_PRODUCT_TYPE} PRIVATE ${_PrivateLinkLibraries} ) list(APPEND _OpKernelLibraries ${_Target}) else () # 存在 1/n 多 Kernel 配置时, 添加后缀, 编译多 Kernel.a while (NOT "${_GrpIdx}" STREQUAL "-1") # 获取当前 Func, Suffix, CompileDefinitions math(EXPR _FuncIdx "${_GrpIdx} + 1") math(EXPR _SuffixIdx "${_GrpIdx} + 2") math(EXPR _SubLstBgnIdx "${_GrpIdx} + 3") list(GET TMP_PRIVATE_COMPILE_DEFINITIONS_EXT ${_FuncIdx} _FuncOriValList) list(GET TMP_PRIVATE_COMPILE_DEFINITIONS_EXT ${_SuffixIdx} _SuffixVal) list(SUBLIST TMP_PRIVATE_COMPILE_DEFINITIONS_EXT ${_SubLstBgnIdx} -1 TMP_PRIVATE_COMPILE_DEFINITIONS_EXT) list(FIND TMP_PRIVATE_COMPILE_DEFINITIONS_EXT KernelCtrlParam _GrpIdx) # _GrpIdx 移动 list(SUBLIST TMP_PRIVATE_COMPILE_DEFINITIONS_EXT 0 ${_GrpIdx} _SubCompileDefinitions) string(REPLACE "," ";" _FuncOriValList "${_FuncOriValList}") set(_FuncValDef) foreach (_f ${_FuncOriValList}) list(APPEND _FuncValDef "-D${_f}=${_f}_${_SuffixVal}") endforeach () # 编译目标 set(_Target ${_TargetPrefix}_${_SuffixVal}) add_library(${_Target} STATIC) target_sources(${_Target} PRIVATE ${_Sources}) target_include_directories(${_Target} PRIVATE ${_PrivateIncludeDirectories}) target_compile_definitions(${_Target} PRIVATE ${_FuncValDef} ${_SubCompileDefinitions}) target_compile_options(${_Target} PRIVATE ${_PrivateCompileOptions}) target_link_libraries(${_Target} PUBLIC tikicpulib::${OPS_ADV_UTEST_OPS_TEST_ASCEND_PRODUCT_TYPE} PRIVATE ${_PrivateLinkLibraries} ) list(APPEND _OpKernelLibraries ${_Target}) endwhile () endif () set(_OpsTestUt_OpKernelLibraries ${_OpKernelLibraries} CACHE INTERNAL "" FORCE) endfunction() # Level1, 添加算子 UTest 用例 Common 静态库 #[[ 调用参数: one_value_keywords: BRIEF : 必选参数, 用于指定算子缩略名(建议以大驼峰命名, 与算子实际名称无强制对应关系), 如 Fag/Fas/Fa SNAKE : 必选参数, 用于指定算子全名, 如 flash_attention_score_grad TILING_DATA_DEF_BRIEF: 可选参数, 用于指定链接的 TilingData 头文件目标 multi_value_keywords: SOURCES_EXT : 可选参数, 额外源文件 SOURCES_EXT_FORCE : 可选参数, 强制使用 SOURCES_EXT 指定的额外源文件 (Common), 不再自动寻找 comm 下源文件 PUBLIC_INCLUDES_EXT : 可选参数, 额外头文件搜索路径(public) PRIVATE_INCLUDES_EXT : 可选参数, 额外头文件搜索路径 PRIVATE_LINK_LIBRARIES_EXT : 可选参数, 额外链接库 PRIVATE_COMPILE_DEFINITIONS : 可选参数, 额外的编译宏定义 ]] function(OpsTest_Level1_AddUTestCommonStatic) cmake_parse_arguments( TMP "" "BRIEF;SNAKE;TILING_DATA_DEF_BRIEF" "SOURCES_EXT;SOURCES_EXT_FORCE;PUBLIC_INCLUDES_EXT;PRIVATE_INCLUDES_EXT;PRIVATE_LINK_LIBRARIES_EXT;PRIVATE_COMPILE_DEFINITIONS" "" ${ARGN} ) if (NOT TMP_TILING_DATA_DEF_BRIEF) set(TMP_TILING_DATA_DEF_BRIEF ${TMP_BRIEF}) endif () # 强制指定源码处理 set(_Src1) set(_Src2) set(_Common_Sources ${TMP_SOURCES_EXT}) if (NOT TMP_SOURCES_EXT_FORCE) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/comm) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/comm/inc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/comm/src _Src1) else () file(GLOB_RECURSE _Src1 "${CMAKE_CURRENT_SOURCE_DIR}/comm/*.cc") file(GLOB_RECURSE _Src2 "${CMAKE_CURRENT_SOURCE_DIR}/comm/*.cpp") endif () endif () endif () list(APPEND _Common_Sources ${_Src1} ${_Src2}) list(REMOVE_DUPLICATES _Common_Sources) set(_Target_UTest_Common) if (_Common_Sources) set(_Target_UTest_Common ${UTest_NamePrefix}_${TMP_BRIEF}_UTest_Common) add_library(${_Target_UTest_Common} STATIC) target_sources(${_Target_UTest_Common} PRIVATE ${_Common_Sources}) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/comm/inc) target_include_directories(${_Target_UTest_Common} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/comm/inc) elseif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/comm) target_include_directories(${_Target_UTest_Common} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/comm) endif () target_include_directories(${_Target_UTest_Common} PUBLIC ${TMP_PUBLIC_INCLUDES_EXT} PRIVATE ${OPBASE_INC_DIRS} ${OPS_TRANSFORMER_DIR}/common/include ${ASCEND_CANN_PACKAGE_PATH}/include ${TMP_PRIVATE_INCLUDES_EXT} ) target_compile_definitions(${_Target_UTest_Common} PRIVATE ${TMP_PRIVATE_COMPILE_DEFINITIONS} ) target_link_libraries(${_Target_UTest_Common} PRIVATE -Wl,--as-needed -Wl,--no-whole-archive platform register opp_registry error_manager metadef tiling_api $ $ $<$:$> $<$:$> tikicpulib::${OPS_ADV_UTEST_OPS_TEST_ASCEND_PRODUCT_TYPE} ${UTest_NamePrefix}_${TMP_TILING_DATA_DEF_BRIEF}_OpTilingDataDef ${UTest_NamePrefix}_Utils ${TMP_PRIVATE_LINK_LIBRARIES_EXT} ${_OpsTestUt_OpKernelLibraries} # 当前各算子 common 内以 extern 方式声明 kernel 入口, 故添加依赖 ) endif () set(_OpsTestUt_UTestCommonLibrary ${_Target_UTest_Common} CACHE INTERNAL "" FORCE) endfunction() # Level1, 添加算子 UTest 用例静态库 #[[ 调用参数: one_value_keywords: BRIEF : 必选参数, 用于指定算子缩略名(建议以大驼峰命名, 与算子实际名称无强制对应关系), 如 Fag/Fas/Fa SNAKE : 必选参数, 用于指定算子全名, 如 flash_attention_score_grad TILING_DATA_DEF_BRIEF: 可选参数, 用于指定链接的 TilingData 头文件目标 multi_value_keywords: SOURCES_EXT : 可选参数, 额外源文件 SOURCES_EXT_FORCE : 可选参数, 强制使用 SOURCES_EXT 指定的额外源文件 (UTest), 不再自动寻找 utest 下源文件 PRIVATE_INCLUDES_EXT : 可选参数, 额外头文件搜索路径 PRIVATE_LINK_LIBRARIES_EXT : 可选参数, 额外链接库 PRIVATE_COMPILE_DEFINITIONS : 可选参数, 额外的编译宏定义 ]] function(OpsTest_Level1_AddUTestCaseStatic) cmake_parse_arguments( TMP "" "BRIEF;SNAKE;TILING_DATA_DEF_BRIEF" "SOURCES_EXT;SOURCES_EXT_FORCE;PRIVATE_INCLUDES_EXT;PRIVATE_LINK_LIBRARIES_EXT;PRIVATE_COMPILE_DEFINITIONS" "" ${ARGN} ) if (NOT TMP_TILING_DATA_DEF_BRIEF) set(TMP_TILING_DATA_DEF_BRIEF ${TMP_BRIEF}) endif () # 强制指定源码处理 set(_UTest_Sources ${TMP_SOURCES_EXT}) if (NOT TMP_SOURCES_EXT_FORCE) file(GLOB_RECURSE _Src1 "${CMAKE_CURRENT_SOURCE_DIR}/utest/*.cc") file(GLOB_RECURSE _Src2 "${CMAKE_CURRENT_SOURCE_DIR}/utest/*.cpp") list(APPEND _UTest_Sources ${_Src1} ${_Src2}) endif () list(REMOVE_DUPLICATES _UTest_Sources) if (_UTest_Sources) set(_Target_UTest ${UTest_NamePrefix}_${TMP_BRIEF}_UTest_Case) add_library(${_Target_UTest} STATIC) target_sources(${_Target_UTest} PRIVATE ${_UTest_Sources}) target_include_directories(${_Target_UTest} PRIVATE ${ASCEND_CANN_PACKAGE_PATH}/include ${TMP_PRIVATE_INCLUDES_EXT} ${CMAKE_CURRENT_SOURCE_DIR}/utest ) target_compile_definitions(${_Target_UTest} PRIVATE ${TMP_PRIVATE_COMPILE_DEFINITIONS} ) target_link_libraries(${_Target_UTest} PRIVATE -Wl,--as-needed -Wl,--no-whole-archive gtest $ $ $<$:$> $<$:$> tikicpulib::${OPS_ADV_UTEST_OPS_TEST_ASCEND_PRODUCT_TYPE} ${UTest_NamePrefix}_${TMP_TILING_DATA_DEF_BRIEF}_OpTilingDataDef ${UTest_NamePrefix}_Utils $ ${UTest_NamePrefix}_Utest ${TMP_PRIVATE_LINK_LIBRARIES_EXT} ${_OpsTestUt_UTestCommonLibrary} ) set(_OpsTestUt_UTestCaseLibraries ${_OpsTestUt_UTestCaseLibraries} ${_Target_UTest} CACHE INTERNAL "" FORCE) endif () endfunction() # Level1, 添加算子 UTest 用例(Aclnn)静态库 #[[ 调用参数: one_value_keywords: BRIEF : 必选参数, 用于指定算子缩略名(建议以大驼峰命名, 与算子实际名称无强制对应关系), 如 Fag/Fas/Fa SNAKE : 必选参数, 用于指定算子全名, 如 flash_attention_score_grad TILING_DATA_DEF_BRIEF: 可选参数, 用于指定链接的 TilingData 头文件目标 multi_value_keywords: SOURCES_EXT : 可选参数, 额外源文件 SOURCES_EXT_FORCE : 可选参数, 强制使用 SOURCES_EXT 指定的额外源文件 (UTest_Aclnn), 不再自动寻找 utest_aclnn 下源文件 PRIVATE_INCLUDES_EXT : 可选参数, 额外头文件搜索路径 PRIVATE_COMPILE_DEFINITIONS : 可选参数, 额外的编译宏定义 PRIVATE_LINK_LIBRARIES_EXT : 可选参数, 额外链接库 ]] function(OpsTest_Level1_AddUTestAclnnCaseStatic) cmake_parse_arguments( TMP "" "BRIEF;SNAKE;TILING_DATA_DEF_BRIEF" "SOURCES_EXT;SOURCES_EXT_FORCE;PRIVATE_INCLUDES_EXT;PRIVATE_COMPILE_DEFINITIONS;PRIVATE_LINK_LIBRARIES_EXT" "" ${ARGN} ) if (NOT TMP_TILING_DATA_DEF_BRIEF) set(TMP_TILING_DATA_DEF_BRIEF ${TMP_BRIEF}) endif () # 强制指定源码处理 set(_UTest_Aclnn_Sources ${TMP_SOURCES_EXT}) if (NOT TMP_SOURCES_EXT_FORCE) file(GLOB_RECURSE _Src1 "${CMAKE_CURRENT_SOURCE_DIR}/utest_aclnn/*.cc") file(GLOB_RECURSE _Src2 "${CMAKE_CURRENT_SOURCE_DIR}/utest_aclnn/*.cpp") list(APPEND _UTest_Aclnn_Sources ${_Src1} ${_Src2}) endif () list(REMOVE_DUPLICATES _UTest_Aclnn_Sources) if (_UTest_Aclnn_Sources) set(_Target_UTest_Aclnn ${UTest_NamePrefix}_${TMP_BRIEF}_UTest_Case_Aclnn) add_library(${_Target_UTest_Aclnn} STATIC) target_sources(${_Target_UTest_Aclnn} PRIVATE ${_UTest_Aclnn_Sources}) target_include_directories(${_Target_UTest_Aclnn} PRIVATE ${ASCEND_CANN_PACKAGE_PATH}/include ${TMP_PRIVATE_INCLUDES_EXT} ${CMAKE_CURRENT_SOURCE_DIR}/utest_aclnn ) target_compile_definitions(${_Target_UTest_Aclnn} PRIVATE ${TMP_PRIVATE_COMPILE_DEFINITIONS} ) target_link_libraries(${_Target_UTest_Aclnn} PRIVATE -Wl,--as-needed -Wl,--no-whole-archive gtest $ $ $<$:$> $<$:$> tikicpulib::${OPS_ADV_UTEST_OPS_TEST_ASCEND_PRODUCT_TYPE} ${UTest_NamePrefix}_${TMP_TILING_DATA_DEF_BRIEF}_OpTilingDataDef ${UTest_NamePrefix}_Utils $ ${UTest_NamePrefix}_Utest ${TMP_PRIVATE_LINK_LIBRARIES_EXT} ${_OpsTestUt_UTestCommonLibrary} ) set(_OpsTestUt_UTestAclnnCaseLibraries ${_OpsTestUt_UTestAclnnCaseLibraries} ${_Target_UTest_Aclnn} CACHE INTERNAL "" FORCE) endif () endfunction() # Level2, 添加算子 UTest 用例动态库 及其所需全部库(OpTiling.so, OpKernel.a 等) #[[ 调用参数: one_value_keywords: SUB_SYSTEM : 必选参数, 用于指定算子所属子系统, 如 transformer BRIEF : 必选参数, 用于指定算子缩略名(建议以大驼峰命名, 与算子实际名称无强制对应关系), 如 Fag/Fas/Fa SNAKE : 必选参数, 用于指定算子全名, 如 flash_attention_score_grad TILING_DATA_DEF_BRIEF: 可选参数, 用于指定链接的 TilingData 头文件目标 multi_value_keywords: OPAPI_SOURCES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpApiShared 函数说明 OPAPI_PRIVATE_INCLUDES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpApiShared 函数说明 OPAPI_PRIVATE_LINK_LIBRARIES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpApiShared 函数说明 PROTO_SOURCES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpProtoShared 函数说明 PROTO_PRIVATE_INCLUDES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpProtoShared 函数说明 PROTO_PRIVATE_LINK_LIBRARIES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpProtoShared 函数说明 TILING_SOURCES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpTilingShared 函数说明 TILING_PRIVATE_INCLUDES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpTilingShared 函数说明 TILING_PRIVATE_LINK_LIBRARIES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpTilingShared 函数说明 KERNEL_SOURCES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpKernelStatic 函数说明 KERNEL_TILING_DATA_DEF_H : 透传参数, 详情参见 OpsTest_Level1_AddOpKernelStatic 函数说明 KERNEL_PRIVATE_INCLUDES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpKernelStatic 函数说明 KERNEL_PRIVATE_COMPILE_DEFINITIONS_EXT : 透传参数, 详情参见 OpsTest_Level1_AddOpKernelStatic 函数说明 UTEST_COMMON_SOURCES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestCommonStatic 函数说明 UTEST_COMMON_SOURCES_EXT_FORCE : 透传参数, 详情参见 OpsTest_Level1_AddUTestCommonStatic 函数说明 UTEST_COMMON_PUBLIC_INCLUDES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestCommonStatic 函数说明 UTEST_COMMON_PRIVATE_INCLUDES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestCommonStatic 函数说明 UTEST_COMMON_PRIVATE_COMPILE_DEFINITIONS : 透传参数, 详情参见 OpsTest_Level1_AddUTestCommonStatic 函数说明 UTEST_COMMON_PRIVATE_LINK_LIBRARIES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestCommonStatic 函数说明 UTEST_SOURCES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestCaseStatic 函数说明 UTEST_SOURCES_EXT_FORCE : 透传参数, 详情参见 OpsTest_Level1_AddUTestCaseStatic 函数说明 UTEST_PRIVATE_INCLUDES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestCaseStatic 函数说明 UTEST_PRIVATE_COMPILE_DEFINITIONS : 透传参数, 详情参见 OpsTest_Level1_AddUTestCaseStatic 函数说明 UTEST_PRIVATE_LINK_LIBRARIES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestCaseStatic 函数说明 UTEST_ACLNN_SOURCES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestAclnnCaseStatic 函数说明 UTEST_ACLNN_SOURCES_EXT_FORCE : 透传参数, 详情参见 OpsTest_Level1_AddUTestAclnnCaseStatic 函数说明 UTEST_ACLNN_PRIVATE_INCLUDES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestAclnnCaseStatic 函数说明 UTEST_ACLNN_PRIVATE_COMPILE_DEFINITIONS : 透传参数, 详情参见 OpsTest_Level1_AddUTestAclnnCaseStatic 函数说明 UTEST_ACLNN_PRIVATE_LINK_LIBRARIES_EXT : 透传参数, 详情参见 OpsTest_Level1_AddUTestAclnnCaseStatic 函数说明 ]] function(OpsTest_Level2_AddOp) cmake_parse_arguments( TMP "" "SUB_SYSTEM;BRIEF;SNAKE;TILING_DATA_DEF_BRIEF" "OPAPI_SOURCES_EXT;OPAPI_PRIVATE_INCLUDES_EXT;OPAPI_PRIVATE_LINK_LIBRARIES_EXT;PROTO_SOURCES_EXT;PROTO_PRIVATE_INCLUDES_EXT;PROTO_PRIVATE_LINK_LIBRARIES_EXT;TILING_SOURCES_EXT;TILING_PRIVATE_INCLUDES_EXT;TILING_PRIVATE_LINK_LIBRARIES_EXT;KERNEL_SOURCES_EXT;KERNEL_TILING_DATA_DEF_H;KERNEL_PRIVATE_INCLUDES_EXT;KERNEL_PRIVATE_COMPILE_DEFINITIONS_EXT;UTEST_COMMON_SOURCES_EXT;UTEST_COMMON_SOURCES_EXT_FORCE;UTEST_COMMON_PUBLIC_INCLUDES_EXT;UTEST_COMMON_PRIVATE_INCLUDES_EXT;UTEST_COMMON_PRIVATE_COMPILE_DEFINITIONS;UTEST_COMMON_PRIVATE_LINK_LIBRARIES_EXT;UTEST_SOURCES_EXT;UTEST_SOURCES_EXT_FORCE;UTEST_PRIVATE_INCLUDES_EXT;UTEST_PRIVATE_COMPILE_DEFINITIONS;UTEST_PRIVATE_LINK_LIBRARIES_EXT;UTEST_ACLNN_SOURCES_EXT;UTEST_ACLNN_SOURCES_EXT_FORCE;UTEST_ACLNN_PRIVATE_INCLUDES_EXT;UTEST_ACLNN_PRIVATE_COMPILE_DEFINITIONS;UTEST_ACLNN_PRIVATE_LINK_LIBRARIES_EXT" "" ${ARGN} ) OpsTest_Level1_AddOpApiShared( SUB_SYSTEM ${TMP_SUB_SYSTEM} BRIEF ${TMP_BRIEF} SNAKE ${TMP_SNAKE} SOURCES_EXT ${TMP_OPAPI_SOURCES_EXT} PRIVATE_INCLUDES_EXT ${TMP_OPAPI_PRIVATE_INCLUDES_EXT} PRIVATE_LINK_LIBRARIES_EXT ${TMP_OPAPI_PRIVATE_LINK_LIBRARIES_EXT} ) OpsTest_Level1_AddOpProtoShared( SUB_SYSTEM ${TMP_SUB_SYSTEM} BRIEF ${TMP_BRIEF} SNAKE ${TMP_SNAKE} SOURCES_EXT ${TMP_PROTO_SOURCES_EXT} PRIVATE_INCLUDES_EXT ${TMP_PROTO_PRIVATE_INCLUDES_EXT} PRIVATE_LINK_LIBRARIES_EXT ${TMP_PROTO_PRIVATE_LINK_LIBRARIES_EXT} ) OpsTest_Level1_AddOpTilingShared( SUB_SYSTEM ${TMP_SUB_SYSTEM} BRIEF ${TMP_BRIEF} SNAKE ${TMP_SNAKE} SOURCES_EXT ${TMP_TILING_SOURCES_EXT} PRIVATE_INCLUDES_EXT ${TMP_TILING_PRIVATE_INCLUDES_EXT} PRIVATE_LINK_LIBRARIES_EXT ${TMP_TILING_PRIVATE_LINK_LIBRARIES_EXT} ) OpsTest_Level1_AddOpKernelStatic( SUB_SYSTEM ${TMP_SUB_SYSTEM} BRIEF ${TMP_BRIEF} SNAKE ${TMP_SNAKE} SOURCES_EXT ${TMP_KERNEL_SOURCES_EXT} TILING_DATA_DEF_H ${TMP_KERNEL_TILING_DATA_DEF_H} PRIVATE_INCLUDES_EXT ${TMP_KERNEL_PRIVATE_INCLUDES_EXT} PRIVATE_COMPILE_DEFINITIONS_EXT ${TMP_KERNEL_PRIVATE_COMPILE_DEFINITIONS_EXT} ) OpsTest_Level1_AddUTestCommonStatic( BRIEF ${TMP_BRIEF} SNAKE ${TMP_SNAKE} SOURCES_EXT ${TMP_UTEST_COMMON_SOURCES_EXT} SOURCES_EXT_FORCE ${TMP_UTEST_COMMON_SOURCES_EXT_FORCE} TILING_DATA_DEF_BRIEF ${TMP_TILING_DATA_DEF_BRIEF} PUBLIC_INCLUDES_EXT ${TMP_UTEST_COMMON_PUBLIC_INCLUDES_EXT} PRIVATE_INCLUDES_EXT ${TMP_UTEST_COMMON_PRIVATE_INCLUDES_EXT} PRIVATE_COMPILE_DEFINITIONS ${TMP_UTEST_COMMON_PRIVATE_COMPILE_DEFINITIONS} PRIVATE_LINK_LIBRARIES_EXT ${TMP_UTEST_COMMON_PRIVATE_LINK_LIBRARIES_EXT} ) OpsTest_Level1_AddUTestCaseStatic( BRIEF ${TMP_BRIEF} SNAKE ${TMP_SNAKE} TILING_DATA_DEF_BRIEF ${TMP_TILING_DATA_DEF_BRIEF} SOURCES_EXT ${TMP_UTEST_SOURCES_EXT} SOURCES_EXT_FORCE ${TMP_UTEST_SOURCES_EXT_FORCE} PRIVATE_INCLUDES_EXT ${TMP_UTEST_PRIVATE_INCLUDES_EXT} PRIVATE_COMPILE_DEFINITIONS ${TMP_UTEST_PRIVATE_COMPILE_DEFINITIONS} PRIVATE_LINK_LIBRARIES_EXT ${TMP_UTEST_PRIVATE_LINK_LIBRARIES_EXT} ) OpsTest_Level1_AddUTestAclnnCaseStatic( BRIEF ${TMP_BRIEF} SNAKE ${TMP_SNAKE} TILING_DATA_DEF_BRIEF ${TMP_TILING_DATA_DEF_BRIEF} SOURCES_EXT ${TMP_UTEST_ACLNN_SOURCES_EXT} SOURCES_EXT_FORCE ${TMP_UTEST_ACLNN_SOURCES_EXT_FORCE} PRIVATE_INCLUDES_EXT ${TMP_UTEST_ACLNN_PRIVATE_INCLUDES_EXT} PRIVATE_COMPILE_DEFINITIONS ${TMP_UTEST_ACLNN_PRIVATE_COMPILE_DEFINITIONS} PRIVATE_LINK_LIBRARIES_EXT ${TMP_UTEST_ACLNN_PRIVATE_LINK_LIBRARIES_EXT} ) endfunction() function(op_add_ut_subdirectory OP_UT_LIST OP_UT_DIR_LIST) set(_OP_UT_LIST) set(_OP_UT_DIR_LIST) file(GLOB OP_HOST_CMAKE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/**/**/tests/CMakeLists.txt") foreach(OP_CMAKE_FILE ${OP_HOST_CMAKE_FILES}) if ("${OP_CMAKE_FILE}" MATCHES "tests") get_filename_component(OP_HOST_DIR "${OP_CMAKE_FILE}" DIRECTORY) get_filename_component(OP_DIR "${OP_HOST_DIR}" DIRECTORY) else() get_filename_component(OP_DIR "${OP_CMAKE_FILE}" DIRECTORY) endif() get_filename_component(OP_NAME "${OP_DIR}" NAME) if (DEFINED ASCEND_OP_NAME AND NOT "${ASCEND_OP_NAME}" STREQUAL "") if (NOT "${ASCEND_OP_NAME}" STREQUAL "all" AND NOT "${ASCEND_OP_NAME}" STREQUAL "ALL") if (NOT ${OP_NAME} IN_LIST ASCEND_OP_NAME) continue() endif () endif () endif () list(APPEND _OP_UT_LIST ${OP_NAME}) list(APPEND _OP_UT_DIR_LIST ${OP_DIR}) endforeach() list(REMOVE_DUPLICATES _OP_UT_LIST) list(REMOVE_DUPLICATES _OP_UT_DIR_LIST) list(SORT _OP_UT_LIST) list(SORT _OP_UT_DIR_LIST) set(${OP_UT_LIST} ${_OP_UT_LIST} PARENT_SCOPE) set(${OP_UT_DIR_LIST} ${_OP_UT_DIR_LIST} PARENT_SCOPE) endfunction() # 私有函数, 外部不可直接调用, 用于执行包含多个算子的 UT 可执行程序 #[[ ]] function(OpsTest_RunLaunch) cmake_parse_arguments( TMP "" "TARGET;EXECUTABLE" "" "" ${ARGN} ) if (ENABLE_UT_EXEC) set(LD_LIBRARY_PATH_ "LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:${ASCEND_CANN_PACKAGE_PATH}/compiler/lib64:${ASCEND_CANN_PACKAGE_PATH}/toolkit/tools/simulator/Ascend910B1/lib") if (ENABLE_ASAN OR ENABLE_UBSAN) if (ENABLE_ASAN) # 谨慎修改 ASAN_OPTIONS_ 取值, 当前出现告警会使 UT 失败. # halt_on_error=1, 出现告警时停止运行进而触发构建失败, 避免主进程或 CPU孪生调试 fork 出的子进程出现错误无法发现的情况 # detect_stack_use_after_return=1, 栈空间返回后使用检测 # check_initialization_order, 尝试捕获初始化顺序问题 # strict_init_order, 动态初始化器永远不能访问来自其他模块的全局变量, 及时或者已经初始化 # strict_string_checks, 检查字符串参数是否正确以 null 终止 # detect_leaks=1, 内存泄漏检测 set(ASAN_OPTIONS_ "ASAN_OPTIONS=halt_on_error=1,detect_stack_use_after_return=1,check_initialization_order=1,strict_init_order=1,strict_string_checks=1,detect_leaks=1") message(STATUS "${TMP_EXECUTABLE}: ${ASAN_OPTIONS_}") endif () if (ENABLE_UBSAN) # 谨慎修改 UBSAN_OPTIONS_ 取值, 当前出现告警会使 UT 失败. # halt_on_error=1, 出现告警时停止运行进而触发构建失败, 避免主进程或 CPU孪生调试 fork 出的子进程出现错误无法发现的情况 # print_stacktrace=1, 出错时打印调用栈 set(UBSAN_OPTIONS_ "UBSAN_OPTIONS=halt_on_error=1,print_stacktrace=1") message(STATUS "${TMP_EXECUTABLE}: ${UBSAN_OPTIONS_}") endif () # 用例执行 # 采用链接 ASAN/MSAN 动态库方式执行, 受 SAN 机制限制, 若采用静态库, 则会导致如 OpTiling/OpProto 内 SAN 功能失效. if (NOT "${SAN_LD_PRELOAD}" STREQUAL "") message(STATUS "${SAN_LD_PRELOAD}") endif () if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") add_custom_command( TARGET ${TMP_TARGET} POST_BUILD COMMAND export ${LD_LIBRARY_PATH_} && ulimit -s 32768 && ${ASAN_OPTIONS_} ${UBSAN_OPTIONS_} ./${TMP_EXECUTABLE} COMMENT "Run ${TMP_EXECUTABLE} with Sanitizer, ASAN(${ENABLE_ASAN}), UBSAN(${ENABLE_UBSAN})" ) else () add_custom_command( TARGET ${TMP_TARGET} POST_BUILD COMMAND export ${LD_LIBRARY_PATH_} && export ${SAN_LD_PRELOAD} && ulimit -s 32768 && ${ASAN_OPTIONS_} ${UBSAN_OPTIONS_} ./${TMP_EXECUTABLE} COMMENT "Run ${TMP_EXECUTABLE} with Sanitizer, ASAN(${ENABLE_ASAN}), UBSAN(${ENABLE_UBSAN})" ) endif () else() # 用例执行 add_custom_command( TARGET ${TMP_TARGET} POST_BUILD COMMAND export ${LD_LIBRARY_PATH_} && ./${TMP_EXECUTABLE} COMMENT "Run ${TMP_EXECUTABLE}" ) endif () endif () endfunction() # 生成覆盖率 #[[ 调用参数: one_value_keywords: TARGET : 必选参数, 用于指定覆盖率生成所依赖的目标(POST_BUILD) multi_value_keywords: FILTER_DIRECTORIES : 可选参数, 用于指定覆盖率结果过滤目录 ]] function(OpsTest_GenerateCoverage) cmake_parse_arguments( TMP "" "TARGET" "FILTER_DIRECTORIES" "" ${ARGN} ) if (ENABLE_UT_EXEC) if (ENABLE_GCOV) find_program(LCOV lcov REQUIRED) get_filename_component(GEN_COV_PY ${OPS_ADV_CMAKE_DIR}/scripts/utest/gen_coverage.py REALPATH) get_filename_component(ASCEND_CANN_PACKAGE_PATH_PARENT "${ASCEND_CANN_PACKAGE_PATH}/../" REALPATH) get_filename_component(GEM_COV_DATA_DIR "${CMAKE_CURRENT_BINARY_DIR}" REALPATH) # 获取 gcc 默认头文件搜索路径 execute_process( COMMAND ${CMAKE_C_COMPILER} --print-sysroot-headers-suffix RESULT_VARIABLE _RST OUTPUT_VARIABLE _SUFFIX ERROR_QUIET ) if (_RST) get_filename_component(SYS_ROOT "/usr/include" REALPATH) else () get_filename_component(SYS_ROOT "${_SUFFIX}/usr/include" REALPATH) endif () list(REMOVE_DUPLICATES _FilterCmds) add_custom_command( TARGET ${TMP_TARGET} POST_BUILD COMMAND ${HI_PYTHON} ${GEN_COV_PY} "-s=${OPS_ADV_DIR}" "-c=${GEM_COV_DATA_DIR}" "-f=/tmp/*" "-f=/usr/include/*" "-f=${ASCEND_CANN_PACKAGE_PATH_PARENT}/*" "-y=${OPS_ADV_DIR}/tests/test_config.yaml" COMMENT "Generate coverage for ${TMP_TARGET}" ) endif () endif () endfunction() # 生成包含多个算子的 UT 可执行程序 #[[ ]] function(OpsTest_AddLaunch) add_custom_target(ops_test_utest) if (NOT _OpsTestUt_UTestCaseLibraries AND NOT _OpsTestUt_UTestAclnnCaseLibraries) # 当 _OpsTestUt_UTestCaseLibraries 与 _OpsTestUt_UTestAclnnCaseLibraries 都为空时 # 说明区分领域的 TESTS_UT_OPS_TEST 选项被错误设置, 需排查对应触发 ut 的 python 脚本逻辑及 build.sh. message(STATUS "_OpsTestUt_UTestCaseLibraries = ${_OpsTestUt_UTestCaseLibraries}.") message(STATUS "_OpsTestUt_UTestAclnnCaseLibraries = ${_OpsTestUt_UTestAclnnCaseLibraries}") message(STATUS "_OpsTestUt_UTestCaseLibraries and _OpsTestUt_UTestAclnnCaseLibraries both empty.") return () endif () set(_UTest_OpApiLibrary) set(_UTest_OpProtoLibrary) set(_UTest_OpTilingLibrary) set(_UTest_Main) # UTest 用例可执行程序(常规) set(_UTest_Main_Aclnn) # UTest 用例可执行程序(Aclnn) set(_Utest_ExecutableList) # 为提高PR场景执行效率, PR场景各可执行文件并行执行, 否则串行执行 # OpApi 动态库(可选) OpsTest_AddOpApiShared() # OpProto 动态库(可选) OpsTest_AddOpProtoShared() # OpTiling 动态库(必选) OpsTest_AddOpTilingShared() # UTest 用例可执行程序(常规) if (_OpsTestUt_UTestCaseLibraries) # 支持按算子分离可执行文件, 便于彼此冲突的 Kernel 侧编译宏设置 foreach (_OpsTestUt_UTestCaseLibrary ${_OpsTestUt_UTestCaseLibraries}) # 获取算子工程名 string(REPLACE "_UTest_Case" "" _OpBrief ${_OpsTestUt_UTestCaseLibrary}) string(REPLACE "UTest_" "" _OpBrief ${_OpBrief}) set(_UTest_Main ${UTest_NamePrefix}_Main_Normal_${_OpBrief}) add_executable(${_UTest_Main}) target_sources(${_UTest_Main} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/ut/framework_special/main.cpp) target_compile_options(${_UTest_Main} PRIVATE -fPIC) target_link_libraries(${_UTest_Main} PRIVATE -Wl,--no-as-needed -Wl,--whole-archive $ gtest $ ${_OpsTestUt_UTestCaseLibrary} ${UTest_NamePrefix}_Stubs ${UTest_NamePrefix}_Utils ${_UTest_OpApiLibrary} # 若算子在 UTest_{Op}_Common 内实现 Aclnn 相关执行逻辑, 则需要连接 -Wl,--as-needed -Wl,--no-whole-archive c_sec ) add_dependencies(${_UTest_Main} ${_UTest_OpTilingLibrary}) add_dependencies(ops_test_utest ${_UTest_Main}) if (TESTS_UT_OPS_TEST_CI_PR) OpsTest_RunLaunch(TARGET ${_UTest_Main} EXECUTABLE ${_UTest_Main}) else () list(APPEND _Utest_ExecutableList ${_UTest_Main}) endif () endforeach () endif () # UTest 用例可执行程序(Aclnn) set(_param "--cann_path=${ASCEND_CANN_PACKAGE_PATH}" "--cann_package_name=opp" "get_package_version" ) if (_OpsTestUt_UTestAclnnCaseLibraries) # 支持按算子分离可执行文件, 便于彼此冲突的 Kernel 侧编译宏设置 foreach (_OpsTestUt_UTestAclnnCaseLibrary ${_OpsTestUt_UTestAclnnCaseLibraries}) # 获取算子工程名 string(REPLACE "_UTest_Case_Aclnn" "" _OpBrief ${_OpsTestUt_UTestAclnnCaseLibrary}) string(REPLACE "UTest_" "" _OpBrief ${_OpBrief}) set(_UTest_Main_Aclnn ${UTest_NamePrefix}_Main_Aclnn_${_OpBrief}) add_executable(${_UTest_Main_Aclnn}) target_sources(${_UTest_Main_Aclnn} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/ut/framework_special/main_aclnn.cpp) target_compile_options(${_UTest_Main_Aclnn} PRIVATE -fPIC) target_link_libraries(${_UTest_Main_Aclnn} PRIVATE -Wl,--no-as-needed -Wl,--whole-archive $ gtest $ $<$:$> $<$:$> ${_OpsTestUt_UTestAclnnCaseLibrary} ${UTest_NamePrefix}_Stubs ${UTest_NamePrefix}_Utils ${_UTest_OpApiLibrary} -Wl,--as-needed -Wl,--no-whole-archive c_sec ) add_dependencies(${_UTest_Main_Aclnn} ${_UTest_OpProtoLibrary} ${_UTest_OpTilingLibrary}) add_dependencies(ops_test_utest ${_UTest_Main_Aclnn}) if (TESTS_UT_OPS_TEST_CI_PR) OpsTest_RunLaunch(TARGET ${_UTest_Main_Aclnn} EXECUTABLE ${_UTest_Main_Aclnn}) else () list(APPEND _Utest_ExecutableList ${_UTest_Main_Aclnn}) endif () endforeach () endif () # 为提高PR场景执行效率, PR场景各可执行文件并行执行, 否则串行执行 if (NOT TESTS_UT_OPS_TEST_CI_PR) foreach (_Exe ${_Utest_ExecutableList}) OpsTest_RunLaunch(TARGET ops_test_utest EXECUTABLE ${_Exe}) endforeach () endif () # 生成覆盖率 set(_FilterDirectories) list(REMOVE_DUPLICATES _FilterDirectories) OpsTest_GenerateCoverage(TARGET ops_test_utest FILTER_DIRECTORIES ${_FilterDirectories}) endfunction() # 添加算子UT路径 #[[ ]] function(OpsTestUt_AddSubdirectory) cmake_parse_arguments( TMP "" "" "CLANG_NOT_SUPPORTED_OP_LIST" "" ${ARGN} ) if ("${TESTS_UT_OPS_TEST}" STREQUAL "") return() elseif ("ALL" IN_LIST TESTS_UT_OPS_TEST OR "all" IN_LIST TESTS_UT_OPS_TEST) file(GLOB sub_dirs ${CMAKE_CURRENT_SOURCE_DIR}/*) foreach (_dir ${sub_dirs}) if (IS_DIRECTORY ${_dir}) get_filename_component(_op_type ${_dir} NAME) if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" AND "${_op_type}" IN_LIST TMP_CLANG_NOT_SUPPORTED_OP_LIST) message(STATUS "The UTest of ${_op_type} don't supported clang compiler yet.") continue() endif () add_subdirectory(${_dir}) endif () endforeach () else () set(_added_op_type_list) foreach (_op_type ${TESTS_UT_OPS_TEST}) if (DEFINED ${_op_type}_alias) set(_op_type ${${_op_type}_alias}) endif () if (NOT "${_op_type}" IN_LIST _added_op_type_list) set(_dir ${CMAKE_CURRENT_SOURCE_DIR}/${_op_type}) if (IS_DIRECTORY ${_dir}) if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" AND "${_op_type}" IN_LIST TMP_CLANG_NOT_SUPPORTED_OP_LIST) message(STATUS "The UTest of ${_op_type} don't supported clang compiler yet.") continue() endif () add_subdirectory(${_dir}) list(APPEND _added_op_type_list ${_op_type}) endif () endif () endforeach () endif () endfunction()