init v0.23.0

Signed-off-by: Sun Ruoxi <sunruoxi@4paradigm.com>
This commit is contained in:
2026-08-27 15:11:51 +08:00
parent b582a8e7d1
commit 7f8a1b1f7a
2849 changed files with 712887 additions and 22001 deletions

View File

@@ -0,0 +1,163 @@
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
import argparse
import logging
import os
import shutil
import sys
import regex as re
class OpGenerator:
"""算子工程生成器"""
def __init__(self, op_type, op_name, output_path):
self.op_type = op_type
self.op_name = op_name
self.output_path = output_path
self.template_name = "add_example"
self.script_dir = os.path.dirname(os.path.abspath(__file__))
self.template_dir = os.path.abspath(os.path.join(self.script_dir, "template", "add"))
self.dest_dir = os.path.abspath(os.path.join(self.output_path, self.op_type, self.op_name))
def run(self):
"""执行生成流程"""
self._validate_inputs()
self._copy_template()
self._rename_files()
self._replace_content()
logging.info("成功为 %s/%s 创建算子工程!", self.op_type, self.op_name)
logging.info("工程路径: %s", self.dest_dir)
logging.info("Create the initial directory for %s under %s success", self.op_name, self.op_type)
def _validate_inputs(self):
"""校验输入参数的有效性和安全性"""
if not self.op_type or not self.op_name:
raise ValueError("算子类型和算子名称均不能为空。")
if not re.match(r"^[a-zA-Z0-9_]+$", self.op_type):
raise ValueError(f"算子类型 '{self.op_type}' 包含无效字符。只允许字母、数字和下划线。")
if not re.match(r"^[a-zA-Z0-9_]+$", self.op_name):
raise ValueError(f"算子名称 '{self.op_name}' 包含无效字符。只允许字母、数字和下划线。")
if os.path.exists(self.dest_dir):
raise FileExistsError(f"目标目录 '{self.dest_dir}' 已存在。")
def _copy_template(self):
"""复制模板文件到目标目录"""
logging.info("使用模板在 '%s' 创建算子工程...", self.dest_dir)
if not os.path.exists(self.template_dir):
raise FileNotFoundError(f"找不到模板目录 '{self.template_dir}'。请确保 'template/add' 目录存在。")
try:
shutil.copytree(self.template_dir, self.dest_dir)
if not os.path.isfile(os.path.join(os.path.dirname(self.dest_dir), "CMakeLists.txt")):
cmake_src = os.path.join(os.path.dirname(self.template_dir), "CMakeLists.txt")
cmake_dest = os.path.join(os.path.dirname(self.dest_dir), "CMakeLists.txt")
shutil.copy2(cmake_src, cmake_dest)
except OSError as e:
raise OSError(f"复制模板文件失败: {e}") from e
def _rename_files(self):
"""重命名文件和目录中的占位符"""
for root, dirs, files in os.walk(self.dest_dir, topdown=False):
for name in files + dirs:
if self.template_name not in name:
continue
old_path = os.path.join(root, name)
new_name = name.replace(self.template_name, self.op_name)
new_path = os.path.join(root, new_name)
try:
os.rename(old_path, new_path)
except OSError as e:
raise OSError(f"重命名 '{old_path}''{new_path}' 失败: {e}") from e
def _replace_content_in_file(self, file_path, replacements):
"""Helper to replace content in a single file."""
try:
with open(file_path, encoding="utf-8", errors="ignore") as f:
content = f.read()
except OSError as e:
logging.warning("读取文件 '%s' 失败: %s", file_path, e)
return
original_content = content
for old, new in replacements.items():
content = content.replace(old, new)
if content == original_content:
return
try:
with open(file_path, "w", encoding="utf-8") as f:
f.write(content)
except OSError as e:
logging.warning("写入文件 '%s' 失败: %s", file_path, e)
def _replace_content(self):
"""替换文件内容中的占位符"""
op_name_capitalized = "".join(word.capitalize() for word in self.op_name.split("_"))
template_name_capitalized = "".join(word.capitalize() for word in self.template_name.split("_"))
replacements = {
self.template_name: self.op_name,
self.template_name.upper(): self.op_name.upper(),
template_name_capitalized: op_name_capitalized,
"add_example": self.op_name,
}
for root, _, files in os.walk(self.dest_dir):
for file in files:
if file.endswith((".pyc", ".pyo")):
continue
file_path = os.path.join(root, file)
self._replace_content_in_file(file_path, replacements)
def execute(args):
"""根据命令行参数执行算子生成"""
generator = OpGenerator(op_type=args.op_type, op_name=args.op_name, output_path=args.output_path)
generator.run()
def register_parser(subparsers):
"""为 opgen 命令注册解析器。"""
parser_opgen = subparsers.add_parser("opgen", help="生成项目骨架")
parser_opgen.add_argument("--op_type", "-t", required=True, help="算子分类,例如 math")
parser_opgen.add_argument("--op_name", "-n", required=True, help="新算子的名称,例如 asinh")
parser_opgen.add_argument("--output_path", "-p", default=".", help="生成工程的根路径")
parser_opgen.set_defaults(func=execute)
def main():
"""主函数,用于独立执行"""
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s", stream=sys.stdout)
parser = argparse.ArgumentParser(description="生成项目骨架")
parser.add_argument("--op_type", "-t", required=True, help="算子分类,例如 math")
parser.add_argument("--op_name", "-n", required=True, help="新算子的名称,例如 asinh")
parser.add_argument("--output_path", "-p", default=".", help="生成工程的根路径")
args = parser.parse_args()
try:
execute(args)
except Exception as e:
logging.error("发生非预期的错误,退出。错误信息: %s", e)
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,29 @@
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
set(OPTEST_NAME optest_${PKG_NAME})
file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
foreach(SUB_DIR ${CURRENT_DIRS})
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 ${SUB_DIR} IN_LIST ASCEND_OP_NAME)
continue()
endif ()
endif ()
endif ()
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
add_subdirectory(${SUB_DIR})
else()
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/op_host/CMakeLists.txt")
add_subdirectory(${SUB_DIR}/op_host)
endif()
endif()
endforeach()

View File

@@ -0,0 +1,19 @@
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
if(NOT ENABLE_TEST AND NOT BENCHMARK)
list(REMOVE_ITEM CURRENT_DIRS tests)
endif()
foreach(SUB_DIR ${CURRENT_DIRS})
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
add_subdirectory(${SUB_DIR})
endif()
endforeach()

View File

@@ -0,0 +1,166 @@
/**
 * 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.
 */
// 本文件参考example下示例自动生成
// 您可自由修改此文件满足需求
#include <iostream>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_add_example.h"
#define CHECK_RET(cond, return_expr) \
do { \
if (!(cond)) { \
return_expr; \
} \
} while (0)
#define LOG_PRINT(message, ...) \
do { \
printf(message, ##__VA_ARGS__); \
} while (0)
int64_t GetShapeSize(const std::vector<int64_t>& shape)
{
int64_t shapeSize = 1;
for (auto i : shape) {
shapeSize *= i;
}
return shapeSize;
}
void PrintOutResult(std::vector<int64_t>& shape, void** deviceAddr)
{
auto size = GetShapeSize(shape);
std::vector<float> resultData(size, 0);
auto ret = aclrtMemcpy(
resultData.data(), resultData.size() * sizeof(resultData[0]), *deviceAddr, size * sizeof(resultData[0]),
ACL_MEMCPY_DEVICE_TO_HOST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return);
for (int64_t i = 0; i < size; i++) {
LOG_PRINT("mean result[%ld] is: %f\n", i, resultData[i]);
}
}
int Init(int32_t deviceId, aclrtStream* stream)
{
// 固定写法,初始化
auto ret = aclInit(nullptr);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret);
ret = aclrtSetDevice(deviceId);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret);
ret = aclrtCreateStream(stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret);
return 0;
}
template <typename T>
int CreateAclTensor(
const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, aclDataType dataType,
aclTensor** tensor)
{
auto size = GetShapeSize(shape) * sizeof(T);
// 2. 申请device侧内存
auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
// 3. 调用aclrtMemcpy将host侧数据拷贝到device侧内存上
ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
// 计算连续tensor的strides
std::vector<int64_t> strides(shape.size(), 1);
for (int64_t i = shape.size() - 2; i >= 0; i--) {
strides[i] = shape[i + 1] * strides[i + 1];
}
// 调用aclCreateTensor接口创建aclTensor
*tensor = aclCreateTensor(
shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(),
*deviceAddr);
return 0;
}
int main()
{
// 1. 调用acl进行device/stream初始化
int32_t deviceId = 0;
aclrtStream stream;
auto ret = Init(deviceId, &stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
// 2. 构造输入与输出需要根据API的接口自定义构造
aclTensor* selfX = nullptr;
void* selfXDeviceAddr = nullptr;
std::vector<int64_t> selfXShape = {32, 4, 4, 4};
std::vector<float> selfXHostData(2048, 1); // 2048创建包含32*4*4*4=2048个元素的向量
ret = CreateAclTensor(selfXHostData, selfXShape, &selfXDeviceAddr, aclDataType::ACL_FLOAT, &selfX);
CHECK_RET(ret == ACL_SUCCESS, return ret);
aclTensor* selfY = nullptr;
void* selfYDeviceAddr = nullptr;
std::vector<int64_t> selfYShape = {32, 4, 4, 4};
std::vector<float> selfYHostData(2048, 1);
ret = CreateAclTensor(selfYHostData, selfYShape, &selfYDeviceAddr, aclDataType::ACL_FLOAT, &selfY);
CHECK_RET(ret == ACL_SUCCESS, return ret);
aclTensor* out = nullptr;
void* outDeviceAddr = nullptr;
std::vector<int64_t> outShape = {32, 4, 4, 4};
std::vector<float> outHostData(2048, 1);
ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// 3. 调用CANN算子库API需要修改为具体的Api名称
uint64_t workspaceSize = 0;
aclOpExecutor* executor;
// 4. 调用aclnnAddExample第一段接口
ret = aclnnAddExampleGetWorkspaceSize(selfX, selfY, out, &workspaceSize, &executor);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAddExampleGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
// 根据第一段接口计算出的workspaceSize申请device内存
void* workspaceAddr = nullptr;
if (workspaceSize > static_cast<uint64_t>(0)) {
ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret);
}
// 5. 调用aclnnAddExample第二段接口
ret = aclnnAddExample(workspaceAddr, workspaceSize, executor, stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAddExample failed. ERROR: %d\n", ret); return ret);
// 6. (固定写法)同步等待任务执行结束
ret = aclrtSynchronizeStream(stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
// 5. 获取输出的值将device侧内存上的结果拷贝至host侧需要根据具体API的接口定义修改
PrintOutResult(outShape, &outDeviceAddr);
// 7. 释放aclTensor需要根据具体API的接口定义修改
aclDestroyTensor(selfX);
aclDestroyTensor(selfY);
aclDestroyTensor(out);
// 8. 释放device资源
aclrtFree(selfXDeviceAddr);
aclrtFree(selfYDeviceAddr);
aclrtFree(outDeviceAddr);
if (workspaceSize > static_cast<uint64_t>(0)) {
aclrtFree(workspaceAddr);
}
aclrtDestroyStream(stream);
aclrtResetDevice(deviceId);
// 9. acl去初始化
aclFinalize();
return 0;
}

View File

@@ -0,0 +1,18 @@
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
add_op_to_compiled_list()
if (BUILD_OPEN_PROJECT)
target_sources(op_host_aclnn PRIVATE
add_example_def.cpp
)
endif()
add_modules_sources(OPTYPE add_example ACLNNTYPE aclnn)

View File

@@ -0,0 +1,55 @@
/**
 * 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.
 */
/*!
* \file add_example_def.cpp
* \brief
*/
#include "register/op_def_registry.h"
namespace ops {
class AddExample : public OpDef {
public:
explicit AddExample(const char* name) : OpDef(name)
{
// 输入参数说明
this->Input("x1") // 输入x1定义
.ParamType(REQUIRED) // 必选输入
.DataType({ge::DT_FLOAT, ge::DT_INT32}) // 支持数据类型
.Format({ge::FORMAT_ND, ge::FORMAT_ND}) // 支持format格式
.UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND}) // 未确定大小shape对应format格式
.AutoContiguous(); // 内存自动连续化
this->Input("x2") // 输入x2定义
.ParamType(REQUIRED)
.DataType({ge::DT_FLOAT, ge::DT_INT32})
.Format({ge::FORMAT_ND, ge::FORMAT_ND})
.UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND})
.AutoContiguous();
this->Output("y") // 输出y定义
.ParamType(REQUIRED)
.DataType({ge::DT_FLOAT, ge::DT_INT32})
.Format({ge::FORMAT_ND, ge::FORMAT_ND})
.UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND})
.AutoContiguous();
OpAICoreConfig aicoreConfig;
aicoreConfig.DynamicCompileStaticFlag(true)
.DynamicFormatFlag(false)
.DynamicRankSupportFlag(true)
.DynamicShapeSupportFlag(true)
.NeedCheckSupportFlag(false)
.PrecisionReduceFlag(true)
.ExtendCfgInfo("opFile.value", "add_example"); // 这里制定的值会对应到kernel入口文件名.cpp
this->AICore().AddConfig("ascend910b", aicoreConfig); // 其他的soc版本补充部分配置项
this->AICore().AddConfig("ascend910_93", aicoreConfig);
}
};
OP_ADD(AddExample); // 添加算子信息库
} // namespace ops

View File

@@ -0,0 +1,48 @@
/**
 * 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.
 */
/*!
* \file add_example_infer.cpp
* \brief
*/
#include "register/op_impl_registry.h"
#include "log/log.h"
using namespace ge;
namespace ops {
static constexpr int64_t IDX_0 = 0;
static ge::graphStatus InferShapeAddExample(gert::InferShapeContext* context)
{
OP_LOGD(context->GetNodeName(), "Begin to do InferShapeAddExample");
// get input shapes
const gert::Shape* xShape = context->GetInputShape(IDX_0);
OP_CHECK_NULL_WITH_CONTEXT(context, xShape);
// get output shapes
gert::Shape* yShape = context->GetOutputShape(IDX_0);
OP_CHECK_NULL_WITH_CONTEXT(context, yShape);
// 填充输出shape大小
auto xShapeSize = xShape->GetDimNum();
yShape->SetDimNum(xShapeSize);
for (size_t i = 0; i < xShapeSize; i++) {
int64_t dim = xShape->GetDim(i);
yShape->SetDim(i, dim);
}
OP_LOGD(context->GetNodeName(), "End to do InferShapeAddExample");
return GRAPH_SUCCESS;
}
IMPL_OP_INFERSHAPE(AddExample).InferShape(InferShapeAddExample);
} // namespace ops

View File

@@ -0,0 +1,156 @@
/**
 * 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.
 */
/*!
* \file add_example_tiling.cpp
* \brief
*/
#include "log/log.h"
#include "util/math_util.h"
#include "tiling_base/tiling_util.h"
#include "tiling_base/tiling_templates_registry.h"
#include "../op_kernel/add_example_tiling_data.h"
#include "../op_kernel/add_example_tiling_key.h"
namespace optiling {
using namespace Ops::Transformer::OpTiling;
const uint32_t BLOCK_DIM = 8;
const int64_t TILE_NUM = 8;
const uint32_t WS_SYS_SIZE = 16U * 1024U * 1024U;
const int32_t DIMS_LIMIT = 4;
constexpr int32_t ATTRPOS0 = 0;
constexpr uint32_t INDEXZERO = 0;
constexpr uint32_t INDEXONE = 1;
constexpr uint32_t INDEXTWO = 2;
constexpr uint32_t INDEXTHREE = 3;
struct AddExampleCompileInfo {};
// 获取平台信息如ubSize, coreNum
static ge::graphStatus GetPlatformInfo(gert::TilingContext* context, uint64_t& ubSize, int64_t& coreNum)
{
// 获取ubsize coreNum
fe::PlatFormInfos* platformInfoPtr = context->GetPlatformInfo();
OP_CHECK_NULL_WITH_CONTEXT(context, platformInfoPtr);
auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfoPtr);
coreNum = ascendcPlatform.GetCoreNumAiv();
OP_CHECK_IF(coreNum == 0, OP_LOGE(context, "coreNum is 0"), return ge::GRAPH_FAILED);
ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize);
OP_CHECK_IF(ubSize == 0, OP_LOGE(context, "ubSize is 0"), return ge::GRAPH_FAILED);
return ge::GRAPH_SUCCESS;
}
// 获取属性shape信息
ge::graphStatus GetShapeAttrsInfo(gert::TilingContext* context, int64_t& totalIdx, ge::DataType& dataType)
{
// 获取输入shape信息
auto inputX = context->GetInputShape(0);
OP_CHECK_NULL_WITH_CONTEXT(context, inputX);
// 如果输入shape 是标量 转换为{1},否则保持原 shape 不变
auto inputShapeX = EnsureNotScalar(inputX->GetStorageShape());
auto inputY = context->GetInputShape(1);
OP_CHECK_NULL_WITH_CONTEXT(context, inputY);
auto inputShapeY = EnsureNotScalar(inputY->GetStorageShape());
auto outZ = context->GetOutputShape(0);
OP_CHECK_NULL_WITH_CONTEXT(context, outZ);
auto outShapeZ = EnsureNotScalar(outZ->GetStorageShape());
// shape校验
OP_CHECK_IF(
inputShapeX.GetDimNum() != DIMS_LIMIT || inputShapeY.GetDimNum() != DIMS_LIMIT ||
outShapeZ.GetDimNum() != DIMS_LIMIT,
OP_LOGE(
context, "AddExample: inputx,inputy,outputz shape dim = %zu, %zu, %zu, should be equal 4",
inputShapeX.GetDimNum(), inputShapeY.GetDimNum(), outShapeZ.GetDimNum()),
return ge::GRAPH_FAILED);
// 获取shape dim值
auto nDim = inputShapeX.GetDim(INDEXZERO);
auto cDim = inputShapeX.GetDim(INDEXONE);
auto hDim = inputShapeX.GetDim(INDEXTWO);
auto wDim = inputShapeX.GetDim(INDEXTHREE);
totalIdx = nDim * cDim * hDim * wDim;
// dtype校验
const std::set<ge::DataType> supportedDtype = {ge::DT_FLOAT, ge::DT_INT32};
auto inputDesc = context->GetInputDesc(0);
OP_CHECK_NULL_WITH_CONTEXT(context, inputDesc);
dataType = inputDesc->GetDataType();
if (supportedDtype.count(dataType) == 0) {
OP_LOGE(context, "invalid dtype");
return ge::GRAPH_FAILED;
}
return ge::GRAPH_SUCCESS;
}
ge::graphStatus GetWorkspaceSize(gert::TilingContext* context)
{
size_t* currentWorkspace = context->GetWorkspaceSizes(1);
OP_CHECK_NULL_WITH_CONTEXT(context, currentWorkspace);
currentWorkspace[0] = WS_SYS_SIZE;
return ge::GRAPH_SUCCESS;
}
// tiling 分发入口
static ge::graphStatus AddExampleTilingFunc(gert::TilingContext* context)
{
// 1、获取平台运行信息
uint64_t ubSize;
int64_t coreNum;
OP_CHECK_IF(
GetPlatformInfo(context, ubSize, coreNum) != ge::GRAPH_SUCCESS, OP_LOGE(context, "GetPlatformInfo error"),
return ge::GRAPH_FAILED);
// 2、获取shape、属性信息
int64_t totalIdx;
ge::DataType dataType;
OP_CHECK_IF(
GetShapeAttrsInfo(context, totalIdx, dataType) != ge::GRAPH_SUCCESS,
OP_LOGE(context, "GetShapeAttrsInfo error"), return ge::GRAPH_FAILED);
// 3、获取WorkspaceSize信息
OP_CHECK_IF(
GetWorkspaceSize(context) != ge::GRAPH_SUCCESS, OP_LOGE(context, "GetWorkspaceSize error"),
return ge::GRAPH_FAILED);
// 4、设置tiling信息
AddExampleTilingData* tiling = context->GetTilingData<AddExampleTilingData>();
OP_CHECK_NULL_WITH_CONTEXT(context, tiling);
OP_CHECK_IF(
memset_s(tiling, sizeof(AddExampleTilingData), 0, sizeof(AddExampleTilingData)) != EOK,
OP_LOGE(context, "set tiling data error"), return ge::GRAPH_FAILED);
tiling->totalLength = totalIdx;
tiling->tileNum = TILE_NUM;
context->SetBlockDim(BLOCK_DIM);
uint64_t tilingKey = 0;
// 区分dtype走不同得tiling key分支.
if (dataType == ge::DT_FLOAT) {
tilingKey = GET_TPL_TILING_KEY(ELEMENTWISE_TPL_SCH_MODE_0);
context->SetTilingKey(tilingKey);
} else if (dataType == ge::DT_INT32) {
tilingKey = GET_TPL_TILING_KEY(ELEMENTWISE_TPL_SCH_MODE_1);
context->SetTilingKey(tilingKey);
} else {
OP_LOGE(context, "get dtype error");
return ge::GRAPH_FAILED;
}
return ge::GRAPH_SUCCESS;
}
static ge::graphStatus TilingParseForAddExample([[maybe_unused]] gert::TilingParseContext* context)
{
return ge::GRAPH_SUCCESS;
}
// tiling注册入口.
IMPL_OP_OPTILING(AddExample).Tiling(AddExampleTilingFunc).TilingParse<AddExampleCompileInfo>(TilingParseForAddExample);
} // namespace optiling

View File

@@ -0,0 +1,43 @@
/**
 * 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.
 */
/*!
* \file add_example.cpp
* \brief
*/
#include "add_example.h"
enum class AddExampleTilingKey : uint32_t
{
TILING_KEY_EXAMPLE_FLOAT = 0,
TILING_KEY_EXAMPLE_INT32 = 1,
};
template <uint32_t schMode>
__global__ __aicore__ void add_example(GM_ADDR x, GM_ADDR y, GM_ADDR z, GM_ADDR workspace, GM_ADDR tiling)
{
REGISTER_TILING_DEFAULT(AddExampleTilingData);
GET_TILING_DATA_WITH_STRUCT(AddExampleTilingData, tilingData, tiling);
// 场景1
if constexpr (schMode == static_cast<uint32_t>(AddExampleTilingKey::TILING_KEY_EXAMPLE_FLOAT)) {
NsAddExample::AddExample<float> op; // 算子kernel实例获取
op.Init(x, y, z, &tilingData); // 算子kernel实例初始化
op.Process(); // 算子kernel实例执行
}
// 场景2
if constexpr (schMode == static_cast<uint32_t>(AddExampleTilingKey::TILING_KEY_EXAMPLE_INT32)) {
NsAddExample::AddExample<int32_t> op; // 算子kernel实例获取
op.Init(x, y, z, &tilingData); // 算子kernel实例初始化
op.Process(); // 算子kernel实例执行
}
}

View File

@@ -0,0 +1,117 @@
/**
 * 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.
 */
/*!
* \file add_example.h
* \brief
*/
#ifndef ADD_EXAMPLE_H
#define ADD_EXAMPLE_H
#include "kernel_operator.h"
#include "kernel_tiling/kernel_tiling.h"
#include "add_example_tiling_data.h"
#include "add_example_tiling_key.h"
namespace NsAddExample {
using namespace AscendC;
constexpr int32_t BUFFER_NUM = 2;
template <typename T>
class AddExample
{
public:
__aicore__ inline AddExample(){};
__aicore__ inline void Init(GM_ADDR x, GM_ADDR y, GM_ADDR z, const AddExampleTilingData* tilingData);
__aicore__ inline void Process();
private:
__aicore__ inline void CopyIn(int32_t progress);
__aicore__ inline void CopyOut(int32_t progress);
__aicore__ inline void Compute(const int32_t dataLength);
private:
TPipe pipe;
TQue<QuePosition::VECIN, BUFFER_NUM> inputQueueX;
TQue<QuePosition::VECIN, BUFFER_NUM> inputQueueY;
TQue<QuePosition::VECOUT, BUFFER_NUM> outputQueueZ;
GlobalTensor<T> inputGMX;
GlobalTensor<T> inputGMY;
GlobalTensor<T> outputGMZ;
int64_t blockLength_ = 0;
int64_t tileNum_ = 0;
uint32_t tileLength_ = 0;
};
template <typename T>
__aicore__ inline void AddExample<T>::Init(GM_ADDR x, GM_ADDR y, GM_ADDR z, const AddExampleTilingData* tilingData)
{
blockLength_ = tilingData->totalLength / AscendC::GetBlockNum();
tileNum_ = tilingData->tileNum;
tileLength_ = blockLength_ / tileNum_ / BUFFER_NUM;
inputGMX.SetGlobalBuffer((__gm__ T*)x + blockLength_ * AscendC::GetBlockIdx(), blockLength_);
inputGMY.SetGlobalBuffer((__gm__ T*)y + blockLength_ * AscendC::GetBlockIdx(), blockLength_);
outputGMZ.SetGlobalBuffer((__gm__ T*)z + blockLength_ * AscendC::GetBlockIdx(), blockLength_);
pipe.InitBuffer(inputQueueX, BUFFER_NUM, tileLength_ * sizeof(T));
pipe.InitBuffer(inputQueueY, BUFFER_NUM, tileLength_ * sizeof(T));
pipe.InitBuffer(outputQueueZ, BUFFER_NUM, tileLength_ * sizeof(T));
}
template <typename T>
__aicore__ inline void AddExample<T>::CopyIn(int32_t progress)
{
AscendC::LocalTensor<T> xLocal = inputQueueX.AllocTensor<T>();
AscendC::LocalTensor<T> yLocal = inputQueueY.AllocTensor<T>();
AscendC::DataCopy(xLocal, inputGMX[progress * tileLength_], tileLength_);
AscendC::DataCopy(yLocal, inputGMY[progress * tileLength_], tileLength_);
inputQueueX.EnQue(xLocal);
inputQueueY.EnQue(yLocal);
}
template <typename T>
__aicore__ inline void AddExample<T>::CopyOut(int32_t progress)
{
AscendC::LocalTensor<T> zLocal = outputQueueZ.DeQue<T>();
AscendC::DataCopy(outputGMZ[progress * tileLength_], zLocal, tileLength_);
outputQueueZ.FreeTensor(zLocal);
}
template <typename T>
__aicore__ inline void AddExample<T>::Compute(int32_t progress)
{
AscendC::LocalTensor<T> xLocal = inputQueueX.DeQue<T>();
AscendC::LocalTensor<T> yLocal = inputQueueY.DeQue<T>();
AscendC::LocalTensor<T> zLocal = outputQueueZ.AllocTensor<T>();
AscendC::Add(zLocal, xLocal, yLocal, tileLength_);
outputQueueZ.EnQue<T>(zLocal);
inputQueueX.FreeTensor(xLocal);
inputQueueY.FreeTensor(yLocal);
}
template <typename T>
__aicore__ inline void AddExample<T>::Process()
{
int32_t loopCount = tileNum_ * BUFFER_NUM;
for (int32_t i = 0; i < loopCount; i++) {
CopyIn(i);
Compute(i);
CopyOut(i);
}
}
} // namespace NsAddExample
#endif // ADD_EXAMPLE_H

View File

@@ -0,0 +1,23 @@
/**
 * 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.
 */
/*!
* \file add_example_tiling_data.h
* \brief tiling data struct
*/
#ifndef __ADD_EXAMPLE_TILLING_DATA_H__
#define __ADD_EXAMPLE_TILLING_DATA_H__
struct AddExampleTilingData {
int64_t totalLength;
int64_t tileNum;
};
#endif

View File

@@ -0,0 +1,35 @@
/**
 * 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.
 */
