# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
###################################################################################################
# copy kernel src to tbe/ascendc path
###################################################################################################
function(kernel_src_copy)
set(oneValueArgs TARGET DST_DIR)
set(multiValueArgs IMPL_DIR)
cmake_parse_arguments(KNCPY "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
add_custom_target(${KNCPY_TARGET})
foreach(OP_DIR ${KNCPY_IMPL_DIR})
get_filename_component(OP_NAME ${OP_DIR} NAME)
message(STATUS "start copy kernel file: ${OP_NAME} to ${KNCPY_DST_DIR}")
if(NOT TARGET ${OP_NAME}_src_copy)
set(SRC_DIR ${OP_DIR}/op_kernel)
if(NOT EXISTS ${SRC_DIR})
continue()
endif()
add_custom_target(${OP_NAME}_src_copy
COMMAND ${CMAKE_COMMAND} -E make_directory ${KNCPY_DST_DIR}/${OP_NAME}
COMMAND bash -c "find ${SRC_DIR} -mindepth 1 -maxdepth 1 -exec cp -r {} ${KNCPY_DST_DIR}/${OP_NAME} \\;"
VERBATIM
)
add_dependencies(${KNCPY_TARGET} ${OP_NAME}_src_copy)
if(ENABLE_PACKAGE)
install(
DIRECTORY ${SRC_DIR}/
DESTINATION ${IMPL_INSTALL_DIR}/${OP_NAME}
)
endif()
endif()
endforeach()
endfunction()
###################################################################################################
# generate operator dynamic python script for compile, generenate out path ${CMAKE_BINARY_DIR}/tbe,
# and install to packages/vendors/${VENDOR_NAME}_transformer/op_impl/ai_core/tbe/${VENDOR_NAME}_impl/dynamic
###################################################################################################
function(add_ops_impl_target)
set(oneValueArgs TARGET OPS_INFO_DIR IMPL_DIR OUT_DIR INSTALL_DIR)
cmake_parse_arguments(OPIMPL "" "${oneValueArgs}" "OPS_BATCH;OPS_ITERATE" ${ARGN})
add_custom_command(OUTPUT ${OPIMPL_OUT_DIR}/.impl_timestamp
COMMAND mkdir -m 700 -p ${OPIMPL_OUT_DIR}/dynamic
COMMAND ${ASCEND_PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/util/ascendc_impl_build.py
\"\" \"${OPIMPL_OPS_BATCH}\" \"${OPIMPL_OPS_ITERATE}\"
${OPIMPL_IMPL_DIR} ${OPIMPL_OUT_DIR}/dynamic ${ASCEND_AUTOGEN_PATH}
--opsinfo-dir ${OPIMPL_OPS_INFO_DIR} ${OPIMPL_OPS_INFO_DIR}/inner ${OPIMPL_OPS_INFO_DIR}/exc
COMMAND rm -rf ${OPIMPL_OUT_DIR}/.impl_timestamp
COMMAND touch ${OPIMPL_OUT_DIR}/.impl_timestamp
DEPENDS ${CMAKE_SOURCE_DIR}/scripts/util/ascendc_impl_build.py
)
add_custom_target(${OPIMPL_TARGET} ALL
DEPENDS ${OPIMPL_OUT_DIR}/.impl_timestamp
)
file(GLOB dynamic_impl ${OPIMPL_OUT_DIR}/dynamic/*.py)
if(ENABLE_PACKAGE)
install(
FILES ${dynamic_impl}
DESTINATION ${OPIMPL_INSTALL_DIR}
OPTIONAL
)
endif()
endfunction()
###################################################################################################
# generate aic-${compute_unit}-ops-info.json from aic-${compute_unit}-ops-info.ini
# generate outpath: ${CMAKE_BINARY_DIR}/tbe/op_info_cfg/ai_core/${compute_unit}/
# install path: packages/vendors/${VENDOR_NAME}_transformer/op_impl/ai_core/tbe/config/${compute_unit}
###################################################################################################
function(add_ops_info_target)
set(oneValueArgs TARGET OPS_INFO_DIR COMPUTE_UNIT OUTPUT INSTALL_DIR)
cmake_parse_arguments(OPINFO "" "${oneValueArgs}" "" ${ARGN})
get_filename_component(opinfo_file_path "${OPINFO_OUTPUT}" DIRECTORY)
add_custom_command(OUTPUT ${OPINFO_OUTPUT}
COMMAND mkdir -p ${opinfo_file_path}
COMMAND ${ASCEND_PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/util/parse_ini_to_json.py
${OPINFO_OPS_INFO_DIR}/aic-${OPINFO_COMPUTE_UNIT}-ops-info.ini
${OPINFO_OPS_INFO_DIR}/inner/aic-${OPINFO_COMPUTE_UNIT}-ops-info.ini
${OPINFO_OPS_INFO_DIR}/exc/aic-${OPINFO_COMPUTE_UNIT}-ops-info.ini
${OPINFO_OUTPUT}
)
add_custom_target(${OPINFO_TARGET} ALL
DEPENDS ${OPINFO_OUTPUT}
)
if(ENABLE_PACKAGE)
install(FILES ${OPINFO_OUTPUT}
DESTINATION ${OPINFO_INSTALL_DIR}
)
endif()
endfunction()
###################################################################################################
# merge ops info ini in aclnn/aclnn_inner/aclnn_exc to a total ini file
# srcpath: ${ASCEND_AUTOGEN_PATH}
# generate outpath: ${CMAKE_BINARY_DIR}/tbe/config
###################################################################################################
function(merge_ini_files)
set(oneValueArgs TARGET OPS_INFO_DIR COMPUTE_UNIT)
cmake_parse_arguments(MGINI "" "${oneValueArgs}" "" ${ARGN})
add_custom_command(OUTPUT ${ASCEND_KERNEL_CONF_DST}/aic-${MGINI_COMPUTE_UNIT}-ops-info.ini
COMMAND touch ${MGINI_OPS_INFO_DIR}/aic-merged-${MGINI_COMPUTE_UNIT}-ops-info.ini
COMMAND ${ASCEND_PYTHON_EXECUTABLE} ${OPS_KERNEL_BINARY_SCRIPT}/merge_ini_files.py
${MGINI_OPS_INFO_DIR}/aic-${MGINI_COMPUTE_UNIT}-ops-info.ini
${MGINI_OPS_INFO_DIR}/inner/aic-${MGINI_COMPUTE_UNIT}-ops-info.ini
${MGINI_OPS_INFO_DIR}/exc/aic-${MGINI_COMPUTE_UNIT}-ops-info.ini
--output-file ${ASCEND_KERNEL_CONF_DST}/aic-${MGINI_COMPUTE_UNIT}-ops-info.ini
)
add_custom_target(${MGINI_TARGET} ALL
DEPENDS ${ASCEND_KERNEL_CONF_DST}/aic-${MGINI_COMPUTE_UNIT}-ops-info.ini
)
endfunction()
# ##################################################################################################
# merge ops proto headers in aclnn/aclnn_inner/aclnn_exc to a total proto file
# srcpath: ${ASCEND_AUTOGEN_PATH}
# generate outpath: ${CMAKE_BINARY_DIR}/tbe/graph
# ##################################################################################################
function(merge_graph_headers)
set(oneValueArgs TARGET OUT_DIR)
cmake_parse_arguments(MGPROTO "" "${oneValueArgs}" "" ${ARGN})
get_target_property(proto_headers ${GRAPH_PLUGIN_NAME}_proto_headers INTERFACE_SOURCES)
add_custom_command(OUTPUT ${MGPROTO_OUT_DIR}/ops_proto_math.h
COMMAND ${ASCEND_PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/util/merge_proto.py
${proto_headers}
--output-file ${MGPROTO_OUT_DIR}/ops_proto_math.h
)
add_custom_target(${MGPROTO_TARGET} ALL
DEPENDS ${MGPROTO_OUT_DIR}/ops_proto_math.h
)
endfunction()
###################################################################################################
# generate binary compile shell script and binary json
# srcpath: ${ASCEND_AUTOGEN_PATH}
# outpath: ${CMAKE_BINARY_DIR}/binary/${compute_unit}
###################################################################################################
function(generate_bin_scripts)
set(oneValueArgs TARGET OP_NAME OPS_INFO_DIR COMPUTE_UNIT OUT_DIR)
cmake_parse_arguments(GENBIN "" "${oneValueArgs}" "" ${ARGN})
file(MAKE_DIRECTORY ${GENBIN_OUT_DIR}/gen)
file(MAKE_DIRECTORY ${GENBIN_OUT_DIR}/gen/${GENBIN_OP_NAME})
message(STATUS "start generate_bin_scripts for op: ${GENBIN_OP_NAME}")
add_custom_target(generate_bin_scripts_${GENBIN_COMPUTE_UNIT}_${GENBIN_OP_NAME}
COMMAND ${ASCEND_PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/util/ascendc_bin_param_build.py
${GENBIN_OPS_INFO_DIR}/aic-${GENBIN_COMPUTE_UNIT}-ops-info.ini
${GENBIN_OUT_DIR}/gen/${GENBIN_OP_NAME} ${GENBIN_COMPUTE_UNIT}
--opc-config-file ${ASCEND_AUTOGEN_PATH}/${CUSTOM_OPC_OPTIONS}
--ops ${GENBIN_OP_NAME}
COMMAND ${ASCEND_PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/util/ascendc_bin_param_build.py
${GENBIN_OPS_INFO_DIR}/inner/aic-${GENBIN_COMPUTE_UNIT}-ops-info.ini
${GENBIN_OUT_DIR}/gen/${GENBIN_OP_NAME} ${GENBIN_COMPUTE_UNIT}
--opc-config-file ${ASCEND_AUTOGEN_PATH}/${CUSTOM_OPC_OPTIONS}
--ops ${GENBIN_OP_NAME}
COMMAND ${ASCEND_PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/util/ascendc_bin_param_build.py
${GENBIN_OPS_INFO_DIR}/exc/aic-${GENBIN_COMPUTE_UNIT}-ops-info.ini
${GENBIN_OUT_DIR}/gen/${GENBIN_OP_NAME} ${GENBIN_COMPUTE_UNIT}
--opc-config-file ${ASCEND_AUTOGEN_PATH}/${CUSTOM_OPC_OPTIONS}
--ops ${GENBIN_OP_NAME}
)
if(NOT TARGET ${GENBIN_TARGET})
add_custom_target(${GENBIN_TARGET})
endif()
add_dependencies(${GENBIN_TARGET} generate_bin_scripts_${GENBIN_COMPUTE_UNIT}_${GENBIN_OP_NAME}
)
endfunction()
###################################################################################################
# copy binary config from op_host/config to tbe/config path
###################################################################################################
function(binary_config_copy)
set(oneValueArgs TARGET OP_NAME CONF_DIR DST_DIR COMPUTE_UNIT)
cmake_parse_arguments(CNFCPY "" "${oneValueArgs}" "" ${ARGN})
file(MAKE_DIRECTORY ${CNFCPY_DST_DIR}/${CNFCPY_COMPUTE_UNIT}/${CNFCPY_OP_NAME})
add_custom_target(${CNFCPY_TARGET}
COMMAND rm -rf ${CNFCPY_DST_DIR}/${CNFCPY_COMPUTE_UNIT}/${CNFCPY_OP_NAME}/*
COMMAND cp -r ${CNFCPY_CONF_DIR}/${CNFCPY_COMPUTE_UNIT}/* ${CNFCPY_DST_DIR}/${CNFCPY_COMPUTE_UNIT}/${CNFCPY_OP_NAME}
)
endfunction()
###################################################################################################
# compile binary from op_host/config binary json files
# generate outpath: ${CMAKE_BINARY_DIR}/binary/${compute_unit}/bin
# install path: ${BIN_KERNEL_INSTALL_DIR}/${compute_unit}
###################################################################################################
function(compile_from_config)
set(oneValueArgs TARGET OP_NAME OPS_INFO_DIR IMPL_DIR CONFIG_DIR OP_PYTHON_DIR OUT_DIR INSTALL_DIR COMPUTE_UNIT)
cmake_parse_arguments(CONFCMP "" "${oneValueArgs}" "" ${ARGN})
file(MAKE_DIRECTORY ${CONFCMP_OUT_DIR}/src)
file(MAKE_DIRECTORY ${CONFCMP_OUT_DIR}/bin)
file(MAKE_DIRECTORY ${CONFCMP_OUT_DIR}/gen)
snake_to_camel("${CONFCMP_OP_NAME}" OP_TYPE)
message(STATUS "start to compile op: ${CONFCMP_OP_NAME}, op_type: ${OP_TYPE}")
# add Environment Variable Configurations of python & ccache
set(_ASCENDC_ENV_VAR)
list(APPEND _ASCENDC_ENV_VAR export HI_PYTHON=${ASCEND_PYTHON_EXECUTABLE} &&)
# whether need judging CMAKE_C_COMPILER_LAUNCHER
if(${CMAKE_CXX_COMPILER_LAUNCHER} MATCHES "ccache$")
list(APPEND _ASCENDC_ENV_VAR export ASCENDC_CCACHE_EXECUTABLE=${CMAKE_CXX_COMPILER_LAUNCHER} &&)
endif()
# copy binary config file to tbe/config
binary_config_copy(
TARGET bin_conf_${CONFCMP_OP_NAME}_${CONFCMP_COMPUTE_UNIT}_copy
OP_NAME ${CONFCMP_OP_NAME}
CONF_DIR ${CONFCMP_CONFIG_DIR}
DST_DIR ${ASCEND_KERNEL_CONF_DST}
COMPUTE_UNIT ${CONFCMP_COMPUTE_UNIT}
)
add_custom_target(config_compile_${CONFCMP_COMPUTE_UNIT}_${CONFCMP_OP_NAME}
COMMAND ${_ASCENDC_ENV_VAR} bash ${OPS_KERNEL_BINARY_SCRIPT}/build_binary_single_op.sh
${OP_TYPE}
${CONFCMP_COMPUTE_UNIT}
${CONFCMP_OUT_DIR}/bin
WORKING_DIRECTORY ${OPS_KERNEL_BINARY_SCRIPT}
DEPENDS ${ASCEND_KERNEL_CONF_DST}/aic-${CONFCMP_COMPUTE_UNIT}-ops-info.ini
ascendc_kernel_src_copy
bin_conf_${CONFCMP_OP_NAME}_${CONFCMP_COMPUTE_UNIT}_copy
)
if(NOT TARGET binary)
add_custom_target(binary)
endif()
add_custom_target(${CONFCMP_TARGET}
COMMAND cp -r ${CONFCMP_IMPL_DIR}/*.* ${CONFCMP_OUT_DIR}/src
COMMAND cp ${CONFCMP_OP_PYTHON_DIR}/${CONFCMP_OP_NAME}.py ${CONFCMP_OUT_DIR}/src
)
add_dependencies(binary config_compile_${CONFCMP_COMPUTE_UNIT}_${CONFCMP_OP_NAME} ${CONFCMP_TARGET})
if(ENABLE_PACKAGE)
install(DIRECTORY ${CONFCMP_OUT_DIR}/bin/${CONFCMP_COMPUTE_UNIT}/${CONFCMP_OP_NAME}
DESTINATION ${BIN_KERNEL_INSTALL_DIR}/${CONFCMP_COMPUTE_UNIT} OPTIONAL
)
install(FILES ${CONFCMP_OUT_DIR}/bin/config/${CONFCMP_COMPUTE_UNIT}/${CONFCMP_OP_NAME}.json
DESTINATION ${BIN_KERNEL_CONFIG_INSTALL_DIR}/${CONFCMP_COMPUTE_UNIT} OPTIONAL
)
endif()
endfunction()
###################################################################################################
# generate binary_info_config.json
# generate outpath: ${CMAKE_BINARY_DIR}/binary/${compute_unit}/bin/config
# install path: packages/vendors/${VENDOR_NAME}_transformer/op_impl/ai_core/tbe/kernel/config
###################################################################################################
function(gen_binary_info_config_json)
set(oneValueArgs TARGET BIN_DIR COMPUTE_UNIT)
cmake_parse_arguments(GENBIN_INFOCFG "" "${oneValueArgs}" "" ${ARGN})
add_custom_command(OUTPUT ${GENBIN_INFOCFG_BIN_DIR}/bin/config/${GENBIN_INFOCFG_COMPUTE_UNIT}/binary_info_config.json
COMMAND ${ASCEND_PYTHON_EXECUTABLE} ${OPS_KERNEL_BINARY_SCRIPT}/gen_binary_info_config.py
${GENBIN_INFOCFG_BIN_DIR}/bin
${GENBIN_INFOCFG_COMPUTE_UNIT}
DEPENDS ${GENBIN_INFOCFG_BIN_DIR}/bin/config
)
add_custom_target(${GENBIN_INFOCFG_TARGET}
DEPENDS ${GENBIN_INFOCFG_BIN_DIR}/bin/config/${GENBIN_INFOCFG_COMPUTE_UNIT}/binary_info_config.json
)
if(NOT TARGET gen_bin_info_config)
add_custom_target(gen_bin_info_config)
endif()
add_dependencies(gen_bin_info_config ${GENBIN_INFOCFG_TARGET})
if(ENABLE_PACKAGE)
install(
FILES ${GENBIN_INFOCFG_BIN_DIR}/bin/config/${GENBIN_INFOCFG_COMPUTE_UNIT}/binary_info_config.json
DESTINATION ${BIN_KERNEL_CONFIG_INSTALL_DIR}/${GENBIN_INFOCFG_COMPUTE_UNIT} OPTIONAL
)
endif()
endfunction()
# binary compile
function(gen_ops_info_and_python)
gen_aclnn_with_opdef()
if(NOT TARGET opbuild_custom_gen_aclnn_all)
message(STATUS "no need build binary, for all the ops do not have any operator def")
return()
endif()
kernel_src_copy(
TARGET ascendc_kernel_src_copy
OP_LIST ${COMPILED_OPS}
IMPL_DIR ${COMPILED_OP_DIRS}
DST_DIR ${ASCEND_KERNEL_SRC_DST}
)
add_ops_impl_target(
TARGET ascendc_impl_gen
OPS_INFO_DIR ${ASCEND_AUTOGEN_PATH}
IMPL_DIR ${ASCEND_KERNEL_SRC_DST}
OUT_DIR ${CMAKE_BINARY_DIR}/tbe
INSTALL_DIR ${IMPL_DYNAMIC_INSTALL_DIR}
)
merge_graph_headers(
TARGET merge_ops_proto ALL
OUT_DIR ${ASCEND_GRAPH_CONF_DST}
)
set(ascendc_impl_gen_depends ascendc_kernel_src_copy opbuild_custom_gen_aclnn_all)
foreach(compute_unit ${ASCEND_COMPUTE_UNIT})
# generate aic-${compute_unit}-ops-info.json, operator infos
add_ops_info_target(
TARGET ops_info_gen_${compute_unit}
OUTPUT ${CMAKE_BINARY_DIR}/tbe/op_info_cfg/ai_core/${compute_unit}/aic-${compute_unit}-ops-info.json
OPS_INFO_DIR ${ASCEND_AUTOGEN_PATH}
COMPUTE_UNIT ${compute_unit}
INSTALL_DIR ${OPS_INFO_INSTALL_DIR}
)
# merge ops info ini files
merge_ini_files(TARGET merge_ini_${compute_unit}
OPS_INFO_DIR ${ASCEND_AUTOGEN_PATH}
COMPUTE_UNIT ${compute_unit}
)
list(APPEND ascendc_impl_gen_depends ops_info_gen_${compute_unit})
endforeach()
add_dependencies(ascendc_impl_gen ${ascendc_impl_gen_depends})
if(ENABLE_BINARY OR ENABLE_CUSTOM)
foreach(compute_unit ${ASCEND_COMPUTE_UNIT})
foreach(OP_DIR ${COMPILED_OP_DIRS})
get_filename_component(op_name ${OP_DIR} NAME)
# generate opc shell scripts for autogen binary config ops
generate_bin_scripts(
TARGET gen_bin_scripts
OP_NAME ${op_name}
OPS_INFO_DIR ${ASCEND_AUTOGEN_PATH}
COMPUTE_UNIT ${compute_unit}
OUT_DIR ${CMAKE_BINARY_DIR}/binary/${compute_unit}
)
if(EXISTS ${OP_DIR}/op_host/config/${compute_unit}/${op_name}_binary.json)
# binary compile from binary json config
message(STATUS "[INFO] On [${compute_unit}], [${op_name}] compile binary with self config.")
compile_from_config(
TARGET ascendc_bin_${compute_unit}_${op_name}
OP_NAME ${op_name}
OPS_INFO_DIR ${ASCEND_AUTOGEN_PATH}
IMPL_DIR ${OP_DIR}/op_kernel
CONFIG_DIR ${OP_DIR}/op_host/config
OP_PYTHON_DIR ${CMAKE_BINARY_DIR}/tbe/dynamic
OUT_DIR ${CMAKE_BINARY_DIR}/binary/${compute_unit}
INSTALL_DIR ${BIN_KERNEL_INSTALL_DIR}
COMPUTE_UNIT ${compute_unit}
)
add_dependencies(ascendc_bin_${compute_unit}_${op_name} merge_ini_${compute_unit} ascendc_impl_gen)
endif()
endforeach()
# generate binary_info_config.json
gen_binary_info_config_json(
TARGET gen_bin_info_config_${compute_unit}
BIN_DIR ${CMAKE_BINARY_DIR}/binary/${compute_unit}
COMPUTE_UNIT ${compute_unit}
)
endforeach()
endif()
endfunction()