/*!
* \file add_example_tiling_key.h
* \brief add_example tiling key declare
*/
#ifndef __ADD_EXAMPLE_TILING_KEY_H__
#define __ADD_EXAMPLE_TILING_KEY_H__
#include "ascendc/host_api/tiling/template_argument.h"
/* Mode场景定义 */
#define ELEMENTWISE_TPL_SCH_MODE_0 0
#define ELEMENTWISE_TPL_SCH_MODE_1 1
/* 继续定义其他Mode场景... */
/* 模板参数 */
ASCENDC_TPL_ARGS_DECL(AddExample,
ASCENDC_TPL_UINT_DECL(schMode, 1, ASCENDC_TPL_UI_LIST, ELEMENTWISE_TPL_SCH_MODE_0, ELEMENTWISE_TPL_SCH_MODE_1)
);
ASCENDC_TPL_SEL(
ASCENDC_TPL_ARGS_SEL(
ASCENDC_TPL_UINT_SEL(schMode, ASCENDC_TPL_UI_LIST, ELEMENTWISE_TPL_SCH_MODE_0, ELEMENTWISE_TPL_SCH_MODE_1)));
#endif

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,2 @@
CUSTOM_DATA_PATH=$HOME/Ascend/latest/data/
CUSTOM_CONF_PATH=$HOME/Ascend/latest/conf/

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,515 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
"""filelist相关类。"""
import itertools
import os
from collections import Counter
from collections.abc import Callable, Iterator
from enum import IntEnum
from functools import partial
from itertools import chain, repeat
from operator import and_, attrgetter, contains, itemgetter, lt, methodcaller, ne, not_
from typing import NamedTuple
from .utils.comm_log import CommLog
from .utils.funcbase import any_, constant, dispatch, identity, invoke, pipe, side_effect, star_apply
from .utils.pkg_utils import (
TOP_DIR,
FilelistError,
GenerateFilelistError,
conditional_apply,
config_feature_to_string,
pairwise,
swap_args,
)
class FileItem(NamedTuple):
"""文件条目"""
module: str
operation: str
relative_path_in_pkg: str
relative_install_path: str
is_in_docker: str
permission: str
owner_group: str
install_type: str
softlink: list[str]
feature: set[str]
is_common_path: str
configurable: str
hash_value: str
block: str
pkg_inner_softlink: list[str]
chip: set[str]
is_dir: bool
def create_file_item(*args, **kwargs) -> FileItem:
"""创建文件条目。"""
file_item = FileItem(*args, **kwargs)
if not isinstance(file_item.feature, set):
raise TypeError("The feature parameter should be a set.")
if not isinstance(file_item.chip, set):
raise TypeError("The chip parameter should be a set.")
if not isinstance(file_item.softlink, list):
raise TypeError("The softlink parameter should be a list.")
if not isinstance(file_item.pkg_inner_softlink, list):
raise TypeError("The pkg_inner_softlink parameter should be a list.")
return file_item
# 文件列表
FileList = list[FileItem]
def soft_links_to_string(soft_links: list[str]) -> str:
"""软链接转换为字符串。"""
if not soft_links:
return "NA"
return ";".join(soft_links)
def file_item_to_string(item: FileItem) -> str:
"""文件条目转换为字符串。"""
return ",".join(
[
item.module,
item.operation,
item.relative_path_in_pkg,
item.relative_install_path,
item.is_in_docker,
item.permission,
item.owner_group,
item.install_type,
soft_links_to_string(item.softlink),
config_feature_to_string(item.feature),
item.is_common_path,
item.configurable,
item.hash_value,
item.block,
soft_links_to_string(item.pkg_inner_softlink),
config_feature_to_string(item.chip),
]
)
def get_filelist_header_string() -> str:
"""获取文件列表表头。"""
return ",".join(
[
"module",
"operation",
"relative_path_in_pkg",
"relative_install_path",
"is_in_docker",
"permission",
"owner:group",
"install_type",
"softlink",
"feature",
"is_common_path",
"configurable",
"hash",
"block",
"pkg_inner_softlink",
"chip",
]
)
def get_soft_links_not_in_common_paths(filelist: FileList, target_env: str) -> Iterator[list[str]]:
for file_item_t in filelist:
if file_item_t.relative_install_path.startswith(target_env):
for softlink in file_item_t.softlink:
if not softlink.startswith(target_env):
yield softlink
def fill_is_common_path(filelist: FileList, target_env: str) -> Iterator[FileItem]:
"""填充文件条目中是否为公共目录字段。"""
soft_links = set(get_soft_links_not_in_common_paths(filelist, target_env))
for file_item in filelist:
if file_item.relative_install_path.startswith(target_env):
yield file_item._replace(is_common_path="Y")
else:
is_soft_links_prefix = map(methodcaller("startswith", f"{file_item.relative_install_path}/"), soft_links)
if any(is_soft_links_prefix):
yield file_item._replace(is_common_path="YY")
else:
yield file_item
def is_relative_install_path(path: str) -> bool:
"""是否为相对路径。"""
return not path.startswith("/")
def is_specific_operations(file_item: FileItem, operations: list[str]) -> bool:
"""是否为特定的操作类型。"""
return file_item.operation in operations
def is_specific_install_type(file_item: FileItem, install_types: set[str]) -> bool:
"""是否为特定的安装类型。"""
item_install_types = set(file_item.install_type.split(";"))
if "all" in item_install_types:
return True
return bool(item_install_types & install_types)
def get_install_path_dirs(install_path: str) -> Iterator[str]:
"""获取安装路径父目录。"""
install_path = os.path.dirname(install_path)
while install_path not in ("", "/"):
yield install_path
install_path = os.path.dirname(install_path)
def get_missing_dir_set(filelist: FileList) -> set[str]:
"""获取缺失目录集合。
文件列表可能出现某一级目录缺失情况。
如配置了file_info:aaa/bbb/ccc.txt但只配置了dir_info:aaa
那么缺失dir_info:aaa/bbb
"""
parent_dirs: set[str] = invoke(
pipe(
dispatch(
pipe(
partial(
filter,
partial(is_specific_operations, operations={"copy", "copy_entity"}),
),
partial(map, attrgetter("relative_install_path")),
partial(filter, is_relative_install_path),
set,
partial(map, get_install_path_dirs),
chain.from_iterable,
),
pipe(
partial(map, attrgetter("softlink")),
chain.from_iterable,
partial(
filter,
pipe(
dispatch(
bool,
is_relative_install_path,
partial(ne, "NA"),
),
all,
),
),
set,
partial(map, get_install_path_dirs),
chain.from_iterable,
),
pipe(
partial(map, attrgetter("pkg_inner_softlink")),
chain.from_iterable,
partial(
filter,
pipe(
dispatch(
bool,
partial(ne, "NA"),
),
all,
),
),
set,
partial(map, get_install_path_dirs),
chain.from_iterable,
),
),
chain.from_iterable,
set,
),
filelist,
)
mkdir_installs: set[str] = {
file_item.relative_install_path
for file_item in filter(partial(is_specific_operations, operations={"mkdir"}), filelist)
if is_relative_install_path(file_item.relative_install_path)
}
mkdir_parent_dirs: set[str] = set(itertools.chain.from_iterable(map(get_install_path_dirs, mkdir_installs)))
missing_dir_set = sorted((parent_dirs | mkdir_parent_dirs) - mkdir_installs)
return set(missing_dir_set)
def print_missing_dir_set(missing_dir_set: set[str], in_msg: str = None) -> set[str]:
"""打印缺失目录集合。"""
if in_msg:
tail_msg = f" {in_msg}"
else:
tail_msg = ""
for path in sorted(missing_dir_set):
CommLog.cilog_error(f'missing dir info path "{path}"{tail_msg}')
return missing_dir_set
def print_unsafe_paths(unsafe_paths: tuple[str, ...]) -> tuple[str, ...]:
"""打印非安全路径。"""
for path in unsafe_paths:
CommLog.cilog_error(f'unsafe path "{path}" in move scene.')
return unsafe_paths
# 获取filelist中所有的特性集合
get_features_in_filelist = pipe(
partial(map, attrgetter("feature")),
chain.from_iterable, # 展开集合序列为元素序列
set, # 去重
partial(filter, partial(ne, "comm")), # 排除comm特性
set,
)
# 获取filelist中所有的芯片集合
get_chips_in_filelist = pipe(
partial(map, attrgetter("chip")),
chain.from_iterable, # 展开集合序列为元素序列
set, # 去重
)
def check_features_in_filelist(features: set[str], filelist: FileList) -> set[str]:
"""检查文件列表中特性配置目录规范。"""
return invoke(
pipe(
# 过滤指定features的file_item
partial(filter, pipe(attrgetter("feature"), partial(and_, features), bool)),
list,
get_missing_dir_set,
partial(print_missing_dir_set, in_msg=f"in features {features}"),
),
filelist,
)
def check_chip_in_filelist(chip: str, filelist: FileList) -> set[str]:
"""检查文件列表中芯片配置目录规范。"""
return invoke(
pipe(
# 过滤指定chip的file_item
partial(
filter,
any_(
pipe(attrgetter("chip"), not_), # 没有配置chip
pipe(attrgetter("chip"), partial(swap_args(contains), chip), bool), # 配置了指定chip
),
),
list,
get_missing_dir_set,
partial(print_missing_dir_set, in_msg=f"in chip {chip}"),
),
filelist,
)
check_filelist_features = any_(
pipe(
dispatch(
pipe(
get_features_in_filelist,
# 对于每个feature与comm组成一个set
partial(map, lambda x: {x, "comm"}),
# 此时为feature集合序列
),
repeat, # 重复filelist
),
tuple,
star_apply(zip),
# 此时为元组序列元组的第1个元素是过滤的feature集合第2个元素是filelist
partial(itertools.starmap, check_features_in_filelist),
# 此时为集合序列;合并为一个集合
chain.from_iterable,
set,
),
pipe(
dispatch(
get_chips_in_filelist,
repeat, # 重复filelist
),
tuple,
star_apply(zip),
# 此时为元组序列元组的第1个元素是chip集合第2个元素是filelist
partial(itertools.starmap, check_chip_in_filelist),
# 此时为集合序列;合并为一个集合
chain.from_iterable,
set,
),
)
# 检查move是否安全是否存在同一个源路径被mv多次
check_move_safe = pipe(
partial(
filter,
partial(is_specific_operations, operations={"copy", "copy_entity", "move"}),
),
partial(map, attrgetter("relative_path_in_pkg")),
Counter,
methodcaller("items"),
partial(filter, pipe(itemgetter(1), partial(lt, 1))),
partial(map, itemgetter(0)),
tuple,
print_unsafe_paths,
)
def check_filelist(filelist: FileList, check_features: bool, check_move: bool):
"""检查文件列表是否符合规范。"""
if check_features:
check_features_func = check_filelist_features
else:
check_features_func = constant(set())
if check_move:
check_move_func = check_move_safe
else:
check_move_func = constant(tuple())
# 此处使用any_短路部分报错
check_func = any_(
pipe(
get_missing_dir_set,
print_missing_dir_set,
),
pipe(
partial(filter, partial(is_specific_install_type, install_types={"run"})),
list,
get_missing_dir_set,
partial(print_missing_dir_set, in_msg="in run install type"),
),
check_features_func,
check_move_func,
)
missing = check_func(filelist)
if missing:
raise FilelistError()
def get_common_path(args: list[str]) -> str:
"""公共路径前缀。"""
try:
return os.path.commonpath(args)
except ValueError:
return ""
class FileItemRelation(IntEnum):
"""文件条目之间的关系。"""
NOT_NESTED = 0 # 不是嵌套文件
NESTED = 1 # 嵌套文件
SAME = 2 # 相同文件
def is_nested_file_item(item: FileItem, base_item: FileItem) -> FileItemRelation:
"""是否为嵌套的文件。"""
if base_item is None:
return FileItemRelation.NOT_NESTED
if item == base_item:
return FileItemRelation.SAME
install_path = item.relative_install_path
base_install_path = base_item.relative_install_path
common_install_path = get_common_path([install_path, base_install_path])
if common_install_path != base_install_path:
return FileItemRelation.NOT_NESTED
pkg_path = item.relative_path_in_pkg
base_pkg_path = base_item.relative_path_in_pkg
install_rel_path = os.path.relpath(install_path, base_install_path)
pkg_rel_path = os.path.relpath(pkg_path, base_pkg_path)
if install_rel_path != pkg_rel_path:
# 确保打包与安装相对路径一致
raise FilelistError(f"nested paths {item} and {base_item} are illegal.")
return FileItemRelation.NESTED
def found_nested_file_item(item: FileItem, base_item: FileItem):
"""发现嵌套元素。"""
raise FilelistError(f"found nested paths {item} and {base_item}!")
def convert_nested_path_in_filelist(filelist: FileList):
"""filelist中嵌套路径元素转为del。"""
pre_item = None
for item in filelist:
ret = is_nested_file_item(item, pre_item)
if ret == FileItemRelation.NESTED:
yield item._replace(operation="del")
elif any((ret == FileItemRelation.NOT_NESTED, (ret == FileItemRelation.SAME and not item.is_dir))):
yield item
pre_item = item
# 检查文件列表中的嵌套路径。入参: filelist
check_nested_path_in_filelist = pipe(
partial(filter, partial(is_specific_operations, operations={"copy", "copy_entity"})),
partial(sorted, key=attrgetter("relative_install_path")),
pairwise,
partial(map, conditional_apply(star_apply(is_nested_file_item), star_apply(found_nested_file_item))),
list,
)
# 变换文件列表中嵌套路径。入参: filelist
transform_nested_path_in_filelist = pipe(
dispatch(
partial(itertools.filterfalse, partial(is_specific_operations, operations={"copy"})),
pipe(
partial(filter, partial(is_specific_operations, operations={"copy"})),
partial(sorted, key=attrgetter("relative_install_path")),
convert_nested_path_in_filelist,
),
),
chain.from_iterable,
list,
side_effect(check_nested_path_in_filelist),
)
def generate_filelist(filelist: FileList, filename: str):
"""生成文件列表文件。"""
content_list = list(
itertools.chain([get_filelist_header_string()], [file_item_to_string(item) for item in filelist])
)
content = "\n".join(content_list)
filepath = os.path.join(TOP_DIR, "build", filename)
try:
with open(filepath, "w", encoding="utf-8") as file:
file.write(content)
# filelist.csv文件末尾补充一个换行符
file.write("\n")
except OSError as ex:
raise GenerateFilelistError(filename) from ex
def get_transform_nested_path_func(parallel: bool) -> Callable[[FileList], FileList]:
"""获取转换嵌套路径函数。"""
if parallel:
return transform_nested_path_in_filelist
return identity

View File

@@ -0,0 +1,69 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
"""合并算子binary_info_config.json。"""
import argparse
import json
import os
import sys
def load_json_file(json_file: str):
"""加载json文件。"""
with open(json_file, encoding="utf-8") as file:
json_content = json.load(file)
return json_content
def save_json_file(output_file: str, content):
"""保存json文件。"""
output_dir = os.path.dirname(output_file)
if not os.path.exists(output_dir):
os.makedirs(output_dir, exist_ok=True)
with open(output_file, "w", encoding="utf-8") as file:
json.dump(content, file, ensure_ascii=True, indent=2)
def update_config(base_content, update_content):
"""更新配置。"""
new_content = base_content.copy()
new_content.update(update_content)
return dict(sorted(new_content.items()))
def parse_args(argv: list[str]):
"""入参解析。"""
parser = argparse.ArgumentParser()
parser.add_argument("--base-file", required=True, help="the basic binary_info_config file")
parser.add_argument("--update-file", required=True, help="the update binary_info_config file")
parser.add_argument(
"--output-file", required=True, type=os.path.realpath, help="the output binary_info_config file"
)
args = parser.parse_args(argv)
return args
def main(argv: list[str]) -> bool:
"""主流程。"""
args = parse_args(argv)
base_content = load_json_file(args.base_file)
update_content = load_json_file(args.update_file)
result = update_config(base_content, update_content)
save_json_file(args.output_file, result)
return True
if __name__ == "__main__":
if not main(sys.argv[1:]): # pragma: no cover
sys.exit(1) # pragma: no cover

View File

@@ -0,0 +1,240 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
import os
import shutil
import subprocess
from argparse import Namespace
from collections.abc import Callable
from itertools import chain
from subprocess import PIPE, STDOUT
from typing import NamedTuple
from .utils.comm_log import CommLog
from .utils.pkg_utils import CompressError
class PackageName:
"""包名。"""
def __init__(self, package_attr, args: Namespace, version: str):
self.product_name = package_attr.get("product_name")
self.chip_name = args.chip_name or package_attr.get("chip_name")
self.suffix = args.suffix or package_attr.get("suffix")
self.func_name = get_func_name(args.func_name, package_attr)
self.chip_plat = package_attr.get("chip_plat")
self.deploy_type = package_attr.get("deploy_type")
self.version = version.lower()
self.not_in_name_list = args.not_in_name.split(",")
self.os_arch = args.os_arch
self.package_suffix = args.package_suffix
self.ext_name = args.ext_name
if args.pkg_name_style == "underline":
self.name_sep = "_"
else:
self.name_sep = "-"
def get_attribute(self, name: str) -> str | None:
"""获取属性。"""
if name in self.not_in_name_list:
return None
return getattr(self, name)
def getvalue(self) -> str:
product_name = self.get_attribute("product_name")
chip_name = self.get_attribute("chip_name")
func_name = self.get_attribute("func_name")
version = self.get_attribute("version")
os_arch = self.get_attribute("os_arch")
chip_plat = self.get_attribute("chip_plat")
deploy_type = self.get_attribute("deploy_type")
ext_name = self.get_attribute("ext_name")
package_suffix = "debug" if self.package_suffix == "debug" else None
region1 = "-".join(filter(None, [product_name, remove_ascend(chip_name), func_name]))
region2 = ".".join(filter(None, [version]))
region3 = "-".join(filter(None, [os_arch, chip_plat, deploy_type, package_suffix, ext_name]))
package_name = "_".join(filter(None, [region1, region2, region3]))
return f"{package_name}.{self.suffix}"
class MakeselfPkgParams(NamedTuple):
"""run包打包参数。"""
package_name: str
comments: str
makeself_tool: str | None = None
makeself_header: str | None = None
help_info: str | None = None
source_target: str | None = None
install_script: str | None = None
independent_pkg: bool | None = False
cleanup: str | None = None
def remove_ascend(text):
if text is None:
return None
text_lower = text.lower()
if text_lower == "ascend910_93":
return "A3"
if "ascend" in text_lower:
return text_lower.replace("ascend", "")
return text_lower
def get_func_name(func_name: str, package_attr) -> str:
"""获取包func_name。"""
return func_name or package_attr.get("func_name")
def get_compress_tool() -> str:
tools = ["pigz", "gzip", "bzip2", "xz"]
for tool in tools:
path = shutil.which(tool)
if path:
return "--" + tool
CommLog.cilog_error(
"The system does not come with a compression tool pre-installed."
"Please ensure at least one of the following compression tools is available: %s",
tools,
)
return ""
def get_compress_format() -> str:
tar_format = "gnu"
path = shutil.which("bsdtar")
if path:
tar_format = "ustar"
return tar_format
def compose_makeself_command(params: MakeselfPkgParams) -> str:
"""组装makeself包打包命令。"""
def get_cleanup_commands() -> list[str]:
if params.cleanup:
return ["--cleanup", params.cleanup]
return []
independent_pkg = params.independent_pkg
compress_tool = get_compress_tool()
tar_format = get_compress_format()
if independent_pkg:
commands = chain(
[
"TMPDIR=$pwd",
params.makeself_tool,
"--header",
params.makeself_header,
"--help-header",
params.help_info,
compress_tool,
"--complevel",
"4",
"--nomd5",
"--sha256",
"--nooverwrite",
"--chown",
"--tar-format",
tar_format,
"--tar-extra",
"--numeric-owner",
"--tar-quietly",
],
get_cleanup_commands(),
[params.source_target, params.package_name, params.comments, params.install_script],
)
else:
commands = chain(
[
compress_tool,
"--complevel",
"4",
"--nomd5",
"--sha256",
"--nooverwrite",
"--chown",
"--tar-format",
tar_format,
"--tar-extra",
"--numeric-owner",
"--tar-quietly",
],
get_cleanup_commands(),
[params.package_name, params.comments],
)
command = " ".join(commands)
return command
def create_makeself_pkg_params_factory(
source_target: str, package_name: str, comments: str
) -> Callable[[str, dict, bool], MakeselfPkgParams]:
"""创建Makeself打包参数工厂。"""
def create_makeself_pkg_params(makeself_dir: str, package_attr: dict, independent_pkg=False) -> MakeselfPkgParams:
"""创建Makeself打包参数。"""
cleanup = package_attr.get("cleanup")
if independent_pkg:
install_script = str(package_attr.get("install_script"))
help_info = str(package_attr.get("help"))
makeself_tool = os.path.join(makeself_dir, "makeself.sh")
makeself_header = os.path.join(makeself_dir, "makeself-header.sh")
params = MakeselfPkgParams(
package_name=package_name,
comments=comments,
makeself_tool=makeself_tool,
makeself_header=makeself_header,
help_info=help_info,
source_target=source_target,
install_script=install_script,
independent_pkg=independent_pkg,
cleanup=cleanup,
)
else:
params = MakeselfPkgParams(
package_name=package_name,
comments=comments,
cleanup=cleanup,
)
return params
return create_makeself_pkg_params
def create_run_package_command(params: MakeselfPkgParams) -> tuple[str | None, str | None]:
"""
功能描述: 组装打run包命令
返回值: command
"""
return compose_makeself_command(params), None
def exec_pack_cmd(delivery_dir: str, pack_cmd: str, package_name: str) -> str:
"""执行打包命令"""
if delivery_dir:
cmd = f"cd {delivery_dir} && {pack_cmd}"
else:
cmd = pack_cmd
CommLog.cilog_info("package cmd:%s", cmd)
result = subprocess.run(cmd, shell=True, check=False, stdout=PIPE, stderr=STDOUT)
output = result.stdout.decode()
if result.returncode != 0:
CommLog.cilog_error(__file__, "compress package(%s) failed! %s.", package_name, output)
raise CompressError(package_name)
return package_name

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
import inspect
import logging
import time
logging.basicConfig(
format="[%(asctime)s] [%(levelname)s] [%(pathname)s] [line:%(lineno)d] %(message)s", level=logging.INFO
)
class CommLog:
@staticmethod
def cilog_get_timestamp():
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
@staticmethod
def cilog_print_element(cilog_element):
print("[" + cilog_element + "]", end=" ")
return
@staticmethod
def cilog_logmsg(log_level, filename, line_no, log_msg, *log_paras):
log_timestamp = CommLog.cilog_get_timestamp()
CommLog.cilog_print_element(log_timestamp)
CommLog.cilog_print_element(log_level)
CommLog.cilog_print_element(filename)
CommLog.cilog_print_element(str(line_no))
print(log_msg % log_paras[0])
return
@staticmethod
def cilog_error(log_msg, *log_paras):
frame = inspect.currentframe().f_back
line_no = frame.f_lineno
filename = frame.f_code.co_filename
CommLog.cilog_logmsg("ERROR", filename, line_no, log_msg, log_paras)
return
@staticmethod
def cilog_warning(log_msg, *log_paras):
frame = inspect.currentframe().f_back
line_no = frame.f_lineno
filename = frame.f_code.co_filename
CommLog.cilog_logmsg("WARNING", filename, line_no, log_msg, log_paras)
return
@staticmethod
def cilog_info(log_msg, *log_paras):
frame = inspect.currentframe().f_back
line_no = frame.f_lineno
filename = frame.f_code.co_filename
CommLog.cilog_logmsg("INFO", filename, line_no, log_msg, log_paras)
return

View File

@@ -0,0 +1,94 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
"""函数基础库。"""
import operator
from collections.abc import Callable, Iterator
from typing import TypeVar
A = TypeVar("A")
def constant(value: A) -> Callable[..., A]:
"""常量值。"""
def constant_inner(*_args, **_kwargs) -> A:
return value
return constant_inner
def dispatch(*funcs):
"""分派应用。"""
def dispatch_inner(*args, **kwargs) -> Iterator:
return (func(*args, **kwargs) for func in funcs)
return dispatch_inner
def pipe(*funcs):
"""串联多个函数。"""
def pipe_func(*args, **k_args):
result = funcs[0](*args, **k_args)
for func in funcs[1:]:
result = func(result)
return result
return pipe_func
def identity(value: A) -> A:
"""同一。"""
return value
def invoke(func, *args, **kwargs):
"""调用。"""
return func(*args, **kwargs)
def side_effect(*funcs):
"""调用函数,产生副作用,但不影响管道结果。"""
def side_effect_func(arg):
for func in funcs:
# 不保留结果
func(arg)
return arg
return side_effect_func
def star_apply(func):
"""列表展开再应用。"""
def star_apply_func(arg):
return func(*arg)
return star_apply_func
def any_(*funcs) -> Callable:
"""高阶any。
注意any有短路效果。"""
return pipe(
dispatch(*funcs),
any,
)
def not_(func) -> Callable:
"""高阶not。"""
return pipe(func, operator.not_)

View File

@@ -0,0 +1,181 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
"""基础构件。"""
import os
from collections.abc import Callable, Iterator
from itertools import chain, tee
from pathlib import Path
from typing import Optional, TypeVar
TOP_DIR = str(Path(__file__).resolve().parents[5])
TOP_SOURCE_DIR = TOP_DIR + "/scripts/"
DELIVERY_PATH = "build/_CPack_Packages/makeself_staging"
CONFIG_SCRIPT_PATH = "package"
BLOCK_CONFIG_PATH = "package/module"
SUCCESS = 0
FAIL = -1
A = TypeVar("A")
class PackageError(Exception):
"""打包异常基类。"""
class PackageConfigError(PackageError):
"""打包配置错误异常。"""
class BlockConfigError(PackageError):
"""块配置错误异常。"""
class ParseOsArchError(PackageError):
"""解析os_arch失败异常。"""
class EnvNotSupported(PackageError):
"""环境变量不支持异常。"""
class ContainAsteriskError(PackageError):
"""包含星号异常。"""
def __init__(self, value: str):
super().__init__()
self.value = value
class FilelistError(PackageError):
"""文件列表异常。"""
class UnknownOperateTypeError(PackageError):
"""未知的操作类型。"""
class PackageNameEmptyError(PackageError):
"""包名为空错误。"""
class GenerateFilelistError(PackageError):
"""生成文件列表文件异常。"""
def __init__(self, filename: str):
super().__init__()
self.filename = filename
class IllegalVersionDir(PackageError):
"""version_dir配置错误。"""
class CompressError(PackageError):
"""打包错误。"""
def __init__(self, package_name: str | None):
super().__init__(package_name)
self.package_name = package_name
def flatten(list_of_lists):
"""Flatten one level of nesting"""
return chain.from_iterable(list_of_lists)
def merge_dict(base: dict, *news: dict):
"""合并两个字典。"""
result = base.copy()
for new in news:
result.update(new)
return result
def star_pipe(*funcs):
"""串联多个函数。解包结果。"""
def pipe_func(*args, **k_args):
result = funcs[0](*args, **k_args)
for func in funcs[1:]:
# 解包元组或列表结果
result = func(*result)
return result
return pipe_func
def swap_args(func):
"""交换函数前两个参数。"""
def inner(fst, snd, *args, **k_args):
return func(snd, fst, *args, **k_args)
return inner
def conditional_apply(predicate, func):
"""条件下应用函数。"""
def conditional_apply_func(arg):
if predicate(arg):
return func(arg)
return arg
return conditional_apply_func
def pairwise(iterable):
"""s -> (s0,s1), (s1,s2), (s2, s3), ..."""
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def path_join(base: Optional, *others: str) -> Optional:
"""路径联合。"""
if base is None:
return None
return os.path.join(base, *others)
def yield_if(data, predicate: Callable) -> Iterator:
"""条件满足则产生。"""
if predicate(data):
yield data
def config_feature_to_set(feature_str: str, feature_type: str = "feature") -> set[str]:
"""配置feature转换为集合。"""
if feature_str is None:
return set()
if isinstance(feature_str, set):
return feature_str
if feature_str == "":
raise PackageConfigError(f"Not allow to config {feature_type} empty.")
features = set(feature_str.split(";"))
if "all" in features:
raise PackageConfigError(f"Not allow to config {feature_type} all.")
return features
def config_feature_to_string(features: set[str]) -> str:
"""配置feature集合转换为字符串。"""
if not features:
return "all"
return ";".join(sorted(features))

View File

@@ -0,0 +1,435 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
import os
import xml.etree.ElementTree as ET
from functools import total_ordering
from pathlib import Path
from typing import NamedTuple
import regex as re
class VersionInfoError(Exception):
"""版本信息异常基类。"""
class VersionFormatNotMatch(VersionInfoError):
"""版本格式未匹配。"""
class IntervalFormatNotMatch(VersionInfoError):
"""区间格式未匹配。"""
class DuplicatedPkgConfig(VersionInfoError):
"""解析版本配置失败。重复的包配置。"""
def __init__(self, pkg_name):
super().__init__(pkg_name)
self.pkg_name = pkg_name
class ParseVersionFailed(VersionInfoError):
"""解析版本失败。"""
class CollectRequiresFailed(VersionInfoError):
"""收集包需求失败。"""
def __init__(self, pkg_name, version_str, msg):
super().__init__(pkg_name, version_str, msg)
self.pkg_name = pkg_name
self.version_str = version_str
self.msg = msg
@total_ordering
class Version:
"""版本号。"""
def __init__(self, version):
self.version = version
@classmethod
def match(cls, input_str):
"""输入字符串是否匹配版本号模式。"""
m = re.match(r"[.a-zA-Z0-9]+$", input_str)
return bool(m)
@classmethod
def parse(cls, input_str):
"""解析版本号。"""
if not cls.match(input_str):
raise VersionFormatNotMatch()
return cls(input_str)
@classmethod
def try_convert_to_int_list(cls, str_list):
"""尝试转换为int数组。"""
for idx, item in enumerate(str_list):
try:
int_item = int(item)
str_list[idx] = int_item
except ValueError:
pass
def to_required_list(self):
"""转换为版本需求字符串列表。"""
return [self.version]
def __eq__(self, other):
"""等于。"""
if not isinstance(other, self.__class__):
return False
return self.version == other.version
def __lt__(self, other):
"""小于。"""
if not isinstance(other, self.__class__):
return True
self_list = self.version.split(".")
other_list = other.version.split(".")
self.try_convert_to_int_list(self_list)
self.try_convert_to_int_list(other_list)
self_tuple = tuple(self_list)
other_tuple = tuple(other_list)
return self_tuple < other_tuple
def __str__(self):
return self.version
def __repr__(self):
return repr(self.version)
class Point(NamedTuple):
"""区间端点。"""
type_: int # 类型0为闭区间1为开区间
value: Version
class Interval(NamedTuple):
"""版本号区间。"""
low: Point
high: Point
@classmethod
def match(cls, input_str: str) -> bool:
"""输入字符串是否匹配区间模式。"""
if not input_str.startswith("(") and not input_str.startswith("["):
return False
if not input_str.endswith(")") and not input_str.endswith("]"):
return False
input_str = input_str[1:-1]
return input_str.count(",") <= 1
@classmethod
def parse(cls, input_str):
"""解析版本号区间。"""
if not cls.match(input_str):
raise IntervalFormatNotMatch()
if input_str[0] == "[":
low_type = 0
elif input_str[0] == "(":
low_type = 1
else:
raise AssertionError("should not go here.")
if input_str[-1] == "]":
high_type = 0
elif input_str[-1] == ")":
high_type = 1
else:
raise AssertionError("should not go here.")
input_str = input_str[1:-1]
input_list = input_str.split(",")
low = input_list[0].strip()
if len(input_list) > 1:
high = input_list[1].strip()
else:
high = None
if low:
low_version = Point(low_type, Version(low))
else:
low_version = None
if high:
high_version = Point(high_type, Version(high))
else:
high_version = None
return cls(low=low_version, high=high_version)
def to_required_list(self):
"""转换为版本需求字符串列表。"""
result = []
if self.low:
if self.low.type_ == 0:
operator = ">="
else:
operator = ">"
required_str = f"{operator}{self.low.value.version}"
result.append(required_str)
if self.high:
if self.high.type_ == 0:
operator = "<="
else:
operator = "<"
required_str = f"{operator}{self.high.value.version}"
result.append(required_str)
return result
class Require(NamedTuple):
"""包需求。"""
pkg_name: str
versions: list
@classmethod
def _sort_key(cls, item) -> tuple:
"""排序键。"""
if isinstance(item, Interval):
# 如果存在区间左值,则左值参与排序。
if item.low:
return item.low.value, item.low.type_
# 否则使用区间右值由于开区间更小所以type_取负。
return item.high.value, -item.high.type_
return item, 0
@classmethod
def _sort_versions(cls, versions: list) -> bool:
"""排序版本序列。"""
versions.sort(key=cls._sort_key)
return True
@classmethod
def _to_required_list(cls, versions: list) -> list[str]:
"""转换为版本需求字符串列表。"""
result = []
for version in versions:
requires = version.to_required_list()
result.extend(requires)
return result
@classmethod
def _to_required_str(cls, versions: list) -> str:
"""转换为版本需求字符串。"""
requires = cls._to_required_list(versions)
required_str = ", ".join(requires)
return required_str
def sort_versions(self) -> bool:
"""排序版本序列。"""
return self._sort_versions(self.versions)
def to_required_full_str(self) -> str:
"""转换为版本需求字符串。"""
required_str = self._to_required_str(self.versions)
required_full_str = f'required_package_{self.pkg_name}_version="{required_str}"'
return required_full_str
class ItemElement(NamedTuple):
"""item元素。"""
name: str
version: str
@classmethod
def parse(cls, item_ele: ET.Element, cur_ver: str):
"""解析item元素。"""
name = item_ele.attrib["name"]
version = item_ele.attrib["version"].replace("$(CUR_VER)", cur_ver)
return cls(name=name, version=version)
@classmethod
def skip(cls, item_ele: ET.Element):
"""是否跳过item元素。"""
version = item_ele.attrib["version"]
return version.strip() == ""
class CompatibleElement(NamedTuple):
"""compatible元素。"""
items: list
@classmethod
def parse(cls, compatible_ele: ET.Element, cur_ver: str):
"""解析compatible元素。"""
items = []
for item_ele in compatible_ele.findall("./item"):
if ItemElement.skip(item_ele):
continue
item = ItemElement.parse(item_ele, cur_ver)
items.append(item)
return cls(items=items)
def is_version_number(version: str) -> bool:
"""字符串是否为版本号。"""
has_slash = "/" in version
return not has_slash and len(version.split(".")) >= 3
class VersionXml(NamedTuple):
"""版本配置。"""
release_version: str
version_dir: str
packages: dict
@classmethod
def match(cls, filepath: Path | str) -> bool:
"""文件路径是否匹配版本信息文件。"""
return str(filepath).endswith(".xml")
@classmethod
def parse_version(cls, version_str: str):
"""解析版本配置。"""
ret = Interval.match(version_str)
if ret:
result = Interval.parse(version_str)
return result
ret = Version.match(version_str)
if ret:
result = Version.parse(version_str)
return result
raise ParseVersionFailed()
def get_release_version(self):
"""获取发布版本号。"""
return self.release_version
def get_version_dir(self):
"""获取多版本目录。"""
return self.version_dir
def collect_requires(self, package: str) -> list[Require]:
"""收集对应包的包需求列表。"""
requires = {}
if package not in self.packages:
return []
compatible = self.packages[package]
for item in compatible.items:
pkg_name = item.name
if pkg_name not in requires:
requires[pkg_name] = Require(pkg_name=pkg_name, versions=[])
version_str = item.version
try:
version = self.parse_version(version_str)
except ParseVersionFailed as ex:
msg = f"parse pkg {pkg_name} version {version_str} failed"
raise CollectRequiresFailed(pkg_name, version_str, msg) from ex
requires[pkg_name].versions.append(version)
result = []
for pkg_name in sorted(requires.keys()):
requires[pkg_name].sort_versions()
result.append(requires[pkg_name])
return result
def get_version_dir(version_xml: VersionXml | None, disable_multi_version: bool, version_dir: str | None) -> str | None:
"""获取版本目录名。"""
if disable_multi_version:
return None
if version_dir:
return version_dir
# 支持从version.xml中获取version_dir
if version_xml and version_xml.get_version_dir():
return version_xml.get_version_dir()
return None
def is_multi_version(version_dir: str) -> bool:
"""是否多版本。"""
return bool(version_dir)
class VersionInfo(NamedTuple):
"""版本信息。"""
install_version_info: bool
install_version_info_attrib: dict[str, str] | None
itf_versions: list[str]
version: str
version_xml: VersionXml | None
timestamp: str | None
class VersionInfoFile(NamedTuple):
"""生成的版本配置。"""
version: str
itf_version_info: str | None = None
requires: list[Require] | None = None
version_dir: str | None = None
timestamp: str | None = None
def _get_content(self) -> str:
"""获取版本配置内容。"""
lines = [f"Version={self.version}"]
if self.version_dir:
lines.append(f"version_dir={self.version_dir}")
if self.timestamp:
lines.append(f"timestamp={self.timestamp}")
if self.itf_version_info:
lines.append(self.itf_version_info)
if self.requires:
requires_str = [require.to_required_full_str() for require in self.requires]
lines.extend(requires_str)
lines.append("")
return "\n".join(lines)
def save(self, target_path: Path | str):
"""保存版本配置。"""
content = self._get_content()
target_dir = os.path.dirname(target_path)
if not os.path.exists(target_dir):
os.makedirs(target_dir)
with open(target_path, "w") as file:
file.write(content)

View File

@@ -0,0 +1,281 @@
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
function strip(input) {
sub("^ +", "", input)
sub(" +$", "", input)
return input
}
function check_compatible_le(version_arr, len_version_arr, require_arr, len_require_arr, i) {
for (i = 1; i <= len_require_arr; i++) {
if (require_arr[i] == "") {
continue
}
# len_version_arr lt len_require_arr
if (i > len_version_arr) {
return 1
}
if (version_arr[i] < require_arr[i]) {
return 1
}
if (version_arr[i] > require_arr[i]) {
return 0
}
}
if (len_version_arr > len_require_arr) {
return 1
}
# len_version_arr eq len_require_arr
return 1
}
function check_compatible_lt(version_arr, len_version_arr, require_arr, len_require_arr, i) {
for (i = 1; i <= len_require_arr; i++) {
if (require_arr[i] == "") {
continue
}
# len_version_arr lt len_require_arr
if (i > len_version_arr) {
return 1
}
if (version_arr[i] < require_arr[i]) {
return 1
}
if (version_arr[i] > require_arr[i]) {
return 0
}
}
if (len_version_arr > len_require_arr) {
return 0
}
# len_version_arr eq len_require_arr
return 0
}
function check_compatible_ge(version_arr, len_version_arr, require_arr, len_require_arr, i) {
for (i = 1; i <= len_require_arr; i++) {
if (require_arr[i] == "") {
continue
}
# len_version_arr lt len_require_arr
if (i > len_version_arr) {
return 0
}
if (version_arr[i] < require_arr[i]) {
return 0
}
if (version_arr[i] > require_arr[i]) {
return 1
}
}
if (len_version_arr > len_require_arr) {
return 1
}
# len_version_arr eq len_require_arr
return 1
}
function check_compatible_gt(version_arr, len_version_arr, require_arr, len_require_arr, i) {
for (i = 1; i <= len_require_arr; i++) {
if (require_arr[i] == "") {
continue
}
# len_version_arr lt len_require_arr
if (i > len_version_arr) {
return 0
}
if (version_arr[i] < require_arr[i]) {
return 0
}
if (version_arr[i] > require_arr[i]) {
return 1
}
}
if (len_version_arr > len_require_arr) {
return 1
}
# len_version_arr eq len_require_arr
return 0
}
function check_compatible_eq(version_arr, len_version_arr, require_arr, len_require_arr, i) {
for (i = 1; i <= len_require_arr; i++) {
if (require_arr[i] == "") {
continue
}
# len_version_arr lt len_require_arr
if (i > len_version_arr) {
return 0
}
if (version_arr[i] != require_arr[i]) {
return 0
}
}
if (len_version_arr > len_require_arr) {
return 1
}
# len_version_arr eq len_require_arr
return 1
}
function check_compatible(version_arr, len_version_arr, require, require_arr, len_require_arr, pos) {
len_require_arr = split(require, require_arr, ".")
pos = match(require_arr[1], /^>=/)
if (pos != 0) {
require_arr[1] = substr(require_arr[1], pos + RLENGTH)
return check_compatible_ge(version_arr, len_version_arr, require_arr, len_require_arr)
}
pos = match(require_arr[1], /^>/)
if (pos != 0) {
require_arr[1] = substr(require_arr[1], pos + RLENGTH)
return check_compatible_gt(version_arr, len_version_arr, require_arr, len_require_arr)
}
pos = match(require_arr[1], /^<=/)
if (pos != 0) {
require_arr[1] = substr(require_arr[1], pos + RLENGTH)
return check_compatible_le(version_arr, len_version_arr, require_arr, len_require_arr)
}
pos = match(require_arr[1], /^</)
if (pos != 0) {
require_arr[1] = substr(require_arr[1], pos + RLENGTH)
return check_compatible_lt(version_arr, len_version_arr, require_arr, len_require_arr)
}
return check_compatible_eq(version_arr, len_version_arr, require_arr, len_require_arr)
}
BEGIN {
len_all_required_arr = split(all_required, all_required_arr, ",")
compated = 0
in_gt = 0
matched_gt = 0
len_version_arr = split(version, version_arr, ".")
for (i = 1; i <= len_all_required_arr; i++) {
all_required_arr[i] = strip(all_required_arr[i])
one_compated = check_compatible(version_arr, len_version_arr, all_required_arr[i])
pos = match(all_required_arr[i], /^>/)
if (pos != 0) {
gt_require = 1
lt_require = 0
eq_require = 0
} else {
pos = match(all_required_arr[i], /^</)
if (pos != 0) {
gt_require = 0
lt_require = 1
eq_require = 0
} else {
gt_require = 0
lt_require = 0
eq_require = 1
}
}
if (matched_gt) {
if (one_compated) {
# gt after gt, all compated.
if (gt_require) {
matched_gt = 1
in_gt = 1
continue
}
# lt after gt, all compated.
if (lt_require) {
compated = 1
matched_gt = 0
in_gt = 0
break
}
# eq after gt, all compated.
if (eq_require) {
# eq compated, go.
compated = 1
break
}
} else {
# miscompated.
# gt after gt, compated first gt. miscompated second gt.
if (gt_require) {
matched_gt = 0
in_gt = 1
continue
}
# lt after gt, compated first gt. miscompated second lt.
if (lt_require) {
matched_gt = 0
in_gt = 0
continue
}
# eq after gt, compated first gt. miscompated second eq.
if (eq_require) {
continue
}
}
} else {
if (one_compated) {
if (gt_require) {
matched_gt = 1
in_gt = 1
continue
}
if (lt_require) {
if (in_gt) {
matched_gt = 0
in_gt = 0
continue
} else {
compated = 1
break
}
}
if (eq_require) {
# eq compated, go.
compated = 1
break
}
} else {
# miscompated.
if (gt_require) {
matched_gt = 0
in_gt = 1
continue
}
if (lt_require) {
matched_gt = 0
in_gt = 0
continue
}
if (eq_require) {
continue
}
}
}
}
if (matched_gt) {
compated = 1
}
if (compated == 0) {
printf("F")
} else {
printf("T")
}
}

View File

@@ -0,0 +1,14 @@
#!/bin/sh
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
set -e
rm -rf $(pwd)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
#!/bin/sh
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
# 通知latest管理器创建版本软链
notify_latest_manager_create_version_softlink() {
local curpath install_path version_dir var_path
set_comm_log "Notifier"
curpath="$(dirname $(readlink -f "${BASH_SOURCE:-$0}"))"
install_path="$(readlink -f "$curpath/..")"
version_dir="$(basename "$curpath")"
var_path="$install_path/$LATEST_DIR/var"
if [ ! -f "$var_path/manager.sh" ]; then
comm_log "ERROR" "$var_path/manager.sh doesn't exist!"
exit 2
fi
if ! "$var_path/manager.sh" --version-dir "$version_dir" create_version_softlink; then
comm_log "ERROR" "create version softlink failed!"
exit 1
fi
return 0
}
# 通知latest管理器删除latest软链
notify_latest_manager_remove_latest_softlink() {
local curpath install_path var_path
set_comm_log "Notifier"
curpath="$(dirname $(readlink -f "${BASH_SOURCE:-$0}"))"
install_path="$(readlink -f "$curpath/..")"
var_path="$install_path/$LATEST_DIR/var"
if [ ! -f "$var_path/manager.sh" ]; then
comm_log "ERROR" "$var_path/manager.sh doesn't exist!"
exit 2
fi
if ! "$var_path/manager.sh" remove_latest_softlink; then
comm_log "ERROR" "remove latest softlink failed!"
exit 1
fi
return 0
}

View File

@@ -0,0 +1,37 @@
#!/bin/csh
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
set func_name = "$1"
switch ( "$func_name" )
case "mk_custom_path":
if ( "`id -u`" == 0 ) then
exit 0
endif
set file_path = "$2"
foreach line ("` cat $file_path `")
set custom_path = "`echo '$line' | cut --only-delimited -d= -f2`"
if ( "$custom_path" == "" ) then
continue
endif
set custom_path = "` eval echo $custom_path `"
if ( ! -d "$custom_path" ) then
mkdir -p "$custom_path"
if ( $status != 0 ) then
set cur_date = "`date +'%Y-%m-%d %H:%M:%S'`"
echo "[Common] [$cur_date] [ERROR]: create $custom_path failed."
exit 1
endif
endif
end
breaksw
default:
breaksw
endsw

View File

@@ -0,0 +1,33 @@
#!/usr/bin/env fish
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
function mk_custom_path
set -l custom_file_path $argv[1]
if test (id -u) -eq 0
return 0
end
while read line
set -l _custom_path (echo "$line" | cut --only-delimited -d= -f2)
if test -z $_custom_path
continue
end
set -l _custom_path (eval echo "$_custom_path")
if not test -d $_custom_path
mkdir -p "$_custom_path"
if not test $status -eq 0
set -l cur_date (date +"%Y-%m-%d %H:%M:%S")
echo "[Common] [$cur_date] [ERROR]: create $_custom_path failed."
return 1
end
end
end < $custom_file_path
return 0
end

View File

@@ -0,0 +1,61 @@
#!/bin/sh
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
mk_custom_path() {
if [ $(id -u) -eq 0 ]; then
return 0
fi
local _custom_path_file="$1"
while read line || [ -n "$line" ]
do
local _custom_path="$(echo "$line" | cut --only-delimited -d= -f2)"
if [ -z "$_custom_path" ]; then
continue
fi
eval "_custom_path=$_custom_path"
if [ ! -d "$_custom_path" ]; then
mkdir -p "$_custom_path"
if [ $? -ne 0 ]; then
cur_date="$(date +"%Y-%m-%d %H:%M:%S")"
echo "[Common] [$cur_date] [ERROR]: create $_custom_path failed."
return 1
fi
fi
done < $_custom_path_file
return 0
}
py_version_check(){
local pyver_set="3.7 3.8 3.9 3.10 3.11 3.12"
local cur_date="$(date +"%Y-%m-%d %H:%M:%S")"
which python3 > /dev/null 2>&1
if [ $? -eq 0 ]; then
local python_version="$(python3 --version 2>&1 | head -n 1)"
local python3_version=$(echo "$python_version" | sed -n 's/.*[^\.0-9]\([0-9]\+\.[0-9]\+\).*/\1/p')
if [ "x$python3_version" != "x" ]; then
for ver in $pyver_set; do
if [ "x$ver" = "x$python3_version" ]; then
return 0
fi
done
echo "[Common] [$cur_date] [WARNING]: $python_version is not in Python3.7.x, Python3.8.x, Python3.9.x, Python3.10.x, Python3.11.x, Python3.12.x"
return 1
else
echo "[Common] [$cur_date] [WARNING]: $python_version cannot be identified as a standard version, please check manually."
return 1
fi
else
echo "[Common] [$cur_date] [WARNING]: python3 is not found."
return 1
fi
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,305 @@
#!/bin/sh
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
# 多版本函数库
# 创建版本目录
create_version_dir() {
local install_path="$1"
local version_dir="$2"
local username="$3"
local usergroup="$4"
local install_for_all="$5"
local ret
if [ ! -d "${install_path}/${version_dir}" ]; then
make_dir "${install_path}/${version_dir}"
ret="$?" && [ $ret -ne 0 ] && return $ret
fi
# 约束版本号目录权限
change_mod "${install_path}/${version_dir}" "750" "${install_for_all}"
ret="$?" && [ $ret -ne 0 ] && return $ret
change_own "${install_path}/${version_dir}" "${username}:${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
return 0
}
# 检查版本包安装结果
check_version_install() {
local install_path="$1"
local version_dir="$2"
local package="$3"
local version_info_path
get_package_version_info "version_info_path" "$install_path" "$version_dir" "$package"
if [ ! -f "$version_info_path" ]; then
comm_log "ERROR" "$version_info_path doesn't exist in check version install!"
return 1
fi
return 0
}
# 安装latest管理器
install_latest_manager() {
local var_path="$1"
shift 1
sh latest_manager/install.sh --install-path="$var_path" "$@"
}
# 卸载latest管理器
uninstall_latest_manager_for_upgrade() {
local var_path="$1"
${var_path}/manager/uninstall.sh --upgrade
}
# 升级latest管理器
upgrade_latest_manager() {
local var_path="$1"
local latest_version_info latest_manager_version local_manager_version
latest_version_info="$var_path/manager/version.info"
if [ -f "$latest_version_info" ]; then
get_version latest_manager_version "$latest_version_info"
get_version local_manager_version "latest_manager/version.info"
set_default "latest_manager_version" "$latest_manager_version" "0"
set_default "local_manager_version" "$local_manager_version" "0"
if [ "$latest_manager_version" -lt "$local_manager_version" ]; then
uninstall_latest_manager_for_upgrade "$var_path"
install_latest_manager "$var_path" "--upgrade"
fi
else
install_latest_manager "$var_path"
fi
}
get_install_for_all_param() {
local _outvar="$1"
local _install_for_all="$2"
local _result=""
if [ "$_install_for_all" = "y" ]; then
_result="--install-for-all"
fi
eval "${_outvar}=\"${_result}\""
}
get_docker_root_param() {
local _outvar="$1"
local _docker_root="$2"
local _result=""
if [ "$_docker_root" != "" ]; then
_result="--docker-root \\\"$_docker_root\\\""
fi
eval "${_outvar}=\"${_result}\""
}
# 通知latest管理器
notify_latest_manager() {
local var_path="$1"
local package="$2"
local version="$3"
local version_dir="$4"
local install_for_all="$5"
local docker_root="$6"
local ext_params="$7"
local operation="$8"
local ret package_dir install_for_all_param docker_root_param
if [ ! -f "$var_path/manager.sh" ]; then
return 1
fi
if [ "${USE_SHARE_INFO}" == "y" ]; then
ext_params="$ext_params --use-share-info"
fi
get_package_dir package_dir "$package"
get_install_for_all_param "install_for_all_param" "$install_for_all"
get_docker_root_param "docker_root_param" "$docker_root"
eval "\"$var_path/manager.sh\"" --version "\"$version\"" --version-dir "\"$version_dir\"" \
--package "\"$package\"" --package-dir "\"$package_dir\"" \
"$install_for_all_param" "$docker_root_param" "$ext_params" "$operation"
ret="$?" && [ $ret -ne 0 ] && return $ret
return 0
}
# 通知latest管理器安装完成
notify_latest_manager_installed() {
local local_manager_version
local ext_params
get_version local_manager_version "latest_manager/version.info"
set_default "local_manager_version" "$local_manager_version" "0"
if [ "$INCREMENT" = "y" ]; then
ext_params="--serial $local_manager_version --increment"
else
ext_params="--serial $local_manager_version"
fi
notify_latest_manager "$@" "$ext_params" "package_installed"
}
# 通知latest管理器创建软链
# 老版本全部卸载后latest回滚到新版本时会用老版本的install_common_parser.sh
# 调用新版本的--create-package-latest-softlink会走到这个流程。
notify_latest_manager_create_softlink() {
notify_latest_manager "$@" "" "package_create_softlink"
}
# 通知latest管理器删除软链
notify_latest_manager_remove_softlink() {
notify_latest_manager "$@" "" "package_remove_softlink"
}
# 通知latest管理器准备卸载
notify_latest_manager_pre_uninstall() {
notify_latest_manager "$@" "" "package_pre_uninstall"
}
# 通知latest管理器卸载完成
notify_latest_manager_uninstalled() {
local is_recreate_softlink="$1"
local recreate_softlink=""
local ret
shift 1
if [ "$is_recreate_softlink" = "y" ]; then
recreate_softlink="--recreate-softlink"
fi
notify_latest_manager "$@" "$recreate_softlink" "package_uninstalled"
ret="$?" && [ $ret -ne 0 ] && return $ret
return 0
}
# 多版本安装流程
multi_version_install() {
local install_type="$1"
local install_path="$2"
local filelist_path="$3"
local package="$4"
local feature_param="$5"
local version="$6"
local version_dir="$7"
local username="$8"
local usergroup="$9"
local setenv="${10}"
local is_upgrade="${11}"
local docker_root="${12}"
local custom_options="${13}"
local install_for_all="${14}"
local ret total_ret="0" pkg_running_version version_pair_arr last_version last_version_dir
create_version_dir "${install_path}" "${version_dir}" "${username}" "${usergroup}" "${install_for_all}"
ret="$?" && [ $ret -ne 0 ] && return $ret
version_install "${install_type}" "${install_path}" "${filelist_path}" "${package}" "${feature_param}" \
"${version_dir}" "${username}" "${usergroup}" "${setenv}" "${is_upgrade}" "${docker_root}" "${custom_options}"
ret="$?" && [ $ret -ne 0 ] && return $ret
check_version_install "$install_path" "$version_dir" "$package"
ret="$?" && [ $ret -ne 0 ] && return $ret
return ${total_ret}
}
# 删除latest下空目录
del_empty_dirs_in_latest() {
local install_type="$1"
local install_path="$2"
local latest_dir="$3"
local filelist_path="$4"
local feature_param="$5"
local ret
create_stash_mod "${install_path}/${latest_dir}"
ret="$?" && [ $ret -ne 0 ] && return $ret
foreach_filelist "filter_common_dirs" "reset_mod_dirs_with_stash_mod" "${install_type}" "${install_path}/${latest_dir}" "mkdir" \
"${filelist_path}" "${feature_param}" "no" "normal"
ret="$?" && [ $ret -ne 0 ] && return $ret
foreach_filelist "filter_common_dirs" "remove_install_dirs" "${install_type}" "${install_path}/${latest_dir}" "mkdir" \
"${filelist_path}" "${feature_param}" "reverse" "normal"
ret="$?" && [ $ret -ne 0 ] && return $ret
foreach_stashmod "restore_stash_mod" "${install_path}/${latest_dir}" "reverse"
ret="$?" && [ $ret -ne 0 ] && return $ret
remove_stash_mod "${install_path}/${latest_dir}"
ret="$?" && [ $ret -ne 0 ] && return $ret
return 0
}
# 多版本卸载流程
multi_version_uninstall() {
local install_type="$1"
local install_path="$2"
local filelist_path="$3"
local package="$4"
local feature_param="$5"
local version="$6"
local version_dir="$7"
local username="$8"
local usergroup="$9"
local docker_root="${10}"
local custom_options="${11}"
local is_recreate_softlink="${12}"
local tmp_root tmp_filelist_path
local ret total_ret=0 install_path_full="" is_running="" is_upgrade
local running_packages is_final_running="false"
check_param_not_empty "usergroup" "need set usergroup parameter in multi version uninstall!"
ret="$?" && [ ${ret} -ne 0 ] && return ${ret}
get_tmp_root "tmp_root"
tmp_filelist_path=$(mktemp "$tmp_root/filelist_XXXXXX" || exit 1)
cp -f "${filelist_path}" "${tmp_filelist_path}"
if [ $? -ne 0 ]; then
log "ERROR" "cp -f ${filelist_path} ${tmp_filelist_path} failed!"
exit 1
fi
del_tmp_filelist="rm -f \"${tmp_filelist_path}\""
version_uninstall "${install_type}" "${install_path}" "${filelist_path}" "${package}" "${feature_param}" \
"${version_dir}" "${username}" "${docker_root}" "${custom_options}"
if [ $? -ne 0 ]; then
eval "${del_tmp_filelist}"
return 1
fi
# 删除临时文件tmp_filelist_path
eval "${del_tmp_filelist}"
# 删除版本空目录
is_dir_empty "${install_path}/${version_dir}"
if [ $? -eq 0 ]; then
remove_dir_icp "${install_path}/${version_dir}"
ret="$?" && [ $ret -ne 0 ] && total_ret="1"
fi
return ${total_ret}
}

View File

@@ -0,0 +1,469 @@
#!/bin/sh
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
# 公共脚本操作库
ENV_SHELL_TYPES="bash csh fish"
# 检查参数。
__check_param() {
local name="$1"
local value
value="$(eval echo \${${name}})"
if [ "${value}" = "" ]; then
log "ERROR" "need set ${name} parameter!"
exit 1
fi
}
# 设置用户家目录路径
__set_userpath() {
local username="$1"
local docker_root="$2"
if [ -z "${docker_root}" ] || [ "${docker_root}" = "/" ]; then
userpath="$(eval echo "~${username}")"
else
if [ "${username}" = "root" ]; then
userpath="${docker_root}/root"
else
userpath="${docker_root}/home/${username}"
fi
fi
}
# 获取setenv.[shell]路径正则
get_setenv_path_regex() {
local _outvar="$1"
local _package="$2"
local _shell_type="$3"
# setenv传入路径正则规则
# 必须以/开头(绝对路径)
# 必须以/${package}/bin/setenv.${shell_type}结尾
local _path_regex="\/\(.\+\/\)\?${_package}\/bin\/setenv.${_shell_type}"
eval "${_outvar}=\"${_path_regex}\""
}
# 创建setenv文件
__create_setenv_file() {
local file="$1"
local shell_type="$2"
local add_multi_version_param="$3"
local install_path="$4"
local ret
if [ ! -f "${file}" ]; then
echo "#!/usr/bin/env ${shell_type}" > ${file}
ret="$?" && [ $ret -ne 0 ] && return $ret
if [ "${add_multi_version_param}" = "true" ]; then
if [ "${shell_type}" = "bash" ]; then
echo "export ASCEND_HOME_PATH=\"${install_path}\"" >> "${file}"
ret="$?" && [ $ret -ne 0 ] && return $ret
elif [ "${shell_type}" = "fish" ]; then
echo "set -gx ASCEND_HOME_PATH \"${install_path}\"" >> "${file}"
ret="$?" && [ $ret -ne 0 ] && return $ret
elif [ "${shell_type}" = "csh" ]; then
echo "setenv ASCEND_HOME_PATH \"${install_path}\"" >> "${file}"
ret="$?" && [ $ret -ne 0 ] && return $ret
fi
fi
fi
return 0
}
# 是否存在ASCEND_HOME_PATH环境变量
has_ascend_home_path_env() {
local file="$1"
[ ! -f "${file}" ] && return 0
grep "\<ASCEND_HOME_PATH\>" "${file}" > /dev/null 2>&1
}
# 添加ASCEND_HOME_PATH环境变量
add_ascend_home_path_env() {
local file="$1"
local shell_type="$2"
local install_path="$3"
if [ "${shell_type}" = "bash" ]; then
sed -i "1aexport ASCEND_HOME_PATH=\"${install_path}\"" "${file}"
elif [ "${shell_type}" = "fish" ]; then
sed -i "1aset -gx ASCEND_HOME_PATH \"${install_path}\"" "${file}"
elif [ "${shell_type}" = "csh" ]; then
sed -i "1asetenv ASCEND_HOME_PATH \"${install_path}\"" "${file}"
fi
}
# 删除rcfile中的source <path>
__remove_path_regex() {
local path_regex="$1"
local rcfile="$2"
if [ -f "${rcfile}" ]; then
sed -i "/source ${path_regex}\( \"multi_version\"\)\?$/d" "${rcfile}"
if [ $? -ne 0 ]; then
log "ERROR" "remove ${rcfile} source command failed!"
exit 1
fi
fi
}
# 获取setenv.${shell_type}文件路径
get_setenv_filepath() {
local _outvar="$1"
local _install_path="$2"
local _shell_type="$3"
eval "${_outvar}=\"${_install_path}/bin/setenv.${_shell_type}\""
}
# setenv.[shell]总脚本中添加一条语句
add_setenv_cmd() {
local install_path="$1"
local setenv_filepath="$2"
local package="$3"
local shell_type="$4"
local username="$5"
local usergroup="$6"
local add_multi_version_param="$7"
local path_regex config_path multi_version_param ret
get_setenv_path_regex "path_regex" "${package}" "${shell_type}"
get_setenv_filepath "config_path" "$install_path" "$shell_type"
__create_setenv_file "${config_path}" "${shell_type}" "${add_multi_version_param}" "${install_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
change_own "${config_path}" "${username}:${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
change_mod "${config_path}" "${SETENV_WRITEABLE_MOD}" ""
ret="$?" && [ $ret -ne 0 ] && return $ret
__remove_path_regex "${path_regex}" "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
if [ "${add_multi_version_param}" = "true" ]; then
multi_version_param=" \"multi_version\""
fi
if [ "${shell_type}" = "bash" ] || [ "${shell_type}" = "fish" ]; then
echo "source ${setenv_filepath}${multi_version_param}" >> "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
elif [ "${shell_type}" = "csh" ]; then
echo "set argv=(\"${setenv_filepath}\"${multi_version_param}); source ${setenv_filepath}" >> "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
fi
change_mod "${config_path}" "${SETENV_MOD}" "${INSTALL_FOR_ALL}"
ret="$?" && [ $ret -ne 0 ] && return $ret
return 0
}
# 修改路径的own
__chown_path() {
local path="$1"
local username="$2"
local usergroup="$3"
if [ "${username}" != "" ] && [ "${usergroup}" != "" ]; then
chown -h "${username}:${usergroup}" "${path}"
if [ $? -ne 0 ]; then
log "ERROR" "${path} chown failed!"
exit 1
fi
fi
return 0
}
# 创建配置所在目录
__create_config_dir() {
local dir="$1"
local username="$2"
local usergroup="$3"
local ret
if [ ! -d "${dir}" ]; then
mkdir -p "${dir}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__chown_path "${dir}" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
fi
return 0
}
# 创建配置文件
__create_config_file() {
local file="$1"
local username="$2"
local usergroup="$3"
local ret
if [ ! -f "${file}" ]; then
touch "${file}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__chown_path "${file}" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
fi
return 0
}
# 为bash添加rc配置
add_bash_env_rc() {
local userpath="$1"
local username="$2"
local usergroup="$3"
local path_regex="$4"
local setenv_filepath="$5"
local config_path="${userpath}/.bashrc"
local ret
__create_config_dir "${userpath}" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__create_config_file "${config_path}" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__remove_path_regex "${path_regex}" "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
echo "source ${setenv_filepath}" >> "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
}
# 为fish添加rc配置
add_fish_env_rc() {
local userpath="$1"
local username="$2"
local usergroup="$3"
local path_regex="$4"
local setenv_filepath="$5"
local config_path="${userpath}/.config/fish/config.fish"
local ret
__create_config_dir "${userpath}" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__create_config_dir "${userpath}/.config" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__create_config_dir "${userpath}/.config/fish" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__create_config_file "${config_path}" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__remove_path_regex "${path_regex}" "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
echo "source ${setenv_filepath}" >> "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
}
# 为csh添加rc配置
add_csh_env_rc() {
local userpath="$1"
local username="$2"
local usergroup="$3"
local path_regex="$4"
local setenv_filepath="$5"
local config_path="${userpath}/.cshrc"
local ret
__create_config_dir "${userpath}" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__create_config_file "${config_path}" "${username}" "${usergroup}"
ret="$?" && [ $ret -ne 0 ] && return $ret
__remove_path_regex "${path_regex}" "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
echo "set argv=(\"${setenv_filepath}\"); source ${setenv_filepath}" >> "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
}
# 添加source setenv.[shell]脚本到rc文件中
add_env_rc() {
local install_path="$1"
local setenv_filepath="$2"
local package="$3"
local shell_type="$4"
local setenv="$5"
local username="$6"
local usergroup="$7"
local add_multi_version_param="$8"
local docker_root="$9"
local path_suffix="${package}/bin/setenv.${shell_type}"
local path_regex
local matched
local userpath
local config_path
local ret
__check_param "package"
__check_param "username"
__check_param "usergroup"
echo "${shell_type}" | grep -E "^(bash|fish|csh)$" > /dev/null
if [ $? -ne 0 ]; then
log "ERROR" "shell type ${shell_type} not support!"
exit 1
fi
get_setenv_path_regex "path_regex" "${package}" "${shell_type}"
matched="$(echo "${setenv_filepath}" | sed -n "/^${path_regex}$/p")"
if [ -z "${matched}" ]; then
log "ERROR" "setenv filepath is illegal, should endswith ${path_suffix}"
exit 1
fi
if [ "${setenv}" = "y" ]; then
__set_userpath "${username}" "${docker_root}"
case "${shell_type}" in
bash) add_bash_env_rc "${userpath}" "${username}" "${usergroup}" "${path_regex}" "${setenv_filepath}" ;;
fish) add_fish_env_rc "${userpath}" "${username}" "${usergroup}" "${path_regex}" "${setenv_filepath}" ;;
csh) add_csh_env_rc "${userpath}" "${username}" "${usergroup}" "${path_regex}" "${setenv_filepath}" ;;
esac
ret="$?" && [ $ret -ne 0 ] && return $ret
fi
# 如果bin目录不存在则不处理
[ ! -d "${install_path}/bin" ] && return 0
add_setenv_cmd "${install_path}" "${setenv_filepath}" "${package}" "${shell_type}" "${username}" "${usergroup}" "${add_multi_version_param}"
}
# 删除setenv文件如果已经没有setenv内容
__remove_setenv_file_if_no_content() {
local file="$1"
local shell_type="$2"
local num
if [ ! -f "${file}" ]; then
return 0
fi
num=$(grep "setenv.${shell_type}" ${file} | wc -l)
if [ ${num} -eq 0 ]; then
rm -f "${file}" > /dev/null 2>&1
if [ $? -ne 0 ]; then
log "WARNING" "Delete file:${file} failed, please delete it by yourself."
fi
fi
}
# 从rc文件中删除source setenv.[shell]
del_env_rc() {
local install_path="$1"
local setenv_filepath="$2"
local shell_type="$3"
local username="$4"
local docker_root="$5"
local path_regex
local userpath
local config_path
local oldmod
__check_param "username"
echo "${shell_type}" | grep -E "^(bash|fish|csh)$" > /dev/null
if [ $? -ne 0 ]; then
log "ERROR" "shell type ${shell_type} not support!"
exit 1
fi
__set_userpath "${username}" "${docker_root}"
# 将路径中的/转换为\/
path_to_regex "path_regex" "${setenv_filepath}"
if [ "${shell_type}" = "bash" ]; then
__remove_path_regex "${path_regex}" "${userpath}/.bashrc"
ret="$?" && [ $ret -ne 0 ] && return $ret
elif [ "${shell_type}" = "fish" ]; then
__remove_path_regex "${path_regex}" "${userpath}/.config/fish/config.fish"
ret="$?" && [ $ret -ne 0 ] && return $ret
elif [ "${shell_type}" = "csh" ]; then
__remove_path_regex "${path_regex}" "${userpath}/.cshrc"
ret="$?" && [ $ret -ne 0 ] && return $ret
fi
get_setenv_filepath "config_path" "$install_path" "$shell_type"
if [ ! -f "${config_path}" ]; then
# 如果文件不存在,则不处理
return 0
fi
get_file_mod "oldmod" "${config_path}"
change_mod "${config_path}" "${SETENV_WRITEABLE_MOD}" ""
ret="$?" && [ $ret -ne 0 ] && return $ret
__remove_path_regex "${path_regex}" "${config_path}"
ret="$?" && [ $ret -ne 0 ] && return $ret
change_mod "${config_path}" "${oldmod}" ""
ret="$?" && [ $ret -ne 0 ] && return $ret
__remove_setenv_file_if_no_content "${config_path}" "${shell_type}"
}
# 移除路径中的docker_root
remove_path_docker_root() {
local _outvar="$1"
local _path="$2"
local _docker_root="$3"
local _path_rpdr="$(echo "${_path}" | sed "s/^.\{${#_docker_root}\}//")"
eval "${_outvar}=\"${_path_rpdr}\""
}
# 获取脚本路径与脚本真实路径docker_root
get_shell_path_and_shell_path_real() {
local _outvar="$1"
local _install_path="$2"
local _package="$3"
local _shell_filename="$4"
local _docker_root="$5"
local _package_dirpath _shell_path _shell_path_real
get_package_dirpath "_package_dirpath" "${_package}"
_shell_path_real="${_install_path}/${_package_dirpath}/bin/${_shell_filename}"
if [ "${_docker_root}" != "" ]; then
# 移除脚本路径中的docker_root前缀
remove_path_docker_root "_shell_path" "${_shell_path_real}" "${_docker_root}"
else
_shell_path="${_shell_path_real}"
fi
eval "${_outvar}=\"${_shell_path} ${_shell_path_real}\""
}
# 设置环境变量
add_setenv() {
return 0
}
# 删除环境变量
del_setenv() {
return 0
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,174 @@
#!/bin/sh
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
# 获取版本号,用于版本兼容性对比
get_package_compat_version() {
local _outvar="$1"
local _version_info_path="$2"
local _result
if [ ! -f "${_version_info_path}" ]; then
read -r "$_outvar" <<EOF
EOF
return 1
fi
read -r "$_outvar" <<EOF
$(grep "^Version=" "$_version_info_path" | cut -d= -f2- | cut -d- -f1 | cut -d. -f-3)
EOF
}
# 获取正式包名
get_formal_package_name() {
local _outvar="$1"
local _package="$2"
read -r "$_outvar" <<EOF
$(echo "$_package" | sed 's/_/-/g')
EOF
}
# 获取非正式包名
get_informal_package_name() {
local _outvar="$1"
local _package="$2"
read -r "$_outvar" <<EOF
$(echo "$_package" | sed 's/-/_/g')
EOF
}
# 获取需求包列表。
_get_required_packages() {
local _version_info_path="$1"
if [ ! -f "$_version_info_path" ]; then
return 0
fi
awk '
function join(items, len, sep, result, i) {
if (len >= 1) {
result = items[1]
for (i = 2; i <= len; i++) {
result = sprintf("%s%s%s", result, sep, items[i])
}
return result
}
return ""
}
/^required_package_.+_version=/ {
split($0, line_tokens, "=")
len_require_tokens = split(line_tokens[1], require_tokens, "_")
len_package_names = 0
for (i = 3; i < len_require_tokens; i++) {
len_package_names++
package_names[len_package_names] = require_tokens[i]
}
package_name = join(package_names, len_package_names, "_")
print package_name
}
' "${_version_info_path}"
}
# 获取需求包信息。
_get_required_package_info() {
local _outvar="$1"
local _version_info_path="$2"
local _pkg_name="$3"
local _required_pkg_name
local _required_value
if [ ! -f "${_version_info_path}" ]; then
eval "${_outvar}=\"\""
return 1
fi
_required_pkg_name="required_package_${_pkg_name}_version"
_required_value="$(grep "^${_required_pkg_name}=" "${_version_info_path}" | cut -d= -f2-)"
# _required_value取得的值带有双引号eval时不可以在外侧再添加双引号
eval "${_outvar}=${_required_value}"
}
# 检查版本与需求版本兼容性。
# 兼容返回0不兼容返回1
_check_version_required() {
local version="$1"
local require="$2"
local script_dir="$3"
local src_pkg="$4"
local dst_pkg="$5"
local result
result=$(awk -f "${script_dir}/check_version_required.awk" -v version="${version}" -v all_required="${require}")
if [ "${result}" = "T" ]; then
return 0
fi
echo "Version compatibility check failed, $src_pkg required $dst_pkg version $require, but $dst_pkg version is $version!"
return 1
}
# 检查版本兼容性。
_check_version_compatiable() {
local package="$1"
local install_path="$2"
local script_dir="$3"
local version_info_path="$script_dir/../version.info"
local err_msgs package_formal self_version src_pkg src_pkg_formal dst_pkg dst_pkg_formal
local installed_version_info pkg_version_info_path
get_formal_package_name "package_formal" "$package"
get_package_compat_version "self_version" "$version_info_path"
if [ -d "$install_path/share/info" ]; then
err_msgs="$(
ls "$install_path/share/info" | grep -v "^${package}$" | while read src_pkg; do
get_formal_package_name "src_pkg_formal" "$package"
installed_version_info="$install_path/share/info/$src_pkg/version.info"
grep "^required_package_${package_formal}_version=" "$installed_version_info" | cut -d= -f2- | tr -d '"' | while read required; do
_check_version_required "$self_version" "$required" "$script_dir" "$src_pkg_formal" "$package_formal"
done
done
)"
if [ "$err_msgs" != "" ]; then
while read err_msg; do
comm_log "ERROR" "$err_msg"
done <<EOF
$err_msgs
EOF
return 1
fi
fi
err_msgs="$(
_get_required_packages "${version_info_path}" | while read dst_pkg_formal; do
get_informal_package_name "dst_pkg" "$dst_pkg_formal"
pkg_version_info_path="$install_path/share/info/$dst_pkg_formal/version.info"
if [ ! -f "$pkg_version_info_path" ]; then
pkg_version_info_path="$install_path/share/info/$dst_pkg/version.info"
fi
if [ -f "$pkg_version_info_path" ]; then
get_package_compat_version "pkg_version" "$pkg_version_info_path"
_get_required_package_info "required" "$version_info_path" "$dst_pkg_formal"
_check_version_required "$pkg_version" "$required" "$script_dir" "$package_formal" "$dst_pkg_formal"
fi
done
)"
if [ "$err_msgs" != "" ]; then
while read err_msg; do
comm_log "ERROR" "$err_msg"
done <<EOF
$err_msgs
EOF
return 1
fi
return 0
}

View File

@@ -0,0 +1,16 @@
module,operation,relative_path_in_pkg,relative_install_path,is_in_docker,permission,owner:group,install_type,softlink,feature,is_common_path,configurable,hash,block,pkg_inner_softlink,chip
NA,mkdir,NA,manager,TRUE,550,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/filelist.csv,manager/filelist.csv,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/install.sh,manager/install.sh,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/manager.sh,manager.sh,TRUE,550,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/manager_func.sh,manager/manager_func.sh,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/script_operator.inc,manager/script_operator.inc,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/uninstall.sh,manager/uninstall.sh,TRUE,550,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/version.info,manager/version.info,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/version_compatiable.inc,manager/version_compatiable.inc,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/check_version_required.awk,manager/check_version_required.awk,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/common_func_v2.inc,manager/common_func_v2.inc,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/common_func.inc,manager/common_func.inc,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/common_installer.inc,manager/common_installer.inc,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/install_common_parser.sh,manager/install_common_parser.sh,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
NA,copy,latest_manager/version_cfg.inc,manager/version_cfg.inc,TRUE,440,\\$username:\\$usergroup,all,NA,all,N,FALSE,NA,latest_manager,NA,all
1 module operation relative_path_in_pkg relative_install_path is_in_docker permission owner:group install_type softlink feature is_common_path configurable hash block pkg_inner_softlink chip
2 NA mkdir NA manager TRUE 550 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
3 NA copy latest_manager/filelist.csv manager/filelist.csv TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
4 NA copy latest_manager/install.sh manager/install.sh TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
5 NA copy latest_manager/manager.sh manager.sh TRUE 550 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
6 NA copy latest_manager/manager_func.sh manager/manager_func.sh TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
7 NA copy latest_manager/script_operator.inc manager/script_operator.inc TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
8 NA copy latest_manager/uninstall.sh manager/uninstall.sh TRUE 550 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
9 NA copy latest_manager/version.info manager/version.info TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
10 NA copy latest_manager/version_compatiable.inc manager/version_compatiable.inc TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
11 NA copy latest_manager/check_version_required.awk manager/check_version_required.awk TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
12 NA copy latest_manager/common_func_v2.inc manager/common_func_v2.inc TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
13 NA copy latest_manager/common_func.inc manager/common_func.inc TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
14 NA copy latest_manager/common_installer.inc manager/common_installer.inc TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
15 NA copy latest_manager/install_common_parser.sh manager/install_common_parser.sh TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all
16 NA copy latest_manager/version_cfg.inc manager/version_cfg.inc TRUE 440 \\$username:\\$usergroup all NA all N FALSE NA latest_manager NA all

View File

@@ -0,0 +1,59 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
CURPATH=$(dirname $(readlink -f "$0"))
USERNAME=$(id -un)
USERGROUP=$(id -gn)
common_func_path="${CURPATH}/common_func.inc"
. "$common_func_path"
INSTALL_PATH=""
IS_UPGRADE="n"
set_comm_log "Latest_manager" "$COMM_LOGFILE"
while true
do
case "$1" in
--install-path=*)
INSTALL_PATH="$(echo "$1" | cut -d"=" -f2-)"
shift
;;
--upgrade)
IS_UPGRADE="y"
shift
;;
-*)
comm_log "ERROR" "Unsupported parameters : $1"
exit 1
;;
*)
break
;;
esac
done
if [ "$INSTALL_PATH" = "" ]; then
comm_log "ERROR" "--install-path parameter is required!"
exit 1
fi
if ! sh "$CURPATH/install_common_parser.sh" --package="latest_manager" --install --username="$USERNAME" --usergroup="$USERGROUP" \
--simple-install "full" "$INSTALL_PATH" "$CURPATH/filelist.csv" "all"; then
comm_log "ERROR" "install failed!"
exit 1
fi
if [ "$IS_UPGRADE" = "y" ] && ! "$INSTALL_PATH/manager.sh" "migrate_latest_data"; then
comm_log "ERROR" "migrate latest data failed!"
exit 1
fi

View File

@@ -0,0 +1,128 @@
#!/bin/sh
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
CURPATH=$(dirname "$(readlink -f "$0")")
VAR_PATH="$CURPATH"
common_func_path="$CURPATH/manager/common_func.inc"
version_compatiable_path="$CURPATH/manager/version_compatiable.inc"
common_func_v2_path="$CURPATH/manager/common_func_v2.inc"
version_cfg_path="$CURPATH/manager/version_cfg.inc"
script_operator_path="$CURPATH/manager/script_operator.inc"
manager_func_path="$CURPATH/manager/manager_func.sh"
. "$common_func_path"
. "$version_compatiable_path"
. "$common_func_v2_path"
. "$version_cfg_path"
. "$script_operator_path"
. "$manager_func_path"
set_comm_log "Latest_manager" "$COMM_LOGFILE"
VERSION=""
VERSION_DIR=""
PACKAGE=""
DOCKER_ROOT=""
INTPUT_INSTALL_FOR_ALL="n"
IS_RECREATE_SOFTLINK="n"
INCREMENT="n"
USE_SHARE_INFO="n"
while true
do
case "$1" in
--version)
VERSION="$2"
shift 2
;;
--version-dir)
VERSION_DIR="$2"
shift 2
;;
--package)
PACKAGE="$2"
shift 2
;;
--package-dir)
shift 2
;;
--serial)
shift 2
;;
--install-type)
shift 2
;;
--feature)
shift 2
;;
--chip)
shift 2
;;
--filelist)
shift 2
;;
--docker-root)
DOCKER_ROOT="$2"
shift 2
;;
--recreate-softlink)
IS_RECREATE_SOFTLINK="y"
shift 1
;;
--install-for-all)
INTPUT_INSTALL_FOR_ALL="y"
shift 1
;;
--increment)
INCREMENT="y"
shift 1
;;
--use-share-info)
USE_SHARE_INFO="y"
shift 1
;;
-*)
comm_log "ERROR" "Unsupported parameters : $1"
exit 1
;;
*)
break
;;
esac
done
if [ "$PACKAGE" != "" ]; then
get_titled_package_name "TITLED_PACKAGE" "$PACKAGE"
set_comm_log "$TITLED_PACKAGE" "$COMM_LOGFILE"
fi
OPERATION="$1"
if [ "$OPERATION" = "package_installed" ]; then
package_installed "$CURPATH" "$VERSION" "$VERSION_DIR" "$PACKAGE" \
"$INTPUT_INSTALL_FOR_ALL" "$DOCKER_ROOT"
elif [ "$OPERATION" = "package_pre_uninstall" ]; then
package_pre_uninstall "$CURPATH" "$VERSION" "$VERSION_DIR" "$PACKAGE" \
"$INTPUT_INSTALL_FOR_ALL" "$DOCKER_ROOT"
elif [ "$OPERATION" = "package_uninstalled" ]; then
package_uninstalled "$CURPATH" "$VERSION" "$VERSION_DIR" "$PACKAGE" "$IS_RECREATE_SOFTLINK" \
"$DOCKER_ROOT"
elif [ "$OPERATION" = "package_create_softlink" ]; then
package_create_softlink "$CURPATH" "$VERSION" "$VERSION_DIR" "$PACKAGE" "$DOCKER_ROOT"
elif [ "$OPERATION" = "package_remove_softlink" ]; then
package_remove_softlink "$CURPATH" "$VERSION" "$VERSION_DIR" "$PACKAGE" "$DOCKER_ROOT"
elif [ "$OPERATION" = "create_version_softlink" ]; then
create_version_softlink "$CURPATH" "$VERSION_DIR"
elif [ "$OPERATION" = "remove_latest_softlink" ]; then
remove_latest_softlink "$CURPATH"
elif [ "$OPERATION" = "migrate_latest_data" ]; then
migrate_latest_data "$CURPATH"
fi

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
CURPATH=$(dirname $(readlink -f "$0"))
VARPATH="$(dirname "$CURPATH")"
USERNAME=$(id -un)
USERGROUP=$(id -gn)
common_func_path="$CURPATH/common_func.inc"
manager_func_path="$CURPATH/manager_func.sh"
. "$common_func_path"
. "$manager_func_path"
set_comm_log "Latest_manager" "$COMM_LOGFILE"
IS_UPGRADE="n"
while true
do
case "$1" in
--upgrade)
IS_UPGRADE="y"
shift
;;
*)
break
;;
esac
done
if ! sh "$CURPATH/install_common_parser.sh" --package="latest_manager" --uninstall --username="$USERNAME" --usergroup="$USERGROUP" \
--simple-uninstall "full" "$VARPATH" "$CURPATH/filelist.csv" "all"; then
comm_log "ERROR" "uninstall failed!"
exit 1
fi
if [ "$IS_UPGRADE" = "n" ]; then
remove_manager_refs "$VARPATH"
fi
if ! remove_dir_if_empty "$VARPATH"; then
comm_log "ERROR" "uninstall failed!"
exit 1
fi

View File

@@ -0,0 +1 @@
Version=45

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<block name="EngineeringCommon" install_own="$username:$usergroup" install_mod="440" install_type="all">
<dir_info value="common" install_mod="550">
<path value="$(TARGET_ENV)"/>
<path value="$(TARGET_ENV)/bin" install_softlink="bin"/>
<path value="$(TARGET_ENV)/include" install_softlink="include"/>
<path value="$(TARGET_ENV)/include/version" install_type="devel"/>
<path value="$(TARGET_ENV)/lib64" install_softlink="lib64"/>
<path value="$(TARGET_ENV)/devlib" install_softlink="devlib"/>
<path value="$(TARGET_ENV)/conf" install_softlink="conf"/>
<path value="$(TARGET_ENV)/pkg_inc" install_softlink="pkg_inc"/>
<path value="var" install_mod="750"/>
</dir_info>
</block>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<block name="EngineeringFiles" install_own="$username:$usergroup" install_mod="440" install_type="all">
<file_info value="conf" copy_type="source" src_path="build/release/config/common" dst_path="conf" install_path="$(TARGET_ENV)/conf">
<file value="path.cfg"/>
</file_info>
</block>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<block name="OpsTransformer" copy_type="delivery" src_path="" dst_path="" install_path="" install_own="$username:$usergroup" install_mod="550" install_type="run;devel">
<dir_info install_mod="550">
<path value="$(TARGET_ENV)/lib64"/>
<path value="$(TARGET_ENV)/include"/>
<path value="$(TARGET_ENV)/include/aclnn_kernels"/>
<path value="$(TARGET_ENV)/include/aclnnop"/>
</dir_info>
<file_info value="opapi_transformer_lib" copy_type="delivery" src_path=""
dst_path="built-in/op_impl/ai_core/tbe/op_api/lib/linux/$(ARCH)/"
install_path="$(TARGET_ENV)/lib64/">
<file value="libopapi_transformer.so" install_mod="550"/>
</file_info>
<file_info copy_type="delivery" src_path=""
dst_path="built-in/op_impl/ai_core/tbe/op_api/include"
install_path="$(TARGET_ENV)/include/" install_type="all">
<file value="aclnnop" install_mod="550"/>
</file_info>
<file_info value="rtkb" copy_type="source" src_path="" dst_path="built-in/data" install_path="opp/built-in/data">
<file value="op" entity="true" optional="true"/>
</file_info>
<dir_info value="rtkb_path" install_mod="750" install_type="all">
<path value="opp/built-in/data"/>
<path value="opp/built-in/data/op"/>
</dir_info>
</block>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<block name="OpsTransformerInc" copy_type="delivery" src_path="" dst_path="" install_path="" install_own="$username:$usergroup" install_mod="550"
install_type="all" pkg_feature="opp_binary">
<file_info copy_type="delivery" src_path=""
dst_path="built-in/op_impl/aicpu/"
install_path="opp/built-in/op_impl/aicpu/" install_type="all" optional="true">
<file value="config" install_mod="755"/>
<file value="kernel" install_mod="755"/>
</file_info>
<file_info copy_type="delivery" src_path=""
dst_path="built-in/op_graph/inc"
install_path="opp/built-in/op_graph/inc" install_type="all">
<file value="ops_proto_transformer.h" install_mod="550"/>
</file_info>
<file_info value="opgraph_transformer_lib" copy_type="delivery" src_path=""
dst_path="built-in/op_graph/lib/linux/$(ARCH)/"
install_path="opp/built-in/op_graph/lib/linux/$(ARCH)">
<file value="libopgraph_transformer.so" install_mod="550"/>
</file_info>
<file_info copy_type="delivery" src_path=""
dst_path="built-in/op_impl/ai_core/tbe"
install_path="opp/built-in/op_impl/ai_core/tbe" install_type="all">
<file value="config" install_mod="550"/>
</file_info>
<file_info copy_type="delivery" src_path=""
dst_path="built-in/op_impl/ai_core/tbe"
install_path="opp/built-in/op_impl/ai_core/tbe" install_type="all">
<file value="impl" install_mod="550"/>
</file_info>
<file_info copy_type="delivery" src_path=""
dst_path="built-in/op_impl/ai_core/tbe"
install_path="opp/built-in/op_impl/ai_core/tbe" install_type="all">
<file value="kernel" optional="true" install_mod="550"/>
</file_info>
<file_info copy_type="delivery" src_path=""
dst_path="built-in/op_impl/ai_core/tbe"
install_path="opp/built-in/op_impl/ai_core/tbe" install_type="all">
<file value="op_tiling_device" optional="true" install_mod="550"/>
</file_info>
<file_info value="ophost_transformer_lib" copy_type="delivery" src_path=""
dst_path="built-in/op_impl/ai_core/tbe/op_host/lib/linux/$(ARCH)/"
install_path="opp/built-in/op_impl/ai_core/tbe/op_host/lib/linux/$(ARCH)/">
<file value="libophost_transformer.so" install_mod="550"/>
</file_info>
<file_info value="op_transformer_onnx_plugin_lib" copy_type="delivery" src_path=""
dst_path="built-in/framework/onnx/" install_path="opp/built-in/framework/onnx">
<file value="libop_transformer_onnx_plugin.so" install_mod="550"/>
</file_info>
</block>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<config name="ops_transformer" copy_type="delivery" src_path="lib/" dst_path="ops_transformer" install_type="all" install_mod="550" install_own="$username:$usergroup">
<package_info>
<product_name>cann</product_name>
<chip_name>910b</chip_name>
<func_name>ops-transformer</func_name>
<suffix>run</suffix>
<install_script>share/info/ops_transformer/script/install.sh</install_script>
<help>share/info/ops_transformer/script/help.info</help>
<cleanup>share/info/ops_transformer/script/cleanup.sh</cleanup>
</package_info>
<generate_info value="ops_transformer_version.h" dst_path="share/info/ops_transformer" install_path="$(TARGET_ENV)/include/version" install_mod="440" install_type="devel" generator="version_header">
<OPS_TRANSFORMER_VERSION>$(ASCEND_VER)</OPS_TRANSFORMER_VERSION>
<OPS_TRANSFORMER_TIMESTAMP>$(TIMESTAMP_NO)</OPS_TRANSFORMER_TIMESTAMP>
</generate_info>
<generate_info value="scene.info" dst_path="share/info/ops_transformer" install_path="share/info/ops_transformer" install_mod="440">
<os>$(OS_NAME)</os>
<os_version>$(OS_VER)</os_version>
<arch>$(ARCH)</arch>
</generate_info>
<file_info value="ops_transformer_script" copy_type="source" src_path="" dst_path="share/info/ops_transformer" install_path="share/info/ops_transformer">
<file value="script" entity="true"/>
<file value="version.info"/>
</file_info>
<block_info dependtree="false" dst_path="ops_transformer" block_conf_path="ascend">
<block name="EngineeringCommon"/>
<block name="EngineeringFiles"/>
<block name="OpsTransformer"/>
<block name="OpsTransformerInc"/>
</block_info>
<dir_info value="ops_transformer" install_path="ops_transformer" install_type="all">
<path value="share" install_mod="550"/>
<path value="share/info" install_mod="750"/>
<path value="share/info/ops_transformer" install_mod="550"/>
<path value="share/info/ops_transformer/script" install_mod="550"/>
</dir_info>
<dir_info value="opp" install_path="opp" install_type="all">
<path value="opp" install_mod="750"/>
<path value="opp/script" install_mod="550"/>
<path value="opp/bin" install_mod="550"/>
<path value="opp/include" install_mod="550"/>
<path value="opp/lib64" install_mod="550"/>
<path value="opp/built-in" install_mod="550"/>
<path value="opp/built-in/op_graph" install_mod="550"/>
<path value="opp/built-in/op_graph/inc" install_mod="550"/>
<path value="opp/built-in/op_graph/lib" install_mod="550"/>
<path value="opp/built-in/op_graph/lib/linux" install_mod="550"/>
<path value="opp/built-in/op_graph/lib/linux/$(ARCH)" install_mod="550"/>
<path value="opp/built-in/op_impl" install_mod="550"/>
<path value="opp/built-in/op_impl/ai_core" install_mod="550"/>
<path value="opp/built-in/op_impl/ai_core/tbe" install_mod="550"/>
<path value="opp/built-in/op_impl/ai_core/tbe/op_host" install_mod="550"/>
<path value="opp/built-in/op_impl/ai_core/tbe/op_host/lib" install_mod="550"/>
<path value="opp/built-in/op_impl/ai_core/tbe/op_host/lib/linux" install_mod="550"/>
<path value="opp/built-in/op_impl/ai_core/tbe/op_host/lib/linux/$(ARCH)" install_mod="550"/>
<path value="opp/built-in/framework" install_mod="550"/>
<path value="opp/built-in/framework/onnx" install_mod="550"/>
</dir_info>
</config>

View File

@@ -0,0 +1,14 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
set -e
rm -rf $(pwd)

View File

@@ -0,0 +1,12 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
exit 0

View File

@@ -0,0 +1,36 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
# error number and description
if [ "$(id -u)" != "0" ]; then
_LOG_PATH=$(echo "${HOME}")"/var/log/ascend_seclog"
_INSTALL_LOG_FILE="${_LOG_PATH}/ascend_install.log"
else
_LOG_PATH="/var/log/ascend_seclog"
_INSTALL_LOG_FILE="${_LOG_PATH}/ascend_install.log"
fi
# log functions
getdate() {
_cur_date=$(date +"%Y-%m-%d %H:%M:%S")
echo "${_cur_date}"
}
logandprint() {
is_error_level=$(echo $1 | grep -E 'ERROR|WARN|INFO')
if [ "${is_quiet}" != "y" ] || [ "${is_error_level}" != "" ]; then
echo "[OpsTransformer] [$(getdate)] ""$1"
fi
echo "[OpsTransformer] [$(getdate)] ""$1" >>"${_INSTALL_LOG_FILE}"
}
logandprint "[INFO]: Opp package installed successfully! The new version takes effect immediately."
exit 0

View File

@@ -0,0 +1,10 @@
--full Install full mode
--install-path=<path> Install product to specific dir path
--install-for-all Install for all user
--quiet Quiet install mode, skip human-computer interactions
--uninstall Uninstall product with compatible run package which is installed before
--install-path=<path> Uninstall specific ops_transformer dir path
--upgrade Upgrade product immediately
--install-path=<path> Upgrade specific ops_transformer dir path
--install-for-all Install for all user
--quiet Quiet install mode, skip human-computer interactions

View File

@@ -0,0 +1,617 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
# error number and description
OPERATE_FAILED="0x0001"
PARAM_INVALID="0x0002"
FILE_NOT_EXIST="0x0080"
FILE_NOT_EXIST_DES="File not found."
OPP_COMPATIBILITY_CEHCK_ERR="0x0092"
OPP_COMPATIBILITY_CEHCK_ERR_DES="OppTransformer compatibility check error."
PERM_DENIED="0x0093"
PERM_DENIED_DES="Permission denied."
OPP_PLATFORM_DIR=ops_transformer
OPP_PLATFORM_UPPER=$(echo "${OPP_PLATFORM_DIR}" | tr '[:lower:]' '[:upper:]')
CURR_OPERATE_USER="$(id -nu 2>/dev/null)"
CURR_OPERATE_GROUP="$(id -ng 2>/dev/null)"
# defaults for general user
if [ "$(id -u)" != "0" ]; then
DEFAULT_INSTALL_PATH="${HOME}/Ascend"
else
IS_FOR_ALL="y"
DEFAULT_INSTALL_PATH="/usr/local/Ascend"
fi
# run package's files info, CURR_PATH means current temp path
CURR_PATH=$(dirname $(readlink -f $0))
INSTALL_SHELL_FILE="${CURR_PATH}/opp_install.sh"
RUN_PKG_INFO_FILE="${CURR_PATH}/../scene.info"
VERSION_INFO_FILE="${CURR_PATH}/../version.info"
COMMON_INC_FILE="${CURR_PATH}/common_func.inc"
VERCHECK_FILE="${CURR_PATH}/ver_check.sh"
VERSION_COMPAT_FUNC_PATH="${CURR_PATH}/version_compatiable.inc"
COMMON_FUNC_V2_PATH="${CURR_PATH}/common_func_v2.inc"
VERSION_CFG_PATH="${CURR_PATH}/version_cfg.inc"
OPP_COMMON_FILE="${CURR_PATH}/opp_common.sh"
. "${VERSION_COMPAT_FUNC_PATH}"
. "${COMMON_INC_FILE}"
. "${COMMON_FUNC_V2_PATH}"
. "${VERSION_CFG_PATH}"
. "${OPP_COMMON_FILE}"
ARCH_INFO=$(grep -e "arch" "$RUN_PKG_INFO_FILE" | cut --only-delimited -d"=" -f2-)
# 包内路径
GRAPH_SO_PATH="${CURR_PATH}/../../../../${OPP_PLATFORM_DIR}/built-in/op_graph/lib/linux/${ARCH_INFO}/libopgraph_transformer.so"
HOST_SO_PATH="${CURR_PATH}/../../../../${OPP_PLATFORM_DIR}/built-in/op_impl/ai_core/tbe/op_host/lib/linux/${ARCH_INFO}/libophost_transformer.so"
# defaults info determined by user's inputs
ASCEND_INSTALL_INFO="ascend_install.info"
TARGET_INSTALL_PATH="${DEFAULT_INSTALL_PATH}" #--input-path
TARGET_USERNAME="${CURR_OPERATE_USER}"
TARGET_USERGROUP="${CURR_OPERATE_GROUP}"
TARGET_VERSION_DIR="" # TARGET_INSTALL_PATH + PKG_VERSION_DIR
TARGET_SHARED_INFO_DIR=""
# keys of infos in ascend_install.info
KEY_INSTALLED_UNAME="USERNAME"
KEY_INSTALLED_UGROUP="USERGROUP"
KEY_INSTALLED_TYPE="${OPP_PLATFORM_UPPER}_INSTALL_TYPE"
KEY_INSTALLED_PATH="${OPP_PLATFORM_UPPER}_INSTALL_PATH_VAL"
KEY_INSTALLED_VERSION="${OPP_PLATFORM_UPPER}_VERSION"
KEY_INSTALLED_FEATURE="${OPP_PLATFORM_UPPER}_INSTALL_FEATURE"
KEY_INSTALLED_CHIP="${OPP_PLATFORM_UPPER}_INSTALL_CHIP"
# keys of infos in run package
KEY_RUNPKG_VERSION="Version"
# init install cmd status, set default as n
CMD_LIST="$*"
IS_UNINSTALL=n
IS_INSTALL=n
IS_UPGRADE=n
IS_QUIET=n
IS_INPUT_PATH=n
IS_CHECK=n
IN_INSTALL_TYPE=""
IN_INSTALL_PATH=""
IS_DOCKER_INSTALL=n
IS_SETENV=n
DOCKER_ROOT=""
CONFLICT_CMD_NUMS=0
IN_FEATURE="All"
# log functions
# start info before shell executing
startlog() {
echo "[OpsTransformer] [$(getdate)] [INFO]: Start Time: $(getdate)"
}
exitlog() {
echo "[OpsTransformer] [$(getdate)] [INFO]: End Time: $(getdate)"
}
#check ascend_install.info for the change in code warning
get_installed_info() {
local key="$1"
local res=""
if [ -f "${INSTALL_INFO_FILE}" ]; then
chmod 644 "${INSTALL_INFO_FILE}" >/dev/null 2>&1
res=$(cat ${INSTALL_INFO_FILE} | grep "${key}" | awk -F = '{print $2}')
fi
echo "${res}"
}
clean_before_reinstall() {
local installed_path=$(get_installed_info "${KEY_INSTALLED_PATH}")
local existed_files=$(find ${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR} -type f -print 2>/dev/null)
if [ -z "${existed_files}" ]; then
logandprint "[INFO]: Directory is empty, directly install opp module."
return 0
fi
if [ "${IS_QUIET}" = "y" ]; then
logandprint "[WARNING]: Directory has file existed or installed opp\
module, are you sure to keep installing opp module in it? y"
else
if [ ! -f "${INSTALL_INFO_FILE}" ]; then
logandprint "[INFO]: Directory has file existed, do you want to continue? [y/n]"
else
logandprint "[INFO]: Opp package has been installed on the path $(get_installed_info "${KEY_INSTALLED_PATH}"),\
the version is $(get_installed_info "${KEY_INSTALLED_VERSION}"),\
and the version of this package is ${RUN_PKG_VERSION}, do you want to continue? [y/n]"
fi
while true; do
read yn
if [ "$yn" = "n" ]; then
logandprint "[INFO]: Exit to install opp module."
exitlog
exit 0
elif [ "$yn" = "y" ]; then
break
else
echo "[WARNING]: Input error, please input y or n to choose!"
fi
done
fi
if [ "${installed_path}" = "${TARGET_VERSION_DIR}" ]; then
logandprint "[INFO]: Clean the installed opp module before install."
if [ ! -f "${UNINSTALL_SHELL_FILE}" ]; then
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST};ERR_DES:${FILE_NOT_EXIST_DES}.The file\
(${UNINSTALL_SHELL_FILE}) not exists. Please set the correct install \
path or clean the previous version opp install info (${INSTALL_INFO_FILE}) and then reinstall it."
return 1
fi
bash "${UNINSTALL_SHELL_FILE}" "${TARGET_VERSION_DIR}" "upgrade" "${IS_QUIET}" ${IN_FEATURE} "${IS_DOCKER_INSTALL}" "${DOCKER_ROOT}" "$pkg_version_dir"
if [ "$?" != 0 ]; then
logandprint "[ERROR]: ERR_NO:${INSTALL_FAILED};ERR_DES:Clean the installed directory failed."
return 1
fi
fi
return 0
}
select_last_dir_component() {
path="$1"
last_component=$(basename ${path})
if [ "${last_component}" = "atc" ]; then
last_component="atc"
return
elif [ "${last_component}" = "fwkacllib" ]; then
last_component="fwkacllib"
return
elif [ "${last_component}" = "compiler" ]; then
last_component="compiler"
return
fi
}
# check_version_file() {
# pkg_path="$1"
# component_ret="$2"
# run_pkg_path_temp=$(dirname "${pkg_path}")
# run_pkg_path_temp2=${run_pkg_path_temp%/*}
# run_pkg_path="${run_pkg_path_temp}""/${component_ret}"
# run_pkg_path_temp2=${run_pkg_path%/*}
# version_file="${run_pkg_path}""/version.info"
# version_file_tmp="${run_pkg_path_temp2}""/version.info"
# if [ -f "${version_file_tmp}" ]; then
# version_file=${version_file_tmp}
# fi
# if [ -f "${version_file}" ]; then
# echo "${version_file}" 2 >>/dev/null
# else
# logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST}; The [${component_ret}] version.info in path [${pkg_path}] not exists."
# exitlog
# exit 1
# fi
# return
# }
check_opp_version_file() {
if [ -f "${CURR_PATH}/../../version.info" ]; then
opp_ver_info="${CURR_PATH}/../../version.info"
elif [ -f "${DEFAULT_INSTALL_PATH}/${OPP_PLATFORM_DIR}/share/info/version.info" ]; then
opp_ver_info="${DEFAULT_INSTALL_PATH}/${OPP_PLATFORM_DIR}/share/info/version.info"
else
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST}; The [${OPP_PLATFORM_DIR}] version.info not exists."
exitlog
exit 1
fi
echo "find opp_ver_info: ${opp_ver_info}"
return
}
check_docker_path() {
docker_path="$1"
if [[ "${docker_path}" != /* ]]; then
echo "[OpsTransformer] [ERROR]: ERR_NO:${PARAM_INVALID};ERR_DES:Parameter --docker-root\
must with absolute path that which is start with root directory /. Such as --docker-root=/${docker_path}"
exitlog
exit 1
fi
if [ ! -d "${docker_path}" ]; then
echo "[OpsTransformer] [ERROR]: ERR_NO:${FILE_NOT_EXIST}; The directory:${docker_path} not exist, please create this directory."
exitlog
exit 1
fi
}
judgment_path() {
. "${COMMON_INC_FILE}"
check_install_path_valid "${1}"
if [ $? -ne 0 ]; then
echo "[OpsTransformer][ERROR]: The opp install path ${1} is invalid, only characters in [a-z,A-Z,0-9,-,_] are supported!"
exitlog
exit 1
fi
}
check_install_path() {
TARGET_INSTALL_PATH="$1"
# empty patch check
if [ "x${TARGET_INSTALL_PATH}" = "x" ]; then
echo "[OpsTransformer] [ERROR]: ERR_NO:${PARAM_INVALID};ERR_DES:Parameter --install-path\
not support that the install path is empty."
exitlog
exit 1
fi
# space check
if echo "x${TARGET_INSTALL_PATH}" | grep -q " "; then
echo "[OpsTransformer] [ERROR]: ERR_NO:${PARAM_INVALID};ERR_DES:Parameter --install-path\
not support that the install path contains space character."
exitlog
exit 1
fi
# delete last "/"
local temp_path="${TARGET_INSTALL_PATH}"
temp_path=$(echo "${temp_path%/}")
if [ x"${temp_path}" = "x" ]; then
temp_path="/"
fi
# convert relative path to absolute path
local prefix=$(echo "${temp_path}" | cut -d"/" -f1 | cut -d"~" -f1)
if [ "x${prefix}" = "x" ]; then
TARGET_INSTALL_PATH="${temp_path}"
else
prefix=$(echo "${RUN_PATH}" | cut -d"/" -f1 | cut -d"~" -f1)
if [ x"${prefix}" = "x" ]; then
TARGET_INSTALL_PATH="${RUN_PATH}/${temp_path}"
else
echo "[OpsTransformer] [ERROR]: ERR_NO:${PARAM_INVALID};ERR_DES: Run package path is invalid: $RUN_PATH"
exitlog
exit 1
fi
fi
# convert '~' to home path
local home=$(echo "${TARGET_INSTALL_PATH}" | cut -d"~" -f1)
if [ "x${home}" = "x" ]; then
local temp_path_value=$(echo "${TARGET_INSTALL_PATH}" | cut -d"~" -f2)
if [ "$(id -u)" -eq 0 ]; then
TARGET_INSTALL_PATH="/root$temp_path_value"
else
local home_path=$(eval echo "${USER}")
home_path=$(echo "${home_path}%/")
TARGET_INSTALL_PATH="$home_path$temp_path_value"
fi
fi
}
#get the dir of xxx.run
#opp_install_path_curr=`echo "$2" | cut -d"/" -f2- `
# cut first two params from *.run
get_run_path() {
RUN_PATH=$(echo "$2" | cut -d"-" -f3-)
if [ x"${RUN_PATH}" = x"" ]; then
RUN_PATH=$(pwd)
else
# delete last "/"
RUN_PATH=$(echo "${RUN_PATH%/}")
if [ "x${RUN_PATH}" = "x" ]; then
# root path
RUN_PATH=$(pwd)
fi
fi
}
get_opts() {
i=0
while true
do
if [ "x$1" = "x" ]; then
break
fi
if [ "$(expr substr "$1" 1 2)" = "--" ]; then
i=$(expr $i + 1)
fi
if [ $i -gt 2 ]; then
break
fi
shift 1
done
if [ "$*" = "" ]; then
echo "[ERROR]: ERR_NO:${PARAM_INVALID}; ERR_DES:Unrecognized parameters.Try './xxx.run --help for more information.'"
exitlog
exit 1
fi
while true; do
# skip 2 parameters avoid run pkg and directory as input parameter
case "$1" in
--full)
IN_INSTALL_TYPE=$(echo ${1} | awk -F"--" '{print $2}')
IS_INSTALL="y"
CONFLICT_CMD_NUMS=$(expr $CONFLICT_CMD_NUMS + 1)
shift
;;
--upgrade)
IS_UPGRADE="y"
CONFLICT_CMD_NUMS=$(expr $CONFLICT_CMD_NUMS + 1)
shift
;;
--uninstall)
IS_UNINSTALL="y"
CONFLICT_CMD_NUMS=$(expr $CONFLICT_CMD_NUMS + 1)
shift
;;
--install-path=*)
IS_INPUT_PATH="y"
IN_INSTALL_PATH=$(echo ${1} | cut -d"=" -f2-)
# check path
judgment_path "${IN_INSTALL_PATH}"
check_install_path "${IN_INSTALL_PATH}"
shift
;;
--quiet)
IS_QUIET="y"
shift
;;
--install-for-all)
IS_FOR_ALL="y"
shift
;;
-*)
echo "[OpsTransformer] [ERROR]: ERR_NO:${PARAM_INVALID};ERR_DES:Unsupported parameters [$1],\
operation execute failed. Please use [--help] to see the usage."
exitlog
exit 1
;;
*)
break
;;
esac
done
}
# pre-check
check_opts() {
if [ "${CONFLICT_CMD_NUMS}" != 1 ]; then
echo "[OpsTransformer] [ERROR]: ERR_NO:${PARAM_INVALID};ERR_DES:\
only support one type: full/run/devel/upgrade/uninstall/check, operation execute failed!\
Please use [--help] to see the usage."
exitlog
exit 1
fi
}
# init target_dir and log for install
init_env() {
# create log folder and log file
comm_init_log
if is_version_dirpath "$TARGET_INSTALL_PATH"; then
pkg_version_dir="$(basename "$TARGET_INSTALL_PATH")"
TARGET_INSTALL_PATH="$(dirname "$TARGET_INSTALL_PATH")"
else
pkg_version_dir="cann"
fi
TARGET_VERSION_DIR="$TARGET_INSTALL_PATH/$pkg_version_dir" # Splicing docker-root and install-path
if [ "${IS_DOCKER_INSTALL}" = "y" ]; then
# delete last "/"
local temp_path_param="${DOCKER_ROOT}"
local temp_path_val=$(echo "${temp_path_param%/}")
if [ "x${temp_path_val}" = "x" ]; then
temp_path_val="/"
fi
TARGET_VERSION_DIR=${temp_path_val}${TARGET_VERSION_DIR}
fi
TARGET_SHARED_INFO_DIR=${TARGET_VERSION_DIR}/share/info
UNINSTALL_SHELL_FILE="${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/script/opp_uninstall.sh"
INSTALL_INFO_FILE="${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/${ASCEND_INSTALL_INFO}"
logandprint "[INFO]: Execute the opp run package."
logandprint "[INFO]: OperationLogFile path: ${COMM_LOGFILE}."
logandprint "[INFO]: Input params: $CMD_LIST"
get_package_version "RUN_PKG_VERSION" "$VERSION_INFO_FILE"
local installed_version=$(get_installed_info "${KEY_INSTALLED_VERSION}")
if [ "${installed_version}" = "" ]; then
logandprint "[INFO]: Version of installing opp module is ${RUN_PKG_VERSION}."
else
if [ "${RUN_PKG_VERSION}" != "" ]; then
logandprint "[INFO]: Existed opp module version is ${installed_version},\
the new opp module version is ${RUN_PKG_VERSION}."
fi
fi
}
check_pre_install() {
local installed_user=$(get_installed_info "${KEY_INSTALLED_UNAME}")
local installed_group=$(get_installed_info "${KEY_INSTALLED_UGROUP}")
if [ "${installed_user}" != "" ] || [ "${installed_group}" != "" ]; then
if [ "${installed_user}" != "${TARGET_USERNAME}" ] || [ "${installed_group}" != "${TARGET_USERGROUP}" ]; then
logandprint "[ERROR]: The user and group are not same with last installation,\
do not support overwriting installation!"
exitlog
exit 1
fi
fi
if [ "${IS_UPGRADE}" = "y" ]; then
if [ ! -e "${INSTALL_INFO_FILE}" ]; then
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST}; The directory:${TARGET_INSTALL_PATH} not install OpsTransformer, upgrade failed."
exitlog
exit 1
fi
IN_INSTALL_TYPE=$(get_installed_info "${KEY_INSTALLED_TYPE}")
fi
}
#Support the installation script when the specified path (relative path and absolute path) does not exist
mkdir_install_path() {
local base_dir=$(dirname ${TARGET_INSTALL_PATH})
if [ ! -d ${base_dir} ]; then
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST}; The directory:${base_dir} not exist, please create this directory."
exitlog
exit 1
fi
if [ -d "${TARGET_INSTALL_PATH}" ]; then
test -w ${TARGET_INSTALL_PATH} >>/dev/null 2>&1
if [ "$?" -ne 0 ]; then
#All paths exist with write permission
logandprint "[ERROR]: ERR_NO:${PERM_DENIED};ERR_DES:${PERM_DENIED_DES}. The ${TARGET_USERNAME} do\
access ${TARGET_INSTALL_PATH} failed, please reset the directory to a right permission."
exit 1
fi
else
test -w ${base_dir} >>/dev/null 2>&1
if [ "$?" -ne 0 ]; then
#All paths exist with write permission
logandprint "[ERROR]: ERR_NO:${PERM_DENIED};ERR_DES:${PERM_DENIED_DES}. The ${TARGET_USERNAME} do\
access ${base_dir} failed, please reset the directory to a right permission."
exit 1
else
comm_create_dir "${TARGET_INSTALL_PATH}" "750" "${TARGET_USERNAME}:${TARGET_USERGROUP}" "${IS_FOR_ALL}"
fi
fi
}
install_package() {
if [ "${IS_INSTALL}" = "n" ] && [ "${IS_UPGRADE}" = "n" ]; then
return
fi
local architecture=$(uname -m)
local graph_so_dir_path="${TARGET_VERSION_DIR}/opp/built-in/op_graph/lib/linux/${ARCH_INFO}"
local host_so_dir_path="${TARGET_VERSION_DIR}/opp/built-in/op_impl/ai_core/tbe/op_host/lib/linux/${ARCH_INFO}"
# check platform
if [ "${architecture}" != "${ARCH_INFO}" ] ; then
logandprint "[INFO]: the architecture of the run package is inconsistent with that of the current environment. "
# 异构安装场景拷贝so到指定目录
if [ -d "${TARGET_VERSION_DIR}/opp/built-in/op_graph/lib/linux" ] ; then
chmod u+w ${TARGET_VERSION_DIR}/opp/built-in/op_graph/lib/linux
fi
if [ -d "${TARGET_VERSION_DIR}/opp/built-in/op_impl/ai_core/tbe/op_host/lib/linux" ] ; then
chmod u+w ${TARGET_VERSION_DIR}/opp/built-in/op_impl/ai_core/tbe/op_host/lib/linux
fi
mkdir -p ${graph_so_dir_path}
mkdir -p ${host_so_dir_path}
cp ${GRAPH_SO_PATH} ${graph_so_dir_path}
cp ${HOST_SO_PATH} ${host_so_dir_path}
chmod 755 ${graph_so_dir_path}/*
chmod 755 ${host_so_dir_path}/*
chmod u-w ${TARGET_VERSION_DIR}/opp/built-in/op_graph/lib/linux
chmod u-w ${TARGET_VERSION_DIR}/opp/built-in/op_impl/ai_core/tbe/op_host/lib/linux
exit 0
fi
# use uninstall to clean the install folder
clean_before_reinstall
if [ "$?" != 0 ]; then
comm_log_operation "Install" "${IN_INSTALL_TYPE}" "OpsTransformer" "$?" "${CMD_LIST}"
fi
bash "${INSTALL_SHELL_FILE}" "${TARGET_INSTALL_PATH}" "${TARGET_USERNAME}" "${TARGET_USERGROUP}" "${IN_FEATURE}" \
"${IN_INSTALL_TYPE}" "${IS_FOR_ALL}" "${IS_SETENV}" "${IS_DOCKER_INSTALL}" "${DOCKER_ROOT}" "$pkg_version_dir"
if [ "$?" != 0 ]; then
comm_log_operation "Install" "${IN_INSTALL_TYPE}" "OpsTransformer" "$?" "${CMD_LIST}"
fi
if [ $(id -u) -eq 0 ]; then
chown -R "root":"root" "${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/script" 2>/dev/null
chown "root":"root" "${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}" 2>/dev/null
chmod -R 555 "${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/script" 2>/dev/null
chmod 444 "${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/script/filelist.csv" 2>/dev/null
else
chmod -R 550 "${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/script" 2>/dev/null
chmod 440 "${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/script/filelist.csv" 2>/dev/null
fi
comm_log_operation "Install" "${IN_INSTALL_TYPE}" "OpsTransformer" "$?" "${CMD_LIST}"
}
uninstall_package() {
if [ "${IS_UNINSTALL}" = "n" ]; then
return
fi
if [ ! -f "${UNINSTALL_SHELL_FILE}" ]; then
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST};ERR_DES:The file\
(${UNINSTALL_SHELL_FILE}) not exists. Please make sure that the opp module\
installed in (${TARGET_VERSION_DIR}) and then set the correct install path."
uninstall_path=$(ls "${TARGET_INSTALL_PATH}" 2>/dev/null)
if [ "${uninstall_path}" = "" ]; then
rm -rf "${TARGET_INSTALL_PATH}"
fi
comm_log_operation "Uninstall" "${IN_INSTALL_TYPE}" "OpsTransformer" "$?" "${CMD_LIST}"
exit 0
fi
# 如果是异构卸载
local architecture=$(uname -m)
if [ "${architecture}" != ${ARCH_INFO} ]; then
target_arch=${ARCH_INFO}
else
# 判断异构so是否存在存在则删除
if [ "${architecture}" = "x86_64" ]; then
target_arch="aarch64"
else
target_arch="x86_64"
fi
fi
local graph_so_path="${TARGET_VERSION_DIR}/opp/built-in/op_graph/lib/linux/${target_arch}/libopgraph_transformer.so"
local graph_so_dir_path="${TARGET_VERSION_DIR}/opp/built-in/op_graph/lib/linux/${target_arch}"
local host_so_path="${TARGET_VERSION_DIR}/opp/built-in/op_impl/ai_core/tbe/op_host/lib/linux/${target_arch}/libophost_transformer.so"
local host_so_dir_path="${TARGET_VERSION_DIR}/opp/built-in/op_impl/ai_core/tbe/op_host/lib/linux/${target_arch}"
if [ -f "${graph_so_path}" ]; then
rm -f "${graph_so_path}"
fi
if [ -f "${host_so_path}" ]; then
rm -f "${host_so_path}"
fi
# 判断目录是否存在且是否为空
if [ -d "${graph_so_dir_path}" ]; then
if [ -z "$(ls -A "${graph_so_dir_path}")" ]; then
rm -rf "${graph_so_dir_path}"
fi
fi
if [ -d "${host_so_dir_path}" ]; then
if [ -z "$(ls -A "${host_so_dir_path}")" ]; then
rm -rf "${host_so_dir_path}"
fi
fi
if [ "${architecture}" != ${ARCH_INFO} ]; then
return
fi
bash "${UNINSTALL_SHELL_FILE}" "${TARGET_INSTALL_PATH}" "uninstall" "${IS_QUIET}" ${IN_FEATURE} "${IS_DOCKER_INSTALL}" "${DOCKER_ROOT}" "$pkg_version_dir"
logandprint "[INFO]: Remove precheck info."
comm_log_operation "Uninstall" "${IN_INSTALL_TYPE}" "OpsTransformer" "$?" "${CMD_LIST}"
}
main() {
get_run_path "$@"
startlog
get_opts "$@"
check_opts
init_env
check_pre_install
mkdir_install_path
install_package
uninstall_package
}
main "$@"
exit 0

View File

@@ -0,0 +1,271 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
if [ "$(id -u)" != "0" ]; then
_LOG_PATH=$(echo "${HOME}")"/var/log/ascend_seclog"
_INSTALL_LOG_FILE="${_LOG_PATH}/ascend_install.log"
else
_LOG_PATH="/var/log/ascend_seclog"
_INSTALL_LOG_FILE="${_LOG_PATH}/ascend_install.log"
fi
# log functions
getdate() {
_cur_date=$(date +"%Y-%m-%d %H:%M:%S")
echo "${_cur_date}"
}
logandprint() {
is_error_level=$(echo $1 | grep -E 'ERROR|WARN|INFO')
if [ "${is_quiet}" != "y" ] || [ "${is_error_level}" != "" ]; then
echo "[OpsTransformer] [$(getdate)] ""$1"
fi
echo "[OpsTransformer] [$(getdate)] ""$1" >>"${_INSTALL_LOG_FILE}"
}
# create opapi soft link
createrelativelysoftlink() {
local src_path_="$1"
local dst_path_="$2"
local dst_parent_path_=$(dirname ${dst_path_})
# echo "dst_parent_path_: ${dst_parent_path_}"
local relative_path_=$(realpath --relative-to="$dst_parent_path_" "$src_path_")
# echo "relative_path_: ${relative_path_}"
if [ -L "$2" ]; then
return 0
fi
ln -s "${relative_path_}" "${dst_path_}" 2>/dev/null
if [ "$?" != "0" ]; then
return 1
else
return 0
fi
}
createOpapiLatestSoftlink() {
targetPkg=$2
if [ "${targetPkg}x" = "x" ]; then
#CHANGED
targetPkg=ops_transformer
fi
osName=""
if [ -f "$1/$targetPkg/scene.info" ]; then
. $1/$targetPkg/scene.info
osName=${os}
fi
opapi_lib_path="$1/opp/built-in/op_impl/ai_core/tbe/op_api/lib/${osName}/${architecture}"
opapi_include_level1_path="$1/opp/built-in/op_impl/ai_core/tbe/op_api/include/aclnnop"
opapi_include_level2_path="${opapi_include_level1_path}/level2"
if [ ! -d ${opapi_lib_path} ] || [ ! -d ${opapi_include_level1_path} ] || [ ! -d ${opapi_include_level2_path} ]; then
return 3
fi
if [ -d $(dirname $1)/latest/${architectureDir}/lib64 ]; then
for file_so in $(ls -1 $1/${architectureDir}/lib64 | grep -E "libaclnn_|libopapi.so"); do
latest_arch_lib64_src_path="$1/${architectureDir}/lib64/${file_so}"
latest_arch_lib64_dst_path="$(dirname $1)/latest/${architectureDir}/lib64/${file_so}"
if [ -f $latest_arch_lib64_dst_path ] || [ -L $latest_arch_lib64_dst_path ]; then
rm -fr "$latest_arch_lib64_dst_path"
fi
createrelativelysoftlink ${latest_arch_lib64_src_path} ${latest_arch_lib64_dst_path}
done
fi
# second the headfiles with 1 and 2 level
if [ -d $1/${architectureDir}/include/aclnnop ]; then
for file_level1 in $(ls -1 -F ${opapi_include_level1_path} | grep -v [/$] | sed 's/\*$//'); do
latest_arch_include_src_path="${opapi_include_level1_path}/${file_level1}"
latest_arch_include_dst_path="$(dirname $1)/latest/${architectureDir}/include/aclnnop/${file_level1}"
if [ -f $latest_arch_include_dst_path ] || [ -L $latest_arch_include_dst_path ]; then
rm -fr "$latest_arch_include_dst_path"
fi
createrelativelysoftlink ${latest_arch_include_src_path} ${latest_arch_include_dst_path}
done
fi
if [ -d $1/${architectureDir}/include/aclnnop/level2 ]; then
for file_level2 in $(ls -1 -F ${opapi_include_level2_path} | grep -v [/$] | sed 's/\*$//'); do
latest_arch_include_src_path="${opapi_include_level2_path}/${file_level2}"
latest_arch_include_dst_path="$(dirname $1)/latest/${architectureDir}/include/aclnnop/level2/${file_level2}"
if [ -f $latest_arch_include_dst_path ] || [ -L $latest_arch_include_dst_path ]; then
rm -fr "$latest_arch_include_dst_path"
fi
createrelativelysoftlink ${latest_arch_include_src_path} ${latest_arch_include_dst_path}
done
fi
}
createOpapiSoftlink() {
osName=""
if [ -f "$1/opp/scene.info" ]; then
. $1/opp/scene.info
osName=${os}
fi
opapi_lib_path="$1/opp/built-in/op_impl/ai_core/tbe/op_api/lib/${osName}/${architecture}"
opapi_include_level1_path="$1/opp/built-in/op_impl/ai_core/tbe/op_api/include/aclnnop"
opapi_include_level2_path="${opapi_include_level1_path}/level2"
if [ ! -d ${opapi_lib_path} ] || [ ! -d ${opapi_include_level1_path} ] || [ ! -d ${opapi_include_level2_path} ]; then
return 3
fi
# first the libopapi.so
if [ -d $1/${architectureDir}/lib64 ]; then
for file_so in $(ls -1 ${opapi_lib_path} | grep "so"$); do
arch_lib64_src_path="${opapi_lib_path}/${file_so}"
arch_lib64_dst_path="$1/${architectureDir}/lib64/${file_so}"
if [ -f $arch_lib64_dst_path ] || [ -L $arch_lib64_dst_path ]; then
rm -fr "$arch_lib64_dst_path"
fi
createrelativelysoftlink ${arch_lib64_src_path} ${arch_lib64_dst_path}
done
fi
if [ -d $1/opp/lib64 ]; then
for file_so in $(ls -1 $1/${architectureDir}/lib64 | grep -E "libaclnn_|libopapi.so"); do
opp_lib64_src_path="$1/${architectureDir}/lib64/${file_so}"
opp_lib64_dst_path="$1/opp/lib64/${file_so}"
if [ -f $opp_lib64_dst_path ] || [ -L $opp_lib64_dst_path ]; then
rm -fr "$opp_lib64_dst_path"
fi
createrelativelysoftlink ${opp_lib64_src_path} ${opp_lib64_dst_path}
done
fi
# second the headfiles with 1 and 2 level
if [ -d $1/${architectureDir}/include/aclnnop ]; then
for file_level1 in $(ls -1 -F ${opapi_include_level1_path} | grep -v [/$] | sed 's/\*$//'); do
arch_include_src_path="${opapi_include_level1_path}/${file_level1}"
arch_include_dst_path="$1/${architectureDir}/include/aclnnop/${file_level1}"
if [ -f $arch_include_dst_path ] || [ -L $arch_include_dst_path ]; then
rm -fr "$arch_include_dst_path"
fi
createrelativelysoftlink ${arch_include_src_path} ${arch_include_dst_path}
opp_include_src_path="${arch_include_dst_path}"
opp_include_dst_path="$1/opp/include/aclnnop/${file_level1}"
if [ -f $opp_include_dst_path ] || [ -L $opp_include_dst_path ]; then
rm -fr "$opp_include_dst_path"
fi
createrelativelysoftlink ${opp_include_src_path} ${opp_include_dst_path}
done
fi
if [ -d $1/${architectureDir}/include/aclnnop/level2 ]; then
for file_level2 in $(ls -1 -F ${opapi_include_level2_path} | grep -v [/$] | sed 's/\*$//'); do
arch_include_src_path="${opapi_include_level2_path}/${file_level2}"
arch_include_dst_path="$1/${architectureDir}/include/aclnnop/level2/${file_level2}"
if [ -f $arch_include_dst_path ] || [ -L $arch_include_dst_path ]; then
rm -fr "$arch_include_dst_path"
fi
createrelativelysoftlink ${arch_include_src_path} ${arch_include_dst_path}
opp_include_src_path="${arch_include_dst_path}"
opp_include_dst_path="$1/opp/include/aclnnop/level2/${file_level2}"
if [ -f $opp_include_dst_path ] || [ -L $opp_include_dst_path ]; then
rm -fr "$opp_include_dst_path"
fi
createrelativelysoftlink ${opp_include_src_path} ${opp_include_dst_path}
done
fi
}
# remove opapi soft link
removeopapisoftlink() {
local path="$1"
if [ -L "$1" ]; then
rm -fr ${path}
return 0
else
return 1
fi
}
latestSoftlinksRemove() {
targetdir=$1
osName=""
if [ -f "$targetdir/opp/scene.info" ]; then
. $targetdir/opp/scene.info
osName=${os}
fi
opapi_lib_path="$targetdir/opp/built-in/op_impl/ai_core/tbe/op_api/lib/${osName}/${architecture}"
opapi_include_level1_path="$1/opp/built-in/op_impl/ai_core/tbe/op_api/include/aclnnop"
opapi_include_level2_path="${opapi_include_level1_path}/level2"
if [ -d $(dirname $targetdir)/latest/${architectureDir}/lib64 ]; then
for file_so in $(ls -l "$(dirname $targetdir)/latest/${architectureDir}/lib64/" | grep -E "libaclnn_|libopapi.so"); do
latest_arch_lib64_path="$(dirname $targetdir)/latest/${architectureDir}/lib64/${file_so}"
removeopapisoftlink ${latest_arch_lib64_path}
done
fi
# second the headfiles with 1 and 2 level
if [ -d $(dirname $targetdir)/latest/${architectureDir}/include/aclnnop ]; then
for file_level1 in $(ls -1 -F ${opapi_include_level1_path} | grep -v [/$] | sed 's/\*$//'); do
latest_arch_include_path="$(dirname $targetdir)/latest/${architectureDir}/include/aclnnop/${file_level1}"
removeopapisoftlink ${latest_arch_include_path}
done
fi
if [ -d $(dirname $targetdir)/latest/${architectureDir}/include/aclnnop/level2 ]; then
for file_level2 in $(ls -1 -F ${opapi_include_level2_path} | grep -v [/$] | sed 's/\*$//'); do
latest_arch_include_path="$(dirname $targetdir)/latest/${architectureDir}/include/aclnnop/level2/${file_level2}"
removeopapisoftlink ${latest_arch_include_path}
done
fi
}
softlinksRemove() {
targetdir=$1
osName=""
if [ -f "$targetdir/opp/scene.info" ]; then
. $targetdir/opp/scene.info
osName=${os}
fi
opapi_lib_path="$targetdir/opp/built-in/op_impl/ai_core/tbe/op_api/lib/${osName}/${architecture}"
opapi_include_level1_path="$targetdir/opp/built-in/op_impl/ai_core/tbe/op_api/include/aclnnop"
opapi_include_level2_path="${opapi_include_level1_path}/level2"
# first the libopapi.so
if [ -d $targetdir/${architectureDir}/lib64 ]; then
for file_so in $(ls -1 $targetdir/${architectureDir}/lib64 | grep -E "libaclnn_|libopapi.so"); do
arch_lib64_path="$targetdir/${architectureDir}/lib64/${file_so}"
removeopapisoftlink ${arch_lib64_path}
done
fi
if [ -d $targetdir/opp/lib64 ]; then
for file_so in $(ls -l $targetdir/opp/lib64 | grep -E "libaclnn_|libopapi.so"); do
opp_lib64_path="$targetdir/opp/lib64/${file_so}"
removeopapisoftlink ${opp_lib64_path}
done
fi
# second the headfiles with 1 and 2 level
if [ -d $targetdir/${architectureDir}/include/aclnnop ]; then
for file_level1 in $(ls -1 -F ${opapi_include_level1_path} | grep -v [/$] | sed 's/\*$//'); do
arch_include_path="$targetdir/${architectureDir}/include/aclnnop/${file_level1}"
removeopapisoftlink ${arch_include_path}
opp_include_path="$targetdir/opp/include/aclnnop/${file_level1}"
removeopapisoftlink ${opp_include_path}
done
fi
if [ -d $targetdir/${architectureDir}/include/aclnnop/level2 ]; then
for file_level2 in $(ls -1 -F ${opapi_include_level2_path} | grep -v [/$] | sed 's/\*$//'); do
arch_include_path="$targetdir/${architectureDir}/include/aclnnop/level2/${file_level2}"
removeopapisoftlink ${arch_include_path}
opp_include_path="$targetdir/opp/include/aclnnop/level2/${file_level2}"
removeopapisoftlink ${opp_include_path}
done
fi
}

View File

@@ -0,0 +1,58 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
curpath=$(dirname $(readlink -f "$0"))
SCENE_FILE="${curpath}""/../scene.info"
OPP_COMMON="${curpath}""/opp_common.sh"
common_func_path="${curpath}/common_func.inc"
. "${OPP_COMMON}"
. "${common_func_path}"
# init arch
architecture=$(uname -m)
architectureDir="${architecture}-linux"
while true; do
case "$1" in
--install-path=*)
install_path=$(echo "$1" | cut -d"=" -f2-)
shift
;;
--version-dir=*)
version_dir=$(echo "$1" | cut -d"=" -f2)
shift
;;
--latest-dir=*)
latest_dir=$(echo "$1" | cut -d"=" -f2)
shift
;;
-*)
shift
;;
*)
break
;;
esac
done
get_version_dir "opp_kernel_version_dir" "$install_path/$version_dir/opp_kernel/version.info"
if [ -z "$opp_kernel_version_dir" ]; then
# create op_api soft link
logandprint "[INFO]: Start create opapi softlinks."
createOpapiSoftlink "${install_path}/${version_dir}"
return_code=$?
if [ ${return_code} -eq 0 ]; then
logandprint "[INFO]: Create opapi softlinks successfully!"
elif [ ${return_code} -eq 3 ]; then
logandprint "[WARNING]: opapi source file does not exist!"
else
logandprint "[ERROR]: Create opapi softlinks failed!"
fi
fi

View File

@@ -0,0 +1,55 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
curpath=$(dirname $(readlink -f "$0"))
SCENE_FILE="${curpath}""/../scene.info"
OPP_COMMON="${curpath}""/opp_common.sh"
common_func_path="${curpath}/common_func.inc"
. "${OPP_COMMON}"
. "${common_func_path}"
# init arch
architecture=$(uname -m)
architectureDir="${architecture}-linux"
while true; do
case "$1" in
--install-path=*)
install_path=$(echo "$1" | cut -d"=" -f2-)
shift
;;
--version-dir=*)
version_dir=$(echo "$1" | cut -d"=" -f2)
shift
;;
--latest-dir=*)
latest_dir=$(echo "$1" | cut -d"=" -f2)
shift
;;
-*)
shift
;;
*)
break
;;
esac
done
get_version_dir "opp_kernel_version_dir" "$install_path/$version_dir/opp_kernel/version.info"
if [ -z "$opp_kernel_version_dir" ]; then
# before remove the oppkernel, remove the softlinks
logandprint "[INFO]: Start remove opapi softlinks."
softlinksRemove ${install_path}/${version_dir}
if [ $? -ne 0 ]; then
logandprint "[WARNING]: Remove opapi softlinks failed, some softlinks may not exist."
else
logandprint "[INFO]: Remove opapi softlinks successfully."
fi
fi

View File

@@ -0,0 +1,414 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
PARAM_INVALID="0x0002"
INSTALL_FAILED="0x0000"
INSTALL_FAILED_DES="Update successfully."
FILE_NOT_EXIST="0x0080"
FILE_NOT_EXIST_DES="File not found."
FILE_READ_FAILED="0x0082"
FILE_READ_FAILED_DES="File read failed."
FILE_WRITE_FAILED="0x0081"
FILE_WRITE_FAILED_DES="File write failed."
PERM_DENIED="0x0093"
PERM_DENIED_DES="Permission denied."
# run package's files info
CURR_PATH=$(dirname $(readlink -f $0))
VERSION_INFO_FILE="${CURR_PATH}/../version.info"
FILELIST_FILE="${CURR_PATH}/filelist.csv"
COMMON_PARSER_FILE="${CURR_PATH}/install_common_parser.sh"
SCENE_FILE="${CURR_PATH}/../scene.info"
ASCEND_INSTALL_INFO="ascend_install.info"
ARCH_INFO=$(uname -m)
OPP_PLATFORM_DIR=ops_transformer
OPP_PLATFORM_UPPER=$(echo "${OPP_PLATFORM_DIR}" | tr '[:lower:]' '[:upper:]')
TARGET_INSTALL_PATH=""
TARGET_MOULDE_DIR="" # TARGET_INSTALL_PATH + PKG_VERSION_DIR + OPP_PLATFORM_DIR
TARGET_VERSION_DIR="" # TARGET_INSTALL_PATH + PKG_VERSION_DIR
TARGET_SHARED_INFO_DIR="" # TARGET_INSTALL_PATH + PKG_VERSION_DIR + share/info
TARGET_OPP_BUILT_IN=""
COMMON_INC_FILE="${CURR_PATH}/common_func.inc"
COMMON_FUNC_V2_PATH="${CURR_PATH}/common_func_v2.inc"
VERSION_CFG="${CURR_PATH}/version_cfg.inc"
OPP_COMMON_FILE="${CURR_PATH}/opp_common.sh"
. "${COMMON_INC_FILE}"
. "${COMMON_FUNC_V2_PATH}"
. "${VERSION_CFG}"
. "${OPP_COMMON_FILE}"
# keys of infos in ascend_install.info
KEY_INSTALLED_UNAME="USERNAME"
KEY_INSTALLED_UGROUP="USERGROUP"
KEY_INSTALLED_TYPE="${OPP_PLATFORM_UPPER}_INSTALL_TYPE"
KEY_INSTALLED_FEATURE="${OPP_PLATFORM_UPPER}_INSTALL_FEATURE"
KEY_INSTALLED_CHIP="${OPP_PLATFORM_UPPER}_INSTALL_CHIP"
KEY_INSTALLED_PATH="${OPP_PLATFORM_UPPER}_INSTALL_PATH_VAL"
KEY_INSTALLED_VERSION="${OPP_PLATFORM_UPPER}_VERSION"
get_opts() {
TARGET_INSTALL_PATH="$1"
TARGET_USERNAME="$2"
TARGET_USERGROUP="$3"
IN_FEATURE="$4"
INSTALL_TYPE="$5"
IS_FOR_ALL="$6"
IS_SETENV="$7"
IS_DOCKER_INSTALL="$8"
DOCKER_ROOT="$9"
PKG_VERSION_DIR="${10}"
if [ "${TARGET_INSTALL_PATH}" = "" ] || [ "${TARGET_USERNAME}" = "" ] ||
[ "${TARGET_USERGROUP}" = "" ] || [ "${INSTALL_TYPE}" = "" ]; then
logandprint "[ERROR]: ERR_NO:${PARAM_INVALID};ERR_DES:Empty parameters is invalid for install."
exit 1
fi
INSTALL_FOR_ALL=""
if [ "${IS_FOR_ALL}" = "y" ]; then
INSTALL_FOR_ALL="--install_for_all"
fi
}
init_install_env() {
get_package_version "RUN_PKG_VERSION" "$VERSION_INFO_FILE"
if [ "${PKG_VERSION_DIR}" = "" ]; then
TARGET_VERSION_DIR=${TARGET_INSTALL_PATH}
else
TARGET_VERSION_DIR=${TARGET_INSTALL_PATH}/${PKG_VERSION_DIR}
fi
TARGET_MOULDE_DIR=${TARGET_VERSION_DIR}/${OPP_PLATFORM_DIR}
TARGET_OPP_BUILT_IN=${TARGET_VERSION_DIR}/opp/built-in
TARGET_SHARED_INFO_DIR=${TARGET_VERSION_DIR}/share/info
INSTALL_INFO_FILE=${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/${ASCEND_INSTALL_INFO}
if [ "$(id -u)" != "0" ]; then
LOG_PATH_PERM="740"
LOG_FILE_PERM="640"
INSTALL_INFO_PERM="600"
else
LOG_PATH_PERM="750"
LOG_FILE_PERM="640"
INSTALL_INFO_PERM="644"
fi
if [ "${IS_FOR_ALL}" = "y" ]; then
BUILTIN_PERM="555"
CUSTOM_PERM="755"
CREATE_DIR_PERM="755"
ONLYREAD_PERM="444"
else
BUILTIN_PERM="550"
CUSTOM_PERM="750"
CREATE_DIR_PERM="750"
ONLYREAD_PERM="440"
fi
}
log_with_errorlevel() {
local ret_status="$1"
local level="$2"
local msg="$3"
if [ "${ret_status}" != 0 ]; then
if [ "${level}" = "error" ]; then
logandprint "${msg}"
exit 1
else
logandprint "${msg}"
fi
fi
}
get_installed_info() {
local key="$1"
local res=""
if [ -f "${INSTALL_INFO_FILE}" ]; then
res=$(cat ${INSTALL_INFO_FILE} | grep "${key}" | awk -F = '{print $2}')
fi
echo "${res}"
}
update_install_info() {
local key_val="$1"
local val="$2"
local old_val=$(get_installed_info "${key_val}")
if [ -f "${INSTALL_INFO_FILE}" ]; then
if [ "x${old_val}" = "x" ]; then
echo "${key_val}=${val}" >>"${INSTALL_INFO_FILE}"
else
sed -i "/${key_val}/c ${key_val}=${val}" "${INSTALL_INFO_FILE}"
fi
else
echo "${key_val}=${val}" >"${INSTALL_INFO_FILE}"
fi
}
update_install_infos() {
local uname="$1"
local ugroup="$2"
local type="$3"
local path="$4"
local version
get_package_version "version" "$VERSION_INFO_FILE"
comm_create_file "${INSTALL_INFO_FILE}" "${INSTALL_INFO_PERM}" "${TARGET_USERNAME}:${TARGET_USERGROUP}" "${IS_FOR_ALL}"
update_install_info "${KEY_INSTALLED_UNAME}" "${uname}"
update_install_info "${KEY_INSTALLED_UGROUP}" "${ugroup}"
update_install_info "${KEY_INSTALLED_TYPE}" "${type}"
update_install_info "${KEY_INSTALLED_PATH}" "${path}"
update_install_info "${KEY_INSTALLED_VERSION}" "${version}"
}
check_file_exist() {
local path_param="${1}"
if [ ! -f "${path_param}" ]; then
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST};ERR_DES:The file (${path_param}) does not existed."
exit 1
fi
}
check_env() {
check_file_exist "${FILELIST_FILE}"
check_file_exist "${COMMON_PARSER_FILE}"
}
createsoftlink() {
local src_path="$1"
local dst_path="$2"
if [ -e "$dst_path" ]; then
if [ -L "$dst_path" ]; then
`rm -f $dst_path`
else
return 0
fi
fi
ln -s "${src_path}" "${dst_path}" 2>/dev/null
log_with_errorlevel "$?" "error" "[ERROR]: ERR_NO:${PERM_DENIED};ERR_DES:${src_path} Create softlink to ${dst_path} failed."
}
get_install_path() {
docker_root_tmp="$(echo "${DOCKER_ROOT}" | sed "s#/\+\$##g")"
docker_root_regex="$(echo "${docker_root_tmp}" | sed "s#\/#\\\/#g")"
relative_path_val=$(echo "${TARGET_VERSION_DIR}" | sed "s/^${docker_root_regex}//g" | sed "s/\/\+\$//g")
return
}
setenv() {
logandprint "[INFO]: Set the environment path [ export ASCEND_OPP_PATH=${relative_path_val}/opp ]."
if [ "${IS_DOCKER_INSTALL}" = y ]; then
INSTALL_OPTION="--docker-root=${DOCKER_ROOT}"
else
INSTALL_OPTION=""
fi
if [ "${IS_SETENV}" = "y" ]; then
INSTALL_OPTION="${INSTALL_OPTION} --setenv"
fi
}
# 创建单个文件的软链接,链接文件级别
create_file_softlink() {
local src_file=$1
local dst_file=$2
local base_dir=$(dirname ${dst_file})
comm_create_dir "${base_dir}" "${CREATE_DIR_PERM}" "${TARGET_USERNAME}:${TARGET_USERGROUP}" "${IS_FOR_ALL}"
local relative_file_path=$(realpath -s --relative-to="${base_dir}" "${src_file}")
# 创建软连接
createsoftlink "${relative_file_path}" "${dst_file}"
}
# 创建单个目录的软连接,链接目录级别
create_dir_softlink() {
local src_dir=$1
local dst_dir=$2
local base_dir=$(dirname ${dst_dir})
comm_create_dir "${base_dir}" "${CREATE_DIR_PERM}" "${TARGET_USERNAME}:${TARGET_USERGROUP}" "${IS_FOR_ALL}"
if [ ! -d "${src_dir}" ]; then
logandprint "[ERROR]: src dir ["${src_dir}"] not exists to create soft link."
fi
# 获取相对路径
relative_dir_path=$(realpath -s --relative-to="${base_dir}" "${src_dir}")
# 创建软连接
createsoftlink "${relative_dir_path}" "${dst_dir}"
}
# 创建目录下子目录的软连接,链接子目录级别
create_softlink_for_dirs() {
local src_dir=$1
local dst_dir=$2
if [ ! -d "${src_dir}" ]; then
logandprint "[ERROR]: src dir ["${src_dir}"] not exists to create soft link."
exit 1
fi
comm_create_dir "${dst_dir}" "${CREATE_DIR_PERM}" "${TARGET_USERNAME}:${TARGET_USERGROUP}" "${IS_FOR_ALL}"
find "${src_dir}" -mindepth 1 -maxdepth 1 -type d -print0 | while IFS= read -r -d '' src_dir_path; do
local sub_dir_name=$(basename ${src_dir_path})
local dst_dir_path="${dst_dir}/${sub_dir_name}"
# 计算目录相对路径
local relative_dir_path=$(realpath -s --relative-to="${dst_dir}" "${src_dir_path}")
# 创建软连接
createsoftlink "${relative_dir_path}" "${dst_dir_path}"
done
}
# 创建某目录下所有文件的软链接,链接文件级别,要求目录中不能有子目录
create_softlink_for_files() {
local src_dir=$1
local dst_dir=$2
local exclude_list="$3"
if [ ! -d "${src_dir}" ]; then
logandprint "[ERROR]: src dir ["${src_dir}"] not exists, cannot create soft link."
exit 1
fi
comm_create_dir "${dst_dir}" "${CREATE_DIR_PERM}" "${TARGET_USERNAME}:${TARGET_USERGROUP}" "${IS_FOR_ALL}"
find "${src_dir}" -mindepth 1 -maxdepth 1 -type f -print0 | while IFS= read -r -d '' src_file_path; do
# 文件名
local file_name=$(basename ${src_file_path})
if $(echo ${exclude_list} | grep -wq ${file_name}); then
continue
fi
local dst_file_path="${dst_dir}/${file_name}"
# 获取相对路径
local relative_file_path=$(realpath --relative-to="${dst_dir}" "${src_file_path}")
# 创建软连接
createsoftlink "${relative_file_path}" "${dst_file_path}"
done
}
# 递归创建目录下所有文件的软链接,链接文件级别,目录中可以有子目录,对于子目录会创建对应目录不是链接
create_softlink_for_files_and_dirs() {
local src_dir=$1
local dst_dir=$2
if [ ! -d "${src_dir}" ]; then
logandprint "[ERROR]: src dir ["${src_dir}"] not exists, cannot create soft link."
exit 1
fi
comm_create_dir "${dst_dir}" "${CREATE_DIR_PERM}" "${TARGET_USERNAME}:${TARGET_USERGROUP}" "${IS_FOR_ALL}"
find "${src_dir}" -mindepth 1 -maxdepth 1 -type d -print0 | while IFS= read -r -d '' src_dir_path; do
local base_dir=$(basename ${src_dir_path})
local dst_dir_path="${dst_dir}/${base_dir}"
create_softlink_for_files_and_dirs ${src_dir_path} ${dst_dir_path}
done
create_softlink_for_files ${src_dir} ${dst_dir}
}
add_init_py() {
local opp_builtin_mod=""
local built_in_impl_path=${TARGET_OPP_BUILT_IN}/op_impl/ai_core/tbe/impl/ops_transformer
if [ -d ${built_in_impl_path} ]; then
opp_builtin_mod=$(stat -c %a ${built_in_impl_path})
if [ "$(id -u)" != 0 ] && [ ! -w "${built_in_impl_path}" ]; then
chmod u+w -R "${built_in_impl_path}" 2>/dev/null
fi
fi
touch ${built_in_impl_path}/__init__.py
[ -d ${built_in_impl_path}/dynamic ] && touch ${built_in_impl_path}/dynamic/__init__.py
if [ -n "${opp_builtin_mod}" ]; then
chmod ${opp_builtin_mod} -R "${built_in_impl_path}" 2>/dev/null
fi
}
install_opp() {
logandprint "[INFO]: Begin install opp module."
comm_create_dir "${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}" "${CREATE_DIR_PERM}" "${TARGET_USERNAME}:${TARGET_USERGROUP}" "${IS_FOR_ALL}"
setenv
logandprint "[INFO]: Update the opp install info."
update_install_infos "${TARGET_USERNAME}" "${TARGET_USERGROUP}" "${INSTALL_TYPE}" "${relative_path_val}"
log_with_errorlevel "$?" "error" "[ERROR]: ERR_NO:${INSTALL_FAILED};ERR_DES:Update opp install info failed."
bash "${COMMON_PARSER_FILE}" --package="${OPP_PLATFORM_DIR}" --install --username="${TARGET_USERNAME}" \
--usergroup="${TARGET_USERGROUP}" --set-cann-uninstall --version=$RUN_PKG_VERSION \
--use-share-info --version-dir=$PKG_VERSION_DIR $INSTALL_OPTION ${INSTALL_FOR_ALL} "--feature=all" "--chip=all" \
"${INSTALL_TYPE}" "${TARGET_INSTALL_PATH}" "${FILELIST_FILE}"
log_with_errorlevel "$?" "error" "[ERROR]: ERR_NO:${INSTALL_FAILED};ERR_DES:Install opp module files failed."
logandprint "[INFO]: upgradePercentage:30%"
add_init_py
logandprint "[INFO]: upgradePercentage:50%"
}
main() {
logandprint "[INFO]: Command opp_install"
get_opts "$@"
init_install_env
get_package_upgrade_version_dir "upgrade_version_dir" "$TARGET_INSTALL_PATH" "${OPP_PLATFORM_DIR}"
get_package_last_installed_version "last_installed" "$TARGET_INSTALL_PATH" "${OPP_PLATFORM_DIR}"
last_installed_version=$(echo ${last_installed} | cut --only-delimited -d":" -f2-)
get_install_path
check_env
install_opp
# change log dir and file owner and rights
chmod "${LOG_PATH_PERM}" "${COMM_LOG_DIR}" 2>/dev/null
chmod "${LOG_FILE_PERM}" "${COMM_LOGFILE}" 2>/dev/null
chmod "${LOG_FILE_PERM}" "${COMM_OPERATION_LOGFILE}" 2>/dev/null
if [ "$(id -u)" = "0" ]; then
chmod "${CUSTOM_PERM}" -R "${TARGET_OPP_BUILT_IN}" 2>/dev/null
else
chmod "${BUILTIN_PERM}" -R "${TARGET_OPP_BUILT_IN}" 2>/dev/null
fi
chmod "${ONLYREAD_PERM}" "${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/scene.info" 2>/dev/null
chmod "${ONLYREAD_PERM}" "${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/version.info" 2>/dev/null
chmod "${ONLYREAD_PERM}" "${INSTALL_INFO_FILE}" 2>/dev/null
# change installed folder's owner and group except aicpu
log_with_errorlevel "$?" "error" "[ERROR]: ERR_NO:${INSTALL_FAILED};ERR_DES:Change opp ownership failed.."
logandprint "[INFO]: upgradePercentage:100%"
logandprint "[INFO]: Installation information listed below:"
logandprint "[INFO]: Install path: (${TARGET_VERSION_DIR}/opp)"
logandprint "[INFO]: Install log file path: (${COMM_LOGFILE})"
logandprint "[INFO]: Operation log file path: (${COMM_OPERATION_LOGFILE})"
if [ "${IS_SETENV}" != "y" ]; then
logandprint "[INFO]: Using requirements: when opp module install finished or \
before you run the opp module, execute the command \
[ export ASCEND_OPP_PATH=${TARGET_INSTALL_PATH}/cann/opp ] to set the environment path."
fi
logandprint "[INFO]: Opp package installed successfully! The new version takes effect immediately."
}
main "$@"
exit 0

View File

@@ -0,0 +1,225 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
OPERATE_FAILED="0x0001"
PARAM_INVALID="0x0002"
PARAM_INVALID_DES="Invalid input parameter."
FILE_NOT_EXIST="0x0080"
FILE_NOT_EXIST_DES="File not found."
FILE_READ_FAILED="0x0082"
FILE_READ_FAILED_DES="File read failed."
CURR_PATH=$(dirname $(readlink -f $0))
COMMON_INC_FILE="${CURR_PATH}/common_func.inc"
OPP_COMMON_FILE="${CURR_PATH}/opp_common.sh"
. "${COMMON_INC_FILE}"
. "${OPP_COMMON_FILE}"
ARCH_INFO=$(uname -m)
OPP_PLATFORM_DIR=ops_transformer
OPP_PLATFORM_UPPER=$(echo "${OPP_PLATFORM_DIR}" | tr '[:lower:]' '[:upper:]')
FILELIST_FILE="${CURR_PATH}/filelist.csv"
COMMON_PARSER_FILE="${CURR_PATH}/install_common_parser.sh"
TARGET_INSTALL_PATH=""
TARGET_VERSION_DIR="${CURR_PATH}/../../../.."
TARGET_VERSION_DIR=$(readlink -f ${TARGET_VERSION_DIR}) # TARGET_INSTALL_PATH + PKG_VERSION_DIR
TARGET_MOULDE_DIR=${TARGET_VERSION_DIR}/${OPP_PLATFORM_DIR} # TARGET_INSTALL_PATH + PKG_VERSION_DIR + OPP_PLATFORM_DIR
TARGET_OPP_BUILT_IN=${TARGET_VERSION_DIR}/opp/built-in
TARGET_SHARED_INFO_DIR=${TARGET_VERSION_DIR}/share/info
ASCEND_INSTALL_INFO="ascend_install.info"
# init log file path
INSTALL_INFO_FILE="${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/${ASCEND_INSTALL_INFO}"
VERSION_INFO_FILE="${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/version.info"
# keys of infos in ascend_install.info
KEY_INSTALLED_UNAME="USERNAME"
KEY_INSTALLED_UGROUP="USERGROUP"
KEY_INSTALLED_TYPE="${OPP_PLATFORM_UPPER}_INSTALL_TYPE"
KEY_INSTALLED_FEATURE="${OPP_PLATFORM_UPPER}_INSTALL_FEATURE"
KEY_INSTALLED_PATH="${OPP_PLATFORM_UPPER}_INSTALL_PATH_VAL"
KEY_INSTALLED_VERSION="${OPP_PLATFORM_UPPER}_VERSION"
get_opts() {
INSTALLED_PATH="$1"
UNINSTALL_MODE="$2"
IS_QUIET="$3"
IN_FEATURE="$4"
IS_DOCKER_INSTALL="$5"
DOCKER_ROOT="$6"
PKG_VERSION_DIR="$7"
local paramter_num="$#"
if [ "${paramter_num}" != 0 ]; then
if [ "${INSTALLED_PATH}" = "" ] ||
[ "${UNINSTALL_MODE}" = "" ] ||
[ "${IS_QUIET}" = "" ]; then
logandprint "[ERROR]: ERR_NO:${PARAM_INVALID};ERR_DES:Empty parameters is invalid\
for call uninstall functions."
exit 1
fi
fi
}
get_docker_install_path() {
local docker_root_tmp="$(echo "${DOCKER_ROOT}" | sed "s#/\+\$##g")"
local docker_root_regex="$(echo "${docker_root_tmp}" | sed "s#\/#\\\/#g")"
relative_path_val=$(echo "${TARGET_VERSION_DIR}" | sed "s/^${docker_root_regex}//g" | sed "s/\/\+\$//g")
return
}
log_with_errorlevel() {
local ret_status="$1"
local level="$2"
local msg="$3"
if [ "${ret_status}" != 0 ]; then
if [ "${level}" = "error" ]; then
logandprint "${msg}"
exit 1
else
logandprint "${msg}"
fi
fi
}
check_directory_exist() {
local path="${1}"
if [ ! -d "${path}" ]; then
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST};ERR_DES:Installation directory [${path}] does not exist, uninstall failed."
exit 1
fi
}
check_file_exist() {
local path_param="${1}"
if [ ! -f "${path_param}" ]; then
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST};ERR_DES:The file (${path_param}) does not existed."
exit 1
fi
}
check_installed_files() {
# check install folder existed
check_file_exist "${INSTALL_INFO_FILE}"
check_file_exist "${FILELIST_FILE}"
check_file_exist "${COMMON_PARSER_FILE}"
}
check_installed_type() {
local type="$1"
if [ "${type}" != "run" ] &&
[ "${type}" != "full" ] &&
[ "${type}" != "devel" ]; then
logandprint "[ERROR]: ERR_NO:${UNAME_NOT_EXIST};ERR_DES:Install type of opp module is not right!"
exit 1
fi
}
unsetenv() {
logandprint "[INFO]: Unset the environment path [ export ASCEND_OPP_PATH=${relative_path_val}/opp ]."
if [ "${IS_DOCKER_INSTALL}" = y ]; then
UNINSTALL_OPTION="--docker-root=${DOCKER_ROOT}"
else
UNINSTALL_OPTION=""
fi
}
get_installed_info() {
local key="$1"
local res=""
if [ -f "${INSTALL_INFO_FILE}" ]; then
chmod 644 "${INSTALL_INFO_FILE}" >/dev/null 2>&1
res=$(cat ${INSTALL_INFO_FILE} | grep "${key}" | awk -F = '{print $2}')
fi
echo "${res}"
}
get_installed_param() {
INSTALLED_TYPE=$(get_installed_info "${KEY_INSTALLED_TYPE}")
TARGET_USERNAME=$(get_installed_info "${KEY_INSTALLED_UNAME}")
TARGET_USERGROUP=$(get_installed_info "${KEY_INSTALLED_UGROUP}")
get_package_version "RUN_PKG_VERSION" "$VERSION_INFO_FILE"
if [ "${PKG_VERSION_DIR}" = "" ]; then
TARGET_INSTALL_PATH=${TARGET_VERSION_DIR}
else
TARGET_INSTALL_PATH=$(readlink -f "${TARGET_VERSION_DIR}/../")
fi
}
remove_module() {
chmod u+w ${TARGET_SHARED_INFO_DIR}/${OPP_PLATFORM_DIR}/scene.info
logandprint "[INFO]: Delete the installed opp source files in (${TARGET_VERSION_DIR})."
bash "${COMMON_PARSER_FILE}" --package="${OPP_PLATFORM_DIR}" --uninstall --remove-install-info \
--username="${TARGET_USERNAME}" --usergroup="${TARGET_USERGROUP}" --version=$RUN_PKG_VERSION \
--use-share-info --version-dir=$PKG_VERSION_DIR ${UNINSTALL_OPTION} "${INSTALLED_TYPE}" "${TARGET_INSTALL_PATH}" \
"${FILELIST_FILE}" "${IN_FEATURE}" --recreate-softlink
log_with_errorlevel "$?" "error" "[ERROR]: ERR_NO:${OPERATE_FAILED};ERR_DES:Uninstall opp module failed."
}
remove_init_py() {
local built_in_impl_path=${TARGET_OPP_BUILT_IN}/op_impl/ai_core/tbe/impl/ops_transformer
[ -e ${built_in_impl_path}/__init__.py ] && rm ${built_in_impl_path}/__init__.py > /dev/null 2>&1
[ -e ${built_in_impl_path}/dynamic/__init__.py ] && rm ${built_in_impl_path}/dynamic/__init__.py > /dev/null 2>&1
}
remove_ops_transformer() {
if [ "$(id -u)" != 0 ] && [ ! -w "${TARGET_OPP_BUILT_IN}" ]; then
chmod u+w -R "${TARGET_OPP_BUILT_IN}" 2>/dev/null
fi
remove_init_py
remove_module
if [ "${UNINSTALL_MODE}" != "upgrade" ]; then
logandprint "[INFO]: Delete the install info file (${INSTALL_INFO_FILE})."
rm -f "${INSTALL_INFO_FILE}"
log_with_errorlevel "$?" "warn" "[WARNING] Delete ops install info file failed, please delete it by yourself."
fi
}
logandprint "[INFO]: Begin uninstall the opp module."
main() {
get_opts "$@"
get_docker_install_path
check_installed_files
get_installed_param
check_installed_type "${INSTALLED_TYPE}"
unsetenv
remove_ops_transformer
if [ "${UNINSTALL_MODE}" != "upgrade" ]; then
remove_dir_if_empty ${TARGET_VERSION_DIR}
fi
remove_dir_if_empty ${INSTALLED_PATH}
logandprint "[INFO]: Opp package uninstalled successfully! Uninstallation takes effect immediately."
}
main "$@"
exit 0

View File

@@ -0,0 +1,84 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
CURR_PATH=$(dirname $(readlink -f $0))
# error number and description
FILE_NOT_EXIST="0x0080"
PERM_DENIED="0x0093"
PERM_DENIED_DES="Permission denied."
# log functions
getdate() {
_cur_date=$(date +"%Y-%m-%d %H:%M:%S")
echo "${_cur_date}"
}
logandprint() {
is_error_level=$(echo $1 | grep -E 'ERROR|WARN|INFO')
if [ "${is_quiet}" != "y" ] || [ "${is_error_level}" != "" ]; then
echo "[OpsTransformer] [$(getdate)] ""$1"
fi
echo "[OpsTransformer] [$(getdate)] ""$1" >> "${_INSTALL_LOG_FILE}"
}
if [ "$(id -u)" != "0" ]; then
_LOG_PATH=$(echo "${HOME}")"/var/log/ascend_seclog"
_INSTALL_LOG_FILE="${_LOG_PATH}/ascend_install.log"
else
_LOG_PATH="/var/log/ascend_seclog"
_INSTALL_LOG_FILE="${_LOG_PATH}/ascend_install.log"
fi
# init install cmd status, set default as n
is_quiet=n
quiet_parameter=""
if [ "$#" != "0" ]; then
if [ "$1" = "--quiet" ] && [ "$#" = "1" ]; then
is_quiet=y
quiet_parameter="--quiet"
else
logandprint "Please use correct parameters, only support input nothing or only --quiet parameter."
exit 1
fi
fi
install_shell="${CURR_PATH}/install.sh"
# shell exist check
if [ ! -f "${install_shell}" ]; then
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST};OpsTransformer module is not installed or some ops_transformer source files are lost.\
If there are any residual files, please manually remove those files."
exit 1
fi
# shell execute perm check
if [ ! -x "${install_shell}" ]; then
logandprint "[ERROR]: ERR_NO:${PERM_DENIED};ERR_DES:The user do \
not have the permission to execute this file, please reset the file \
to a right permission."
exit 1
fi
installed_path="$(cd "${CURR_PATH}/../../../../"; pwd)"
parent_installed_path="$(cd "${installed_path}/../"; pwd)"
cd ~
sh "${install_shell}" "--aa" "--aa" "--uninstall" "--install-path=${installed_path}" "${quiet_parameter}"
ret_status="$?"
if [ "${ret_status}" != "0" ]; then
exit 1
fi
if [ -d "${parent_installed_path}" ];then
subdirs_param_install=$(ls "${parent_installed_path}" 2> /dev/null)
if [ "${subdirs_param_install}" = "" ]; then
rm -rf "${parent_installed_path}"
fi
fi
exit 0

View File

@@ -0,0 +1,173 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
req_ver_path=$1
_CURR_PATH=$(dirname $(readlink -f $0))
_DEFAULT_INSTALL_PATH="/usr/local/Ascend"
FILE_NOT_EXIST="0x0080"
getdate() {
_cur_date=$(date +"%Y-%m-%d %H:%M:%S")
echo "${_cur_date}"
}
logandprint() {
echo "[OpsTransformer] [$(getdate)] ""$1"
}
check_path_pre() {
in_checkpath_0="$1"
in_checkpath_1=$(echo ${in_checkpath_0} | cut -d"=" -f2)
if [ "${in_checkpath_1}" = "" ]; then
logandprint "[WARNING]: please input correct path"
exit 1
fi
arr=$(echo ${in_checkpath_1} | awk '{split($0,arr," ");for(i in arr) print arr[i]}')
index=0
for i in $arr; do
id=$((${id:=-1} + 1))
eval arr_$id=$i
index=$(expr $index + 1)
done
len="${index}"
b=0
for i in $(seq 0 ${len}); do
select_last_dir_component "$(eval echo '$'arr_$i)"
ret=$last_component
if [ "${ret}" != "" ]; then
eval checked_path_temp_$b=$(eval echo '$'arr_$i)
b=$(expr $b + 1)
fi
done
check_all_path=""
for i in $(seq 0 ${len}); do
check_all_path="$(eval echo '$'checked_path_temp_$i) $check_all_path"
done
checked_path="${check_all_path}"
return
}
select_last_dir_component() {
path="$1"
last_component=$(basename "${path}")
if [ "${last_component}" = "atc" ]; then
last_component="atc"
return
elif [ "${last_component}" = "fwkacllib" ]; then
last_component="fwkacllib"
return
elif [ "${last_component}" = "compiler" ]; then
last_component="compiler"
return
elif [ "${last_component}" = "fwkplugin" ]; then
last_component="fwkplugin"
return
else
last_component="atc or fwkacllib or compiler"
return
fi
}
check_version_file() {
pkg_path="$1"
component_ret="$2"
run_pkg_path_temp=$(dirname "${pkg_path}")
run_pkg_path="${run_pkg_path_temp}""/${component_ret}"
version_file="${run_pkg_path}""/version.info"
if [ -f "${version_file}" ]; then
echo "${version_file}" 2 >>/dev/null
else
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST}; The [${component_ret}] version.info in path [${pkg_path}] not exists."
exit 1
fi
return
}
check_opp_version_file() {
if [ -f "${_CURR_PATH}/../../version.info" ]; then
ver_info="${_CURR_PATH}/../../version.info"
# ops_transformer/version.info -> ops_transformer
elif [ -f "${_DEFAULT_INSTALL_PATH}/ops_transformer/version.info" ]; then
ver_info="${_DEFAULT_INSTALL_PATH}/ops_transformer/version.info"
else
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST}; The [ops_transformer] version.info not exists."
fi
return
}
check_relation() {
opp_ver_info="$1"
req_pkg_name="$2"
req_pkg_version="$3"
_COMMON_INC_FILE="${_CURR_PATH}/common_func.inc"
if [ -f "${_COMMON_INC_FILE}" ]; then
. "${_COMMON_INC_FILE}"
check_pkg_ver_deps "${opp_ver_info}" "${req_pkg_name}" "${req_pkg_version}"
ret_situation=$ver_check_status
else
logandprint "[ERROR]: ERR_NO:${FILE_NOT_EXIST}; The ${_COMMON_INC_FILE} not exists."
fi
return
}
show_relation() {
relation_situation="$1"
req_pkg_name_val="$2"
req_pkg_path="$3"
if [ "$relation_situation" = "SUCC" ]; then
logandprint "[INFO]: Relationship of ops_transformer with ${req_pkg_name_val} in path ${req_pkg_path} check successfully"
return 0
else
logandprint "[WARNING]: Relationship of ops_transformer with ${req_pkg_name_val} in path ${req_pkg_path} check failed. \
do you want to continue. [y/n] "
while true; do
read yn
if [ "$yn" == "n" ]; then
echo "stop check!"
exit 1
elif [ "$yn" = y ]; then
break
else
echo "[WARNING]: Input error, please input y or n to choose!"
fi
done
fi
}
version_check() {
path_val="$1"
#get ops_transformer version
check_opp_version_file
ret_check_opp_version_file=$ver_info
#get checked path
check_path_pre "${path_val}"
ret_check_path_pre=$checked_path
if [ "${ret_check_path_pre}" != "" ]; then
for var in ${ret_check_path_pre}; do
# select_last_dir_component "${var}"
# component_ret=$last_component
#get atc or fwkacllib name
select_last_dir_component "${var}"
ret_last_component=$last_component
#get the version of atc/fwkacllib
check_version_file "${var}" "${ret_last_component}"
ret_check_version_file=$version_file
#check relation
check_relation "${ret_check_opp_version_file}" "${ret_last_component}" "${ret_check_version_file}"
ret_check_relation=$ret_situation
#show relation
show_relation "${ret_check_relation}" "${ret_last_component}" "${var}"
done
fi
}
version_check "${req_ver_path}"
exit 0

View File

@@ -0,0 +1,823 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
import argparse
import csv
import os
import shutil
import sys
import traceback
from argparse import Namespace
from collections import namedtuple
from collections.abc import Iterator
from datetime import datetime, timezone
from functools import partial
from itertools import chain
from typing import TextIO
import regex as re
from common.py.filelist import (
FileItem,
FileList,
check_filelist,
create_file_item,
generate_filelist,
get_transform_nested_path_func,
)
from common.py.packer import PackageName, create_makeself_pkg_params_factory, create_run_package_command, exec_pack_cmd
from common.py.pkg_parser import ParseOption, XmlConfig, get_cann_version_info, parse_xml_config
from common.py.utils import pkg_utils
from common.py.utils.comm_log import CommLog
from common.py.utils.funcbase import invoke, pipe
from common.py.utils.pkg_utils import (
CONFIG_SCRIPT_PATH,
DELIVERY_PATH,
FAIL,
SUCCESS,
TOP_DIR,
CompressError,
ContainAsteriskError,
FilelistError,
GenerateFilelistError,
PackageNameEmptyError,
UnknownOperateTypeError,
path_join,
)
def get_comments(package_name: PackageName) -> str:
"""获取run包注释。"""
comments = "_".join([package_name.chip_name.upper(), package_name.func_name.upper(), "RUN_PACKAGE"])
return f'"{comments}"'
def get_compress_cmd(delivery_dir: str, pkg_args: Namespace, xml_config: XmlConfig) -> str:
"""获取makeself压缩命令"""
suffix = xml_config.package_attr.get("suffix")
if suffix == "run":
package_name = PackageName(xml_config.package_attr, pkg_args, xml_config.version)
factory = create_makeself_pkg_params_factory(
pkg_args.pkg_output_dir, package_name.getvalue(), get_comments(package_name)
)
params = factory(pkg_args.makeself_dir, xml_config.package_attr, pkg_args.independent_pkg)
pack_cmd, err_msg = create_run_package_command(params)
if err_msg:
CommLog.cilog_error(err_msg)
CommLog.cilog_error("create_run_command failed!")
raise CompressError(package_name.getvalue())
if pkg_args.independent_pkg:
exec_pack_cmd(delivery_dir, pack_cmd, package_name.getvalue())
else:
CommLog.cilog_error("the repack type '%s' is not support!", suffix)
sys.exit(FAIL)
try:
makeself_dir = os.path.join(TOP_DIR, "build/makeself.txt")
with open(makeself_dir, "w") as f:
f.write(pack_cmd)
except Exception as exception:
CommLog.cilog_error(f"save makeself.txt failed!{str(exception)}")
sys.exit(FAIL)
return package_name.getvalue()
def make_parse_option(args_: argparse.Namespace) -> ParseOption:
"""创建解析参数。"""
return ParseOption(args_.os_arch, args_.pkg_version, args_.build_type, args_.package_check, args_.ext_name)
PrivatePackageOption = namedtuple(
"PrivatePackageOption",
[
"os_arch",
"package_suffix",
"not_in_name",
"pkg_version",
"ext_name",
"chip_name",
"func_name",
"version_dir",
"disable_multi_version",
"suffix",
],
)
class PackageOption(PrivatePackageOption):
"""打包配置参数。"""
__slots__ = () # 优化内存,避免创建 __dict__
def __new__(cls, *package_option_args, **kwargs):
return super().__new__(cls, *package_option_args, **kwargs)
def generate_info_content(target_conf, ext_name) -> list[str]:
"""生成info内容。"""
def toolchain_llvm_config() -> Iterator[tuple[str, str]]:
if "llvm" in ext_name:
yield "toolchain", "llvm"
content_list = [f"{key}={value}" for key, value in chain(target_conf["content"].items(), toolchain_llvm_config())]
return content_list
def generate_version_header_content(target_conf) -> Iterator[str]:
"""生成version_header内容。"""
guard_name = target_conf["value"].replace(".", "_").upper()
yield f"#ifndef {guard_name}"
yield f"#define {guard_name}"
yield ""
for name, value in target_conf["content"].items():
if name.endswith("_VERSION"):
version_infos = get_cann_version_info(name, value)
for version_name, version_value in version_infos:
yield f"#define {version_name} {version_value}"
else:
yield f"#define {name} {value}"
yield ""
yield f"#endif /* {guard_name} */"
yield ""
def generate_customized_file(target_conf, ext_name):
filepath = os.path.join(TOP_DIR, "build", target_conf.get("value"))
generator = target_conf.get("generator", "info")
if generator == "version_header":
content_list = generate_version_header_content(target_conf)
else:
content_list = generate_info_content(target_conf, ext_name)
file_content = "\n".join(content_list)
try:
with open(filepath, "w") as file:
file.write(file_content)
except Exception as ex:
CommLog.cilog_error(f"generate customized file {filepath} failed: {ex}!")
return FAIL
return SUCCESS
def get_module(target_config) -> str:
"""获取配置模块。"""
module = target_config.get("module", "NA")
return module if module else "NA"
def get_operation(operation, target_config) -> str:
"""获取操作类型。"""
if operation in ("copy", "move") and target_config.get("entity") == "true":
return "copy_entity"
return operation
def get_permission(target_config) -> str:
"""获取配置权限。"""
return target_config.get("install_mod", "NA")
def get_owner_group(target_config) -> str:
"""获取配置属主。"""
# install_own的可能值为$username:$usergroup
# 防止变量在install_common_parser.sh中被eval展开添加\转义$
# 由于awk会消耗1个\所以需要2个转义符
return target_config.get("install_own", "NA").replace("$", "\\\\$")
def get_install_type(target_config) -> str:
"""获取安装类型。"""
return target_config.get("install_type", "NA")
def get_softlink(target_config) -> list[str]:
"""获取配置软链。"""
softlink_str = target_config.get("install_softlink")
if not softlink_str:
return []
return softlink_str.split(";")
def get_feature(target_config) -> set[str]:
"""获取配置特性。"""
return target_config["feature"]
def get_chip(target_config) -> set[str]:
"""获取配置芯片。"""
return target_config["chip"]
def get_configurable(target_config) -> str:
"""获取配置是否为配置文件。"""
return target_config.get("configurable", "FALSE")
def get_hash_value(target_config) -> str:
"""获取配置哈希值。"""
return target_config.get("hash", "NA")
def get_block(target_config) -> str:
"""获取配置块信息。"""
return target_config.get("name", "NA")
def get_pkg_inner_softlink(target_config) -> list[str]:
"""获取配置包内软链。"""
softlink_str = target_config.get("pkg_inner_softlink")
if not softlink_str:
return []
return softlink_str.split(";")
def parse_install_info(infos: list, operate_type, filter_key) -> Iterator[FileItem]:
"""根据配置解析生成安装信息。"""
for target_config in infos:
target_name = get_target_name(target_config)
if target_config.get("optional") == "true" and operate_type in ("copy", "move"):
path = os.path.join(TOP_DIR, DELIVERY_PATH, target_config.get("dst_path"))
value = os.path.join(TOP_DIR, DELIVERY_PATH, target_config.get("dst_path"), target_name)
if not os.path.exists(path):
continue
if not os.path.exists(value):
continue
if operate_type in ("copy", "move"):
relative_path_in_pkg = os.path.join(target_config.get("dst_path"), target_name)
relative_install_path = path_join(target_config.get("install_path"), target_name)
is_dir = target_config.get("is_dir", False)
elif operate_type == "mkdir":
relative_path_in_pkg = "NA"
relative_install_path = target_config.get("value")
is_dir = False
elif operate_type == "del":
relative_path_in_pkg = "NA"
relative_install_path = path_join(target_config.get("install_path"), target_name)
is_dir = False
else:
raise UnknownOperateTypeError(f"unknown operate type {operate_type}")
if relative_install_path is None:
continue
install_type = get_install_type(target_config)
if any(key in install_type for key in filter_key):
is_in_docker = "TRUE"
else:
is_in_docker = "FALSE"
file_item = create_file_item(
get_module(target_config),
get_operation(operate_type, target_config),
relative_path_in_pkg,
relative_install_path,
is_in_docker,
get_permission(target_config),
get_owner_group(target_config),
install_type,
get_softlink(target_config),
get_feature(target_config),
"N",
get_configurable(target_config),
get_hash_value(target_config),
get_block(target_config),
get_pkg_inner_softlink(target_config),
get_chip(target_config),
is_dir,
)
yield file_item
def execute_repack_process(
xml_config: XmlConfig,
delivery_dir: str,
pkg_args: Namespace,
package_name: PackageName = None,
package_option: PackageOption = None,
):
"""
功能描述: 执行打包流程(拷贝--->签名--->打包)
返回值: SUCCESS/FAIL
"""
release_dir = os.path.join(delivery_dir, xml_config.default_config.get("name", "default"))
# 生成自定义文件
for item in xml_config.generate_infos:
if generate_customized_file(item, package_option.ext_name):
return FAIL
# 校验包中文件或目录大小
if pkg_args.check_size == "True":
limit_list, tag = processing_csv_file(
release_dir, package_name.func_name, package_name.chip_name, pkg_args.build_type
)
if not tag:
return FAIL
if limit_list:
abspath = os.path.abspath(release_dir)
replace_path = abspath + "/"
result = check_add_dir(replace_path, abspath, limit_list)
if not result:
return FAIL
try:
package_name = get_compress_cmd(pkg_args.pkg_output_dir, pkg_args, xml_config)
except CompressError:
return FAIL
CommLog.cilog_info("package %s generate filelist.csv and makeself cmd successfully!", package_name)
return SUCCESS
def check_path_is_conflict(xml_config):
"""
功能描述: 检查打包时安装路径与软连接路径是否冲突
参数: xml_config
返回值: SUCCESS/FAIL
"""
install_path_list = set()
pkg_softlink_list = set()
for item in xml_config.package_content_list:
value_list = item.get("value").split("/")
target_name = value_list[-1] if value_list[-1] else value_list[-2]
if item.get("install_path"):
install_path_list.add(os.path.join(item["install_path"], target_name))
if item.get("pkg_inner_softlink"):
pkg_softlink = item.get("pkg_inner_softlink")
pkg_softlink_list.add(pkg_softlink)
if install_path_list & pkg_softlink_list:
CommLog.cilog_info("intersection:{}".format(install_path_list & pkg_softlink_list))
CommLog.cilog_info("path conflicting: pkg_inner_softlink dir equals install_path!!")
return FAIL
return SUCCESS
def checksum_value(limit_value, release_dir):
"""
功能描叙: 校验传入的文件或目录大小是否合格
参数:
limit_value: limit.csv中的一行数据如[compiler/bin, 3976, 110%]
返回值: True/False
"""
path = os.path.join(release_dir, limit_value[1])
if len(limit_value) >= 7:
try:
max_value = int(limit_value[4])
except ValueError:
CommLog.cilog_error(f"{path} configuration is not standard., Please check limit.csv.")
return True
else:
CommLog.cilog_error(f"{path} configuration is less than four, Please check limit.csv.")
return True
if not os.path.exists(path):
CommLog.cilog_warning(f"{path} doesn't exist, Please check limit.csv.")
return True
size = 0
for root, dirs, files in os.walk(path):
size += os.path.getsize(root)
for f in files:
filepath = os.path.join(root, f)
if os.path.islink(filepath):
continue
if not os.path.exists(filepath):
continue
size += os.path.getsize(os.path.join(root, f))
if size == 0:
size = os.path.getsize(path)
if size > max_value * 1024:
CommLog.cilog_error(f"\n{path} size {size} bytes exceeds maximum {max_value * 1024} bytes")
return False
return True
def processing_csv_file(release_dir, package_name, chip_name, build_type):
"""
功能描叙: 处理limit.csv文件数据
返回值: [],True/[],False
"""
ret = True
limit_list = []
product = os.path.basename(os.path.dirname(release_dir))
limit_path = os.path.join(pkg_utils.TOP_SOURCE_DIR, CONFIG_SCRIPT_PATH, "common/limit.csv")
if not os.path.exists(limit_path):
CommLog.cilog_warning(f"{limit_path} doesn't exist.")
return limit_list, ret
with open(limit_path) as file:
reader = csv.reader(file)
next(reader)
for data in reader:
if not data:
CommLog.cilog_warning("The limit.csv file contains empty lines.")
continue
if is_match_line(package_name, chip_name, product, build_type, data):
if data[1][-1] == "/":
limit_list.append(data[1][:-1])
else:
limit_list.append(data[1])
res = checksum_value(data, release_dir)
if not res:
ret = False
return limit_list, ret
def is_match_line(package_name, chip_name, product, build_type, data):
return package_name == data[0] and chip_name == data[5] and product == data[6] and build_type == data[7].lower()
def check_add_dir(package_path, dirs, limit_list, ret=True):
"""
功能描述: 校验新增目录
参数: path, limit_list
返回值: False/True
"""
for limit_path in limit_list:
if dirs == os.path.join(os.path.split(dirs)[0], limit_path):
return ret
for dir_file in os.listdir(dirs):
path = os.path.join(dirs, dir_file)
relative_path = path.replace(package_path, "")
if os.path.isfile(path) and relative_path not in limit_list:
CommLog.cilog_error(f"{path} is not in limit.csv file and is newly added.")
ret = False
elif os.path.isdir(path) and relative_path not in limit_list:
ret = check_add_dir(package_path, path, limit_list, ret)
return ret
def get_target_name(target_conf) -> str:
"""获取目标名。"""
rename = target_conf.get("rename")
if rename:
return rename
value_list = target_conf.get("value").split("/")
target_name = value_list[-1] if value_list[-1] else value_list[-2]
return target_name
def gen_file_install_list(xml_config: XmlConfig, filter_key) -> tuple[FileList, FileList]:
"""生成filelist列表。"""
file_install_list = []
dir_filelist = parse_install_info(xml_config.dir_install_list, "mkdir", filter_key)
move_filelist = parse_install_info(xml_config.move_content_list, "move", filter_key)
pkg_filelist = parse_install_info(xml_config.package_content_list, "copy", filter_key)
gen_filelist = parse_install_info(xml_config.generate_infos, "copy", filter_key)
# file_info中配置为文件夹这里是被展开的文件,则需要单独删除
del_filelist = parse_install_info(xml_config.expand_content_list, "del", filter_key)
collect_filelist = list(chain(dir_filelist, move_filelist, pkg_filelist, gen_filelist))
collect_filelist = list(xml_config.packer_config.fill_is_common_path(collect_filelist))
all_filelist = list(chain(collect_filelist, del_filelist))
for file_item in all_filelist:
file_install_list.append(file_item)
return file_install_list, []
def generate_filelist_file_by_xml_config(xml_config: XmlConfig, filter_key: list[str], package_check: bool):
"""生成文件列表文件。"""
check_move = xml_config.package_attr.get("use_move", False)
transform_nested_path_func = get_transform_nested_path_func(xml_config.package_attr.get("parallel") or check_move)
check_features = xml_config.package_attr.get("check_features", False)
file_install_list, [] = invoke(
pipe(
gen_file_install_list,
partial(map, transform_nested_path_func),
tuple,
),
xml_config,
filter_key,
)
generate_filelist(file_install_list, "filelist.csv")
# 先生成再检查,有利于问题定位
check_filelist(file_install_list, check_features, check_move)
def get_pkg_xml_relative_path(pkg_args: Namespace) -> str:
"""获取包配置文件相对路径。"""
def parts():
yield CONFIG_SCRIPT_PATH
yield pkg_args.pkg_name
if pkg_args.chip_scenes:
yield pkg_args.chip_scenes
# 可以通過build_rule指定xml_file而且优先级高于默认值
if pkg_args.xml_file:
yield pkg_args.xml_file
else:
yield f"{pkg_args.pkg_name}.xml"
return os.path.join(*parts())
def write_config_inc_var(name: str, package_attr: dict, file: TextIO):
"""向config.inc文件写入变量。"""
if name in package_attr:
value = str(package_attr[name]).lower()
file.write(f"{name.upper()}={value}\n")
def generate_config_inc(package_attr: dict):
"""生成config.inc文件。"""
if "parallel" not in package_attr and "parallel_limit" not in package_attr and "use_move" not in package_attr:
return
year = datetime.now(timezone.utc).year
config_inc = os.path.join(TOP_DIR, "build", "config.inc")
header = [
"#!/bin/sh\n",
"#----------------------------------------------------------------------------\n",
f"# Copyright Huawei Technologies Co., Ltd. 2023-{year}. All rights reserved.\n",
"#----------------------------------------------------------------------------\n",
"\n",
]
if os.path.isfile(config_inc):
os.chmod(config_inc, 0o700)
with open(config_inc, "w", encoding="utf-8") as file:
file.writelines(header)
write_config_inc_var("parallel", package_attr, file)
write_config_inc_var("parallel_limit", package_attr, file)
write_config_inc_var("use_move", package_attr, file)
os.chmod(config_inc, 0o500)
def update_version_info(new_version: str):
version_path = os.path.join(pkg_utils.TOP_DIR, "version.info")
with open(version_path) as file:
content = file.read()
content = re.sub(r"Version=.*", f"Version={new_version}", content)
content = re.sub(r"vension_dir=.*", f"version_dir={new_version}", content)
with open(version_path, "w") as file:
file.write(content)
def main(pkg_name="", xml_file="", main_args=None):
"""
功能描述: 执行打包流程(解析配置--->生成文件列表--->执行拷贝/打包动作)
参数: pkg_name, os_arch, type
返回值: SUCCESS/FAIL
"""
delivery_dir = os.path.join(TOP_DIR, DELIVERY_PATH)
if not os.path.exists(delivery_dir):
return FAIL
config_relative_path = get_pkg_xml_relative_path(main_args)
pkg_xml_file = os.path.join(pkg_utils.TOP_SOURCE_DIR, config_relative_path)
parse_option = make_parse_option(main_args)
if main_args.version_dir:
update_version_info(main_args.version_dir)
try:
xml_config = parse_xml_config(pkg_xml_file, delivery_dir, parse_option, main_args)
except ContainAsteriskError as ex:
CommLog.cilog_error(f"Value contain '*' in {config_relative_path}. value is '{ex.value}'.")
return FAIL
if pkg_name in ["driver", "firmware"]:
filter_key = ["all", "docker"]
elif pkg_name in ["aicpu_kernels_device", "aicpu_kernels_host"]:
filter_key = []
else:
filter_key = ["all", "run"]
# 生成filelist.csv安装列表文件
try:
generate_filelist_file_by_xml_config(
xml_config, filter_key, main_args.package_check or xml_config.package_attr.get("package_check")
)
except PackageNameEmptyError:
CommLog.cilog_error(f"package name is empty in {xml_file}, please check it")
return FAIL
except GenerateFilelistError as ex:
CommLog.cilog_error(
f"generate filelist {ex.filename} failed!",
)
return FAIL
except FilelistError as ex:
CommLog.cilog_error("check filelist error! %s", str(ex))
return FAIL
generate_config_inc(xml_config.package_attr)
if main_args.independent_pkg:
src_file_path = os.path.join(TOP_DIR, "build", "filelist.csv")
dst_file_path = os.path.join(main_args.pkg_output_dir, "share", "info", main_args.pkg_name, "script")
shutil.copy(src_file_path, dst_file_path)
package_option = PackageOption(
main_args.os_arch,
main_args.package_suffix,
main_args.not_in_name,
main_args.pkg_version,
main_args.ext_name,
chip_name=main_args.chip_name,
func_name=main_args.func_name,
version_dir=main_args.version_dir,
disable_multi_version=main_args.disable_multi_version,
suffix=main_args.suffix,
)
package_name = PackageName(xml_config.package_attr, main_args, xml_config.version)
# 检查install_path与pkg_inner_softlink路径是否冲突若冲突则报错
if check_path_is_conflict(xml_config) == FAIL:
return FAIL
# 生成打包命令
return execute_repack_process(
xml_config, delivery_dir, main_args, package_name=package_name, package_option=package_option
)
def args_parse():
"""
功能描述 : 脚本入参解析
参数 : 调用脚本的传参
返回值 : 解析后的参数值
"""
parser = argparse.ArgumentParser(description="This script is for package repack processing.")
parser.add_argument(
"-c",
"--chip_scenes",
metavar="chip_scenes",
required=False,
dest="chip_scenes",
nargs="?",
const="",
default="",
help="This parameter define chip id for package.",
)
parser.add_argument(
"-n", "--pkg_name", metavar="pkg_name", required=False, help="This parameter define pkg_name for config_xml."
)
parser.add_argument(
"-o",
"--os_arch",
metavar="os_arch",
required=False,
dest="os_arch",
nargs="?",
const="",
default=None,
help="This parameter define the package's os_arch",
)
parser.add_argument(
"-t",
"--type",
metavar="type",
required=False,
dest="type",
nargs="?",
const="",
default="repack",
help="This parameter define this script's function",
)
parser.add_argument(
"-i",
"--not_in_name",
metavar="not_in_name",
required=False,
dest="not_in_name",
nargs="?",
const="",
default="",
help="This parameter define the package's name not contain the element",
)
parser.add_argument(
"-v",
"--pkg_version",
metavar="pkg_version",
required=False,
dest="pkg_version",
nargs="?",
const="",
default="",
help="This parameter define the version for package.",
)
parser.add_argument(
"-e",
"--ext_name",
metavar="ext_name",
required=False,
dest="ext_name",
nargs="?",
const="",
default="",
help="This parameter define the package's ext_name",
)
parser.add_argument(
"--package_suffix",
nargs="?",
const="none",
default="none",
help="This parameter define the package suffix, debug or none",
)
parser.add_argument(
"--suffix",
metavar="suffix",
required=False,
dest="suffix",
nargs="?",
const="",
default=None,
help="This parameter define the package suffix, for example such as tar.gz",
)
parser.add_argument(
"-b",
"--build_type",
metavar="build_type",
required=False,
dest="build_type",
nargs="?",
const="",
default="debug",
help="This parameter define release type of package",
)
parser.add_argument(
"-x",
"--xml",
metavar="xml_file",
required=False,
dest="xml_file",
nargs="?",
const="",
default="",
help="This parameter define xml file",
)
parser.add_argument(
"--chip_name",
metavar="chip_name",
required=False,
dest="chip_name",
nargs="?",
const=None,
default=None,
help="This parameter define package chip name, has higher priority than chip name in xml",
)
parser.add_argument(
"--func_name",
metavar="func_name",
required=False,
dest="func_name",
nargs="?",
const=None,
default=None,
help="This parameter define package func name, has higher priority than func name in xml",
)
parser.add_argument(
"--source_root",
metavar="source_root",
required=False,
dest="source_root",
nargs="?",
const="",
help="source root dir.",
)
parser.add_argument(
"--makeself_dir",
metavar="makeself_dir",
required=False,
dest="makeself_dir",
nargs="?",
const="",
help="makeself dir.",
)
parser.add_argument("--independent_pkg", action="store_true", help="Independent pkg.")
parser.add_argument("--pkg-output-dir", default="", help="Package dirpath.")
parser.add_argument("--version_dir", nargs="?", const="", default="", help="Set version dir.")
parser.add_argument("--tag", metavar="tag", nargs="?", const="", default="")
parser.add_argument("--disable-multi-version", action="store_true", help="Disable multi version.")
# 检查打包配置
parser.add_argument("--package-check", action="store_true", help="check package config.")
parser.add_argument("--check_size", nargs="?", const="", default="", help="Check the size of a file or directory.")
parser.add_argument("--pkg-name-style", metavar="pkg_name_style", default="common", help="Package name style.")
return parser.parse_args()
if __name__ == "__main__":
CommLog.cilog_info("%s", " ".join(sys.argv))
args = args_parse()
try:
if args.source_root:
pkg_utils.TOP_SOURCE_DIR = args.source_root
if args.build_type == "":
args.build_type = "debug"
else:
args.build_type = args.build_type.lower()
status = main(args.pkg_name, args.xml_file, main_args=args)
except Exception as e:
CommLog.cilog_error("exception is occurred (%s)!", e)
CommLog.cilog_info("%s", traceback.format_exc())
status = FAIL
sys.exit(status)

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python3
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
import os
import sys
PYF_PATH = os.path.dirname(os.path.realpath(__file__))
sys.path.append(PYF_PATH)

View File

@@ -0,0 +1,779 @@
#!/usr/bin/env python3
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
"""
build_opp_kernel_static.py
"""
import argparse
import concurrent.futures
import contextlib
import glob
import json
import logging as log
import multiprocessing
import os
import platform
import stat
import subprocess
import sys
from collections import defaultdict
from dataclasses import dataclass, field
from pathlib import Path
import regex as re
class Const:
x86 = "x86_64"
arm = "aarch64"
def shell_exec(cmd, shell=False):
try:
ps = subprocess.Popen(cmd, shell)
ps.communicate(timeout=180)
except BaseException as e:
log.error("shell_exec error: %s", e)
sys.exit(1)
def shell_checkout_key_func(symbol_file, key_str):
process = subprocess.Popen(("cat", symbol_file), stdout=subprocess.PIPE)
awk_out = subprocess.check_output(("awk", "{print $8}"), stdin=process.stdout)
process.wait()
cppfilt = subprocess.check_output(("c++filt",), input=awk_out)
if key_str not in cppfilt.decode("utf-8"):
return b""
grep_out = subprocess.check_output(("grep", key_str), input=cppfilt)
return grep_out.decode("utf-8")
def to_upper_camel_case(x) -> str:
"""转大驼峰法命名"""
s = re.sub("_([a-zA-Z])", lambda m: (m.group(1).upper()), x.lower())
return s[0].upper() + s[1:]
def generate_symbol(args):
library_file = args.library_file
symbol_file = args.symbol_file
if not os.path.exists(library_file):
raise FileExistsError(f"generate_symbol input library error, file <{library_file}> not exists.")
process = subprocess.Popen(("readelf", "-Ws", library_file), stdout=subprocess.PIPE)
output = process.communicate(timeout=180)[0].decode("utf-8")
with open(symbol_file, "w") as fd:
fd.write(output)
def parser_generate_symbol(subparsers):
generate_symbol_parser = subparsers.add_parser(name="GenerateSymbol", help="Generate Symbol file of input library")
generate_symbol_parser.add_argument(
"-l", "--library_file", type=str, required=False, dest="library_file", default="", help="Input the library file"
)
generate_symbol_parser.add_argument(
"-s",
"--symbol_file",
type=str,
required=False,
dest="symbol_file",
default="",
help="The symbol file for output",
)
generate_symbol_parser.set_defaults(func=generate_symbol)
class CompileOpStaticLib:
def __init__(self, ops_compile_files: dict, out_path: str, dist_index: int, arch: str):
self.ops_compile_files = ops_compile_files
self.out_path = out_path
self.part_index = dist_index
self.cpu_arch = arch
if self.cpu_arch not in [Const.x86, Const.arm]:
raise Exception(f"CompileOpStaticLib Error, input arch<{arch}> error...")
def compile_link_single(self, file_path, file_o):
(dir_path, file_name) = os.path.split(file_path)
if self.cpu_arch == Const.x86:
shell_exec(
[
"bash",
"-c",
f"cd {dir_path} && "
f"objcopy --input-target binary --output-target elf64-x86-64 "
f"--binary-architecture i386 "
f"{file_name} {file_o}",
],
shell=False,
)
elif self.cpu_arch == Const.arm and platform.machine() != Const.x86:
shell_exec(
[
"bash",
"-c",
f"cd {dir_path} && "
f"objcopy --input-target binary "
f"--output-target elf64-littleaarch64 --binary-architecture aarch64 "
f"{file_name} {file_o}",
],
shell=False,
)
elif self.cpu_arch == Const.arm:
shell_exec(
[
"bash",
"-c",
f"cd {dir_path} && "
f"aarch64-linux-gnu-objcopy --input-target binary "
f"--output-target elf64-littleaarch64 --binary-architecture aarch64 "
f"{file_name} {file_o}",
],
shell=False,
)
def compile_link_o(self, out_path, file_path, is_need_path=True):
file_pre = os.path.basename(file_path).replace(".", "_").replace("-", "_")
path_o_prefix = os.path.join(out_path, f"data_{file_pre}_{self.cpu_arch}.o")
# 向json文件中写入"filePath"参数
if is_need_path and file_path.name.endswith(".json"):
with open(file_path, encoding="UTF-8") as json_fd:
json_dict = json.load(json_fd)
soc = str(file_path).split("/binary/")[-1].split("/bin/")[0]
json_dict["filePath"] = os.path.join(soc, str(file_path).split("/bin/")[-1].split("/kernel/")[-1])
if "opp/built-in/" in str(file_path):
json_dict["filePath"] = (
str(file_path).split("/bin/")[-1].split("/kernel/")[-1].replace("/ops_transformer", "")
)
file_path = os.path.join(out_path, os.path.basename(file_path))
with open(file_path, "w", encoding="UTF-8") as new_json_fd:
new_json_fd.write(json.dumps(json_dict, indent=4))
file_path = os.path.realpath(file_path)
self.compile_link_single(file_path, path_o_prefix)
return
def compile_ops_part_o(self, out_path):
path_data_o = os.path.join(out_path, f"data_*{self.cpu_arch}.o")
path_data_o_list = glob.glob(path_data_o)
if not path_data_o_list:
return
(dir_path, ops_name) = os.path.split(out_path)
file_part_o = f"{ops_name}_{self.cpu_arch}_part{self.part_index}.o" # eg: floor_mod_aarch64_1.a
path_part_o = os.path.join(dir_path, file_part_o)
if self.cpu_arch == Const.x86 or (self.cpu_arch == Const.arm and platform.machine() != Const.x86):
shell_exec(["bash", "-c", f"cd {out_path} && ld -r {path_data_o} -o {path_part_o}"], shell=False)
if self.cpu_arch == Const.arm and platform.machine() == Const.x86:
shell_exec(
["bash", "-c", f"cd {out_path} && aarch64-linux-gnu-ld -r {path_data_o} -o {path_part_o}"], shell=False
)
return
def exec_compile(self):
"""
编译算子静态库
:return:
"""
def get_parallel_num() -> int:
"""
获取多线程最大并发数量
"""
num = multiprocessing.cpu_count() * 2
if num == 0:
num = 16
return num
job_num = get_parallel_num()
for op in self.ops_compile_files:
compile_files = self.ops_compile_files[op].kernel_files
json_files = self.ops_compile_files[op].binary_config_files
runtime_kb_files = self.ops_compile_files[op].runtime_kb_files
op_out_path = os.path.join(self.out_path, op)
if not os.path.exists(op_out_path):
os.makedirs(op_out_path, exist_ok=True)
with concurrent.futures.ThreadPoolExecutor(max_workers=job_num) as executor:
for file in compile_files:
executor.submit(self.compile_link_o, op_out_path, file.resolve())
for file in json_files:
executor.submit(self.compile_link_o, op_out_path, file.resolve(), False)
for file in runtime_kb_files:
executor.submit(self.compile_link_o, op_out_path, file.resolve(), False)
with concurrent.futures.ThreadPoolExecutor(max_workers=job_num) as executor:
executor.submit(self.compile_ops_part_o, op_out_path)
return 0
def compile_static_library(args):
index_num = args.index_num
cpu_aarch = args.cpu_aarch
if cpu_aarch not in [Const.x86, Const.arm]:
raise Exception(f"Input cpu_aarch<{cpu_aarch}> Error, Please input parase.")
ops_compile_files = GenOpResourceIni(args.soc_version, args.build_dir, args.jit).analyze_ops_files()
csl = CompileOpStaticLib(
ops_compile_files, os.path.join(args.build_dir, f"bin_tmp/{args.soc_version}"), index_num, cpu_aarch
)
ret = csl.exec_compile()
return ret
def parser_compile_static_library(subparsers):
"""配置静态编译参数及执行信息"""
compile_lib_parser = subparsers.add_parser(
name="StaticCompile", help="Compile static libraries(.a) on distributed server"
)
compile_lib_parser.add_argument(
"-s",
"--soc_version",
type=str,
required=True,
dest="soc_version",
help="Operator Name, eg: ascend910b, ascend310p",
)
compile_lib_parser.add_argument(
"-b", "--build_dir", type=str, required=True, dest="build_dir", help="Input build dir for this project"
)
compile_lib_parser.add_argument(
"-j", "--jit", action="store_true", dest="jit", help="Compile static libraries(.a) with cann package"
)
compile_lib_parser.add_argument(
"-n", "--index_num", type=int, required=True, dest="index_num", help="Please input distributed compilation idx"
)
compile_lib_parser.add_argument(
"-a", "--cpu_aarch", type=str, required=True, dest="cpu_aarch", help="Please input cpu aarch, eg:x86_64,aarch64"
)
compile_lib_parser.set_defaults(func=compile_static_library)
@dataclass
class OpResource:
"""算子资源"""
# tiling 注册函数
tiling_register: str = field(default=None)
extend_register: str = field(default_factory=list)
# InferShape 注册函数
infer_shape_register: str = field(default=None)
# 知识库注册
tuning_bank_key_register: str = field(default=None)
tuning_bank_parse_register: str = field(default=None)
tuning_tiling_helper: str = field(default=None)
# 二进制配置
binary_config_files: list = field(default_factory=list)
# kernel 编译产出文件
kernel_files: list = field(default_factory=list)
# 知识库文件
runtime_kb_files: list = field(default_factory=list)
class GenOpResourceIni:
def __init__(self, soc_version: str, build_dir: str, build_with_package: bool):
self._soc_version = soc_version
self._build_dir = Path(build_dir)
opp_path = os.environ.get("ASCEND_OPP_PATH")
if build_with_package and opp_path:
opp_path = Path(opp_path)
self._binary_path = opp_path / "built-in/op_impl/ai_core/tbe/kernel"
self._tuning_basic_path = opp_path / "built-in/data/op"
ops_info = opp_path / "built-in/op_impl/ai_core/tbe/config" / self._soc_version
ops_info = list(ops_info.glob(f"aic-{self._soc_version}-ops-info-transformer.json"))
self._ops_info = ops_info[0] if len(ops_info) != 0 else None
else:
self._binary_path = self._build_dir / "binary" / self._soc_version / "bin"
self._tuning_basic_path = self._build_dir / "tbe/config" / self._soc_version
# transformer aic*.json 适配
ops_info = self._build_dir / "custom/op_impl/ai_core/tbe/config" / self._soc_version
ops_info = list(ops_info.glob(f"aic-{self._soc_version}-ops-info*.json"))
self._ops_info = ops_info[0] if len(ops_info) != 0 else None
self._op_resource_path = self._build_dir / "autogen" / self._soc_version / "aclnnop_resource"
self._op_res: dict[str, OpResource] = defaultdict(OpResource)
self._l0op_list = []
TILING_REG_DECL_FMT = """
namespace {namespace} {{
extern gert::OpImplRegisterV2 {func_name};
}}
"""
EXTEND_REG_DECL_FMT = """
namespace {namespace} {{
extern uint32_t {func_name};
}}
"""
TILING_REG_RES_FUNC_FMT = """
void * {op_type}TilingRegisterResource() {{
return {reference_code};
}}
"""
INFER_SHAPE_REG_DECL_FMT = """
namespace {namespace} {{
extern gert::OpImplRegisterV2 {func_name};
}}
"""
INFER_SHAPE_REG_RES_FUNC_FMT = """
void * {op_type}InferShapeRegisterResource() {{
return {reference_code};
}}
"""
TUNING_REG_DECL_FMT = """
namespace {namespace} {{
class {class_type};
extern {class_type} {func_name};
}}
"""
EXTLEND_REG_RES_FUNC_FMT = """
void * {op_type}ExtendRegisterResource() {{
static std::vector<void *> resource = {{{reference_code}}};
return &resource;
}}
"""
TUNING_REG_RES_FUNC_FMT = """
void * {op_type}TuningRegisterResource() {{
static std::vector<void *> resource = {{{tuning_bank_key}, {tuning_bank_parse}, {tuning_helper}}};
return &resource;
}}
"""
KERNEL_BINARY_RES_FUNC_FMT = """
const OP_BINARY_RES& {op_type}KernelResource() {{
static const OP_BINARY_RES resource = {{
{binary_config_ref_code}
{kernel_files_ref_code}
}};
return resource;
}}
"""
TUNING_KB_BINARY_RES_FUNC_FMT = """
const OP_RUNTIME_KB_RES& {op_type}TuningResource() {{
static const OP_RUNTIME_KB_RES resource = {{
{reference_code}
}};
return resource;
}}
"""
OP_RESOURCE_CPP_FMT = """/******************{op_type}算子的所有资源**********************/
#include "register/op_impl_registry.h"
#include <vector>
#include <tuple>
#include <map>
#include <graph/ascend_string.h>
#include <static_space.h>
using OP_HOST_FUNC_HANDLE = std::vector<void *>;
using OP_RES = std::tuple<const uint8_t *, const uint8_t *>;
using OP_BINARY_RES = std::vector<OP_RES>;
using OP_RUNTIME_KB_RES = std::vector<OP_RES>;
using OP_RESOURCES = std::map<ge::AscendString,
std::tuple<OP_HOST_FUNC_HANDLE, OP_BINARY_RES, OP_RUNTIME_KB_RES>>;
namespace {op_type} {{
auto initializer = StaticSpaceInitializer::GetInstance();;
}}
// 资源声明
// extend resource
{extend_declaration}
// Tiling
{tiling_declaration}
// InferShape
{infer_shape_declaration}
// Tuning
{tuning_bank_key_declaration}
{tuning_bank_parse_declaration}
{tuning_helper_declaration}
// kernel 二进制
{binary_config_declaration}
{kernel_files_declaration}
// kb 二进制
{tuning_kb_declaration}
namespace l0op {{
// 资源函数
// Tiling register resource func
{tiling_reg_func}
// InferShape register resource func
{infer_shape_reg_func}
// Tuning register resource func
{tuning_reg_func}
// kernel resource func
{kernel_resource}
// Tuning resource func
{tuning_kb_resource}
}}
// extend resource func
{extend_reg_func}
"""
@staticmethod
def _extract_op_symbol_pair(symbol_file: str, search_key: str, prefix: str, suffix: str):
symbol_ret = shell_checkout_key_func(symbol_file, search_key)
for symbol in symbol_ret.splitlines():
symbol_name = symbol.split("::")[-1]
if not (symbol_name.startswith(prefix) and symbol_name.endswith(suffix)):
log.warning("symbol not satisfied with the format:%s<op_type>%s, skip", prefix, suffix)
continue
op_type = symbol_name
if prefix:
op_type = op_type[len(prefix) :]
if suffix:
op_type = op_type[: -len(suffix)]
yield op_type, symbol
@staticmethod
def _extract_op_symbol_pair_v2(symbol_file: str, search_key: str, prefix: str):
symbol_ret = shell_checkout_key_func(symbol_file, search_key)
for symbol in symbol_ret.splitlines():
symbol_name = symbol.split("::")[-1]
if not (symbol_name.startswith(prefix)):
log.warning("symbol not satisfied with the format:%s, skip", prefix)
continue
op_type = symbol_name
if prefix:
op_type = op_type[len(prefix) :]
op_type = op_type.split("_")[0]
yield op_type, symbol
@staticmethod
def _extract_register_symbol(register_symbol: str):
if not register_symbol:
return "", "", "nullptr"
symbol_data = register_symbol.split("::")
namespace = "::".join(symbol_data[:-1])
if "anonymous" in namespace:
return "", "", "nullptr"
func_name = symbol_data[-1]
reference_code = f"&{register_symbol}"
return namespace, func_name, reference_code
@staticmethod
def _gen_binary_res_code(files):
declaration = ""
reference_code = ""
for binary_file in files:
# static not support supperkernel
if "relocatable" in binary_file.name:
continue
binary_name = binary_file.name.replace(".", "_").replace("-", "_")
declaration += f"""// {binary_file.name}
extern const uint8_t _binary_{binary_name}_start[];
extern const uint8_t _binary_{binary_name}_end[];
"""
reference_code += f"{{_binary_{binary_name}_start, _binary_{binary_name}_end}},\n"
return declaration, reference_code
def gen_ops_ini_files(self):
self.analyze_ops_files()
self._analyze_symbols()
self._analyze_ops_l0op()
if not os.path.exists(self._op_resource_path):
os.makedirs(self._op_resource_path)
for op_type in self._l0op_list:
ini_content = self.generate_op_resouce_ini(op_type)
self._save_op_resource(op_type, ini_content)
for op_type in self._op_res:
if op_type in self._l0op_list:
continue
ini_content = self.generate_op_resouce_ini(op_type)
self._save_op_resource(op_type, ini_content)
def generate_op_resouce_ini(self, op_type: str) -> str:
value_dict = {
"op_type": op_type,
}
value_dict.update(self._gen_register_resouce_code(op_type))
value_dict.update(self._gen_tuning_register_resouce_code(op_type))
value_dict.update(self._gen_binary_resource_code(op_type))
# 处理特殊的共用算子kernel资源的算子
sepical_ops = {"MatMulV2": "MatMul"}
if op_type in sepical_ops:
value_dict["kernel_files_declaration"] = ""
value_dict["kernel_resource"] = f"""
extern const OP_BINARY_RES& {sepical_ops[op_type]}KernelResource();
const OP_BINARY_RES& {op_type}KernelResource() {{
return {sepical_ops[op_type]}KernelResource();
}}
"""
return self.OP_RESOURCE_CPP_FMT.format_map(value_dict)
def analyze_ops_files(self):
if not self._ops_info:
return self._op_res
with open(self._ops_info) as autogen_fd:
ops_info_json = json.load(autogen_fd)
for ops in ops_info_json:
if "opFile" in ops_info_json[ops]:
json_file = f"{ops_info_json[ops]['opFile']['value']}.json"
else:
o_lists = list(Path(self._binary_path).rglob(f"{self._soc_version}/**/*{ops}*.o"))
if len(o_lists) == 0:
continue
else:
json_file = f"{os.path.basename(os.path.dirname(o_lists[0]))}.json"
# json_path = self._binary_path / "config" / self._soc_version / json_file
json_path = self._binary_path / json_file
if "opp/built-in/" in str(self._binary_path):
json_path = self._binary_path / "config" / self._soc_version / "ops_transformer" / json_file
if not os.path.exists(json_path):
continue
with open(json_path) as op_json_fd:
op_json_content = json.load(op_json_fd)
if "binList" not in op_json_content or len(op_json_content["binList"]) == 0:
continue
# 算子.json内 kernel json路径适配
bin_json_file = (
self._binary_path / op_json_content["binList"][0]["binInfo"]["jsonFilePath"].split("/", 1)[1]
)
if "opp/built-in/" in str(self._binary_path):
bin_json_file = (
self._binary_path
/ self._soc_version
/ "ops_transformer"
/ op_json_content["binList"][0]["binInfo"]["jsonFilePath"].split("/", 1)[1]
)
ops_path = os.path.dirname(bin_json_file)
self._op_res[ops].binary_config_files.append(json_path)
self._op_res[ops].kernel_files.extend(sorted(Path(ops_path).iterdir()))
for kb_json in list(Path(self._tuning_basic_path).rglob("*_AiCore_*_runtime_kb.json")):
ops = kb_json.name.split("_AiCore_")[-1].split("_runtime_kb")[0]
self._op_res[ops].runtime_kb_files.append(kb_json)
self._op_res[ops].runtime_kb_files.sort(key=lambda p: p.name)
return self._op_res
def _analyze_ops_l0op(self):
opapi_symbol = self._build_dir / "opapi_transformer.txt"
if not os.path.exists(opapi_symbol):
return
# infershape
for op_type, _ in self._extract_op_symbol_pair(opapi_symbol, "_kernelName_Be_Defined_Multi_Times__", "", ""):
self._l0op_list.append(op_type.split("_kernelName_")[0])
self._l0op_list.sort()
def _save_op_resource(self, op_type, res_content):
res_cpp_file = self._op_resource_path / f"{op_type}_op_resource.cpp"
with contextlib.suppress(FileNotFoundError):
res_cpp_file.unlink()
flags = os.O_WRONLY | os.O_CREAT
modes = stat.S_IWUSR | stat.S_IRUSR
with os.fdopen(os.open(res_cpp_file, flags, modes), "w") as fd:
fd.write(res_content)
def _analyze_symbols(self):
# ophost txt 适配
ophost_symbol = self._build_dir / "ophost_transformer.txt"
if not os.path.exists(ophost_symbol):
return
# infershape
for op_type, symbol in self._extract_op_symbol_pair(
ophost_symbol, "op_impl_register_infershape_", "op_impl_register_infershape_", ""
):
self._op_res[op_type].infer_shape_register = symbol
# tiling
for op_type, symbol in self._extract_op_symbol_pair(
ophost_symbol, "op_impl_register_optiling_", "op_impl_register_optiling_", ""
):
self._op_res[op_type].tiling_register = symbol
for op_type, symbol in self._extract_op_symbol_pair_v2(
ophost_symbol, "op_impl_register_template_", "op_impl_register_template_"
):
self._op_res[op_type].extend_register.append(symbol)
# 知识库
for op_type, symbol in self._extract_op_symbol_pair(
ophost_symbol, "BankKeyRegistryInterf", "g_", "BankKeyRegistryInterf"
):
self._op_res[op_type].tuning_bank_key_register = symbol
for op_type, symbol in self._extract_op_symbol_pair(ophost_symbol, "BankParseInterf", "g_", "BankParseInterf"):
self._op_res[op_type].tuning_bank_parse_register = symbol
for op_type, symbol in self._extract_op_symbol_pair(
ophost_symbol, "g_tuning_tiling_", "g_tuning_tiling_", "Helper"
):
self._op_res[op_type].tuning_tiling_helper = symbol
def _gen_register_resouce_code(self, op_type: str):
"""注册函数"""
# Tiling
namespace, func_name, reference_code = self._extract_register_symbol(self._op_res[op_type].tiling_register)
symbol_map = {
"op_type": op_type,
"namespace": namespace,
"func_name": func_name,
"reference_code": reference_code,
}
tiling_declaration = self.TILING_REG_DECL_FMT.format_map(symbol_map) if func_name else ""
tiling_reg_func = self.TILING_REG_RES_FUNC_FMT.format_map(symbol_map) if func_name else ""
reference_code_list = []
extend_declaration = ""
for symbol in self._op_res[op_type].extend_register:
namespace, func_name, reference_code = self._extract_register_symbol(symbol)
if func_name:
extend_declaration += self.EXTEND_REG_DECL_FMT.format(namespace=namespace, func_name=func_name)
reference_code_list.append(reference_code)
reference_code = ", ".join(reference_code_list)
extend_reg_func = self.EXTLEND_REG_RES_FUNC_FMT.format(op_type=op_type, reference_code=reference_code)
# InferShape
namespace, func_name, reference_code = self._extract_register_symbol(self._op_res[op_type].infer_shape_register)
symbol_map = {
"op_type": op_type,
"namespace": namespace,
"func_name": func_name,
"reference_code": reference_code,
}
infer_shape_declaration = self.INFER_SHAPE_REG_DECL_FMT.format_map(symbol_map) if func_name else ""
infer_shape_reg_func = self.INFER_SHAPE_REG_RES_FUNC_FMT.format_map(symbol_map) if func_name else ""
return {
"tiling_declaration": tiling_declaration,
"infer_shape_declaration": infer_shape_declaration,
"tiling_reg_func": tiling_reg_func,
"infer_shape_reg_func": infer_shape_reg_func,
"extend_reg_func": extend_reg_func,
"extend_declaration": extend_declaration,
}
def _gen_tuning_register_resouce_code(self, op_type: str):
"""知识库注册函数"""
# Tuning
namespace, func_name, tuning_bank_key_ref_code = self._extract_register_symbol(
self._op_res[op_type].tuning_bank_key_register
)
tuning_bank_key_declaration = (
self.TUNING_REG_DECL_FMT.format(
namespace=namespace,
class_type="OpBankKeyFuncRegistryV2",
func_name=func_name,
)
if func_name
else ""
)
namespace, func_name, tuning_bank_parse_ref_code = self._extract_register_symbol(
self._op_res[op_type].tuning_bank_parse_register
)
tuning_bank_parse_declaration = (
self.TUNING_REG_DECL_FMT.format(
namespace=namespace,
class_type="OpBankKeyFuncRegistryV2",
func_name=func_name,
)
if func_name
else ""
)
namespace, func_name, tuning_helper_ref_code = self._extract_register_symbol(
self._op_res[op_type].tuning_tiling_helper
)
tuning_helper_declaration = (
self.TUNING_REG_DECL_FMT.format(
namespace=namespace,
class_type=f"{op_type}ClassHelper",
func_name=func_name,
)
if func_name
else ""
)
tuning_reg_func = self.TUNING_REG_RES_FUNC_FMT.format(
op_type=op_type,
tuning_bank_key=tuning_bank_key_ref_code,
tuning_bank_parse=tuning_bank_parse_ref_code,
tuning_helper=tuning_helper_ref_code,
)
return {
"tuning_bank_key_declaration": tuning_bank_key_declaration,
"tuning_bank_parse_declaration": tuning_bank_parse_declaration,
"tuning_helper_declaration": tuning_helper_declaration,
"tuning_reg_func": tuning_reg_func,
}
def _gen_binary_resource_code(self, op_type: str) -> str:
"""二进制"""
# kernel
binary_config_declaration, binary_config_ref_code = self._gen_binary_res_code(
self._op_res[op_type].binary_config_files
)
kernel_files_declaration, kernel_files_ref_code = self._gen_binary_res_code(self._op_res[op_type].kernel_files)
kernel_resource = (
self.KERNEL_BINARY_RES_FUNC_FMT.format(
op_type=op_type,
binary_config_ref_code=binary_config_ref_code,
kernel_files_ref_code=kernel_files_ref_code,
)
if kernel_files_ref_code
else ""
)
# 知识库
tuning_kb_declaration, tuning_kb_ref_code = self._gen_binary_res_code(self._op_res[op_type].runtime_kb_files)
tuning_kb_resource = self.TUNING_KB_BINARY_RES_FUNC_FMT.format(
op_type=op_type,
reference_code=tuning_kb_ref_code,
)
return {
"binary_config_declaration": binary_config_declaration,
"kernel_files_declaration": kernel_files_declaration,
"tuning_kb_declaration": tuning_kb_declaration,
"kernel_resource": kernel_resource,
"tuning_kb_resource": tuning_kb_resource,
}
def generate_op_resource_h_file(args):
soc_version: str = args.soc_version
build_dir = args.build_dir
gen_ini = GenOpResourceIni(soc_version, build_dir, args.jit)
gen_ini.gen_ops_ini_files()
return
def parser_generate_op_resource_h_file(subparsers):
gen_resource_ini_parser = subparsers.add_parser(
name="GenStaticOpResourceIni", help="Generate xxx_op_resource.h on consolidation server"
)
gen_resource_ini_parser.add_argument(
"-s",
"--soc_version",
type=str,
required=True,
dest="soc_version",
help="Operator Name, eg: ascend910b, ascend310p",
)
gen_resource_ini_parser.add_argument(
"-b", "--build_dir", type=str, required=True, dest="build_dir", help="Input build dir for this project"
)
gen_resource_ini_parser.add_argument(
"-j", "--jit", action="store_true", dest="jit", help="Generate xxx_op_resource.h with cann package"
)
gen_resource_ini_parser.set_defaults(func=generate_op_resource_h_file)
def execute_argus_parse_func():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help="Subparsers Commands")
""" 配置静态编译参数及执行信息 """
parser_compile_static_library(subparsers)
""" 配置头文件生成功能参数及执行信息 """
parser_generate_op_resource_h_file(subparsers)
""" 生成指定库的symbol文件 """
parser_generate_symbol(subparsers)
""" 执行函数功能 """
args = parser.parse_args()
args.func(args)
if __name__ == "__main__":
execute_argus_parse_func()
exit(0)

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env python3
# ----------------------------------------------------------------------------
# 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.
# ----------------------------------------------------------------------------
"""
Function:
The replay function entry
Copyright Information:
Huawei Technologies Co., Ltd. All Rights Reserved © 2020
"""
import os
import stat
REPLAY_BATCH = "batch"
REPLAY_ITERATE = "iterate"
CFG_IMPL_DIR = "impl_dir"
CFG_OUT_DIR = "out_dir"
AUTO_GEN_DIR = "auto_gen_dir"
WFLAGS = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
WMODES = stat.S_IWUSR | stat.S_IRUSR
SOC_MAP_EXT = {
"ascend310p": "Ascend310P3",
"ascend310b": "Ascend310B1",
"ascend910": "Ascend910A",
"ascend910b": "Ascend910B1",
"ascend910_93": "Ascend910_9391",
"ascend950": "Ascend950",
"kirinx90": "KirinX90",
}
BIN_CMD = "asc_opc $1 --main_func={fun} --input_param={param} --soc_version={soc} \
--output=$2 --impl_mode={impl} --simplified_key_mode=0 --op_mode=dynamic\n"
SET_PLOG_LEVEL_ERROR = "export ASCEND_GLOBAL_LOG_LEVEL=3\n"
SET_PLOG_STDOUT = "export ASCEND_SLOG_PRINT_TO_STDOUT=1\n"
SRC_ENV = """
while true; do
case "$1" in
--kernel-src=*)
export BUILD_KERNEL_SRC=$(echo "$1" | cut -d"=" -f2-)
shift
;;
-*)
shift
;;
*)
break
;;
esac
done
"""
CHK_CMD = """
if ! test -f $2/{res_file} ; then
echo "$2/{res_file} not generated!"
exit 1
fi
"""
ATTR_DEF_VAL = {
"str": "",
"int": 0,
"float": 0.0,
"bool": False,
"list_bool": [],
"list_int": [],
"list_float": [],
"list_list_int": [[]],
}
def conv_soc_ver(ver: str):
return SOC_MAP_EXT.get(ver)

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env python3
# ----------------------------------------------------------------------------
# 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.
# ----------------------------------------------------------------------------
import json
import os
import sys
import const_var
if __name__ == "__main__":
if len(sys.argv) != 3:
print(sys.argv)
print("argv error, inert_op_info.py your_op_file lib_op_file")
sys.exit(2)
with open(sys.argv[1]) as load_f:
insert_operator = json.load(load_f)
all_operators = {}
if os.path.exists(sys.argv[2]):
if os.path.getsize(sys.argv[2]) != 0:
with open(sys.argv[2]) as load_f:
all_operators = json.load(load_f)
for k in insert_operator:
if k in all_operators:
print("replace op:[", k, "] success")
else:
print("insert op:[", k, "] success")
all_operators[k] = insert_operator[k]
with os.fdopen(os.open(sys.argv[2], const_var.WFLAGS, const_var.WMODES), "w") as json_file:
json_file.write(json.dumps(all_operators, indent=4))

View File

@@ -0,0 +1,37 @@
#!/bin/bash
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
echo "$@"
top_dir=$1
output_json=$2
first_json=$3
shift 3
merge_json_tool="${top_dir}/scripts/util/insert_op_info.py"
>$output_json
if [[ -f "$first_json" ]]
then
cp -f $first_json $output_json
else
echo "[ERROR] ${first_json} is not a file"
exit 1
fi
for single_json in "$@"
do
if [[ -f "${single_json}" ]]
then
python3 ${top_dir}/scripts/util/insert_op_info.py ${single_json} ${output_json}
else
echo "[ERROR] ${single_json} is not a file"
fi
done

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env python3
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
import argparse
import os
import sys
import regex as re
def match_op_proto(file_path):
with open(file_path, encoding="utf-8") as f:
content = f.read()
op_def_pattern = re.compile(r"REG_OP\((.+)\).*OP_END_FACTORY_REG\(\1\)", re.DOTALL)
match = op_def_pattern.search(content)
if match:
op_name = match.group(1)
op_def = match.group(0)
return op_name, op_def
else:
return None, None
def merge_op_proto(protos_path, output_file):
op_defs = []
for proto_path in protos_path:
if not proto_path.endswith("_proto.h"):
continue
print(f"proto_path: {proto_path}")
op_name, op_def = match_op_proto(proto_path)
if op_def:
op_defs.append(op_def)
# merge op_proto
merged_content = f"""#ifndef OP_TRANSFORMER_PROTO_H_
#define OP_TRANSFORMER_PROTO_H_
#include "graph/operator_reg.h"
#include "register/op_impl_registry.h"
namespace ge{{
{os.linesep.join([f"{op_def}{os.linesep}" for op_def in op_defs])}
}} // namespace ge
#endif // OP_TRANSFORMER_PROTO_H_
"""
with open(output_file, "w", encoding="utf-8") as f:
f.write(merged_content)
print(f"merged op transformer proto file: {output_file}")
def parse_args(argv):
parser = argparse.ArgumentParser()
parser.add_argument("protos", nargs="+")
parser.add_argument("--output-file", nargs=1, default=None)
return parser.parse_args(argv)
if __name__ == "__main__":
args = parse_args(sys.argv)
protos_path = args.protos[1:]
output_file = args.output_file[0]
merge_op_proto(protos_path, output_file)

View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python3
# -----------------------------------------------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------------------------------------------
import logging as log
import os
import subprocess
import sys
from pathlib import Path
def shell_exec(cmd, shell=False):
try:
ps = subprocess.Popen(cmd, shell)
ps.communicate(timeout=180)
except BaseException as e:
log.error("shell_exec error: %s", e)
sys.exit(1)
def search_file(aclnn_cpp):
op_type = None
index = 0
with open(aclnn_cpp) as f:
for line in f.readlines():
index = index + 1
if "_op_resource.h" in line:
op_type = line.replace('_op_resource.h"', "").replace('#include "', "").strip()
if "EXTERN_OP_RESOURCE" in line or "namespace op {" in line:
break
return (op_type, index)
def modify_gen_aclnn(build_path):
auto_gen_cpps = Path(os.path.join(build_path, "autogen")).rglob("aclnn*.cpp")
for aclnn_cpp in auto_gen_cpps:
(op_type, index) = search_file(aclnn_cpp)
if op_type:
shell_exec(
["bash", "-c", f"""sed -i 's/{op_type}_op_resource.h/op_resource.h/g' {aclnn_cpp}"""], shell=False
)
shell_exec(
["bash", "-c", f"""sed -i 's/{op_type}_RESOURCES/AUTO_GEN_OP_RESOURCE({op_type})/g' {aclnn_cpp}"""],
shell=False,
)
shell_exec(["bash", "-c", f"sed -i '{index}i\\EXTERN_OP_RESOURCE({op_type})' {aclnn_cpp}"], shell=False)
return
if __name__ == "__main__":
modify_gen_aclnn(sys.argv[1])