#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
NC="\033[0m"
RED="\033[0;31m"
GREEN="\033[0;32m"
YELLOW="\033[0;33m"
BLUE="\033[0;34m"
ERROR="${RED}[ERROR]"
INFO="${GREEN}[INFO]"
WARN="${YELLOW}[WARN]"
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
CMAKE_SOURCE_DIR=$(realpath "$SCRIPT_DIR/..")
BUILD_DIR="$CMAKE_SOURCE_DIR/build"
OUTPUT_DIR="$CMAKE_SOURCE_DIR/output"
MODE=""
TARGET_NAME=""
CMAKE_BUILD_TYPE="Release"
declare -a CMAKE_OPTIONS=()
CLEAN=false
POST_BUILD_INFO=""
echo -e " _ _______ _____ ____ ____ "
echo -e " / \|_ _\ \ / / _ \/ ___/ ___| "
echo -e " / _ \ | | \ \ / / | | \___ \___ \ "
echo -e " / ___ \| | \ V /| |_| |___) |__) |"
echo -e " /_/ \_\_| \_/ \___/|____/____/ "
function show_help() {
echo -e "${GREEN}Usage:${NC} $0 [options] [--host_ut|--example|--st] [target_name]"
echo -e "\n${BLUE}Options:${NC}"
echo " --clean Clean build directories"
echo " -DSOC NPU arch. Only supports ascend950."
echo " -D<option> Additional CMake options"
echo -e "\n${BLUE}Modes (mutually exclusive):${NC}"
echo " --host_ut [name] Build unit test(s) in host/ (default: host_ut)"
echo " --example [name] Build example(s) (default: atvoss_examples)"
echo " --st [name] Build system test (default: st)"
echo -e "\n${BLUE}Legacy mode:${NC}"
echo " $0 <target> Directly build CMake target (e.g., abs, host_ut)"
}
if [[ $# -eq 0 ]] || [[ "$1" = "-h" ]] || [[ "$1" = "--help" ]]; then
show_help
exit 0
fi
if [[ ! -v ASCEND_HOME_PATH ]]; then
echo -e "${ERROR}ASCEND_HOME_PATH environment variable is not set!${NC}"
echo -e "${ERROR}Please set ASCEND_HOME_PATH before running this script.${NC}"
exit 1
fi
while [[ $# -gt 0 ]]; do
case "$1" in
--clean)
CLEAN=true
shift
;;
-D*)
CMAKE_OPTIONS+=("$1")
shift
;;
--host_ut|--example|--st)
if [[ -n "$MODE" ]]; then
echo -e "${ERROR}Error: Only one mode (--host_ut/--example/--st) allowed.${NC}" >&2
exit 1
fi
MODE="${1#--}"
shift
if [[ $# -gt 0 && "$1" != -* ]]; then
TARGET_NAME="$1"
shift
fi
;;
-*)
echo -e "${ERROR}Unknown option: $1${NC}" >&2
show_help
exit 1
;;
*)
if [[ -n "$MODE" ]]; then
echo -e "${ERROR}Cannot mix mode and direct target.${NC}" >&2
exit 1
fi
TARGET_NAME="$1"
MODE="legacy"
shift
;;
esac
done
if [[ "$CLEAN" == true ]]; then
echo -e "${INFO}Cleaning build directories...\c"
rm -rf "$BUILD_DIR" "$OUTPUT_DIR"
echo -e "Complete!${NC}"
exit 0
fi
if [[ -z "$MODE" ]]; then
echo -e "${ERROR}No mode or target specified.${NC}" >&2
show_help
exit 1
fi
CMAKE_TARGET=""
case "$MODE" in
host_ut)
CMAKE_TARGET=${TARGET_NAME:-host_ut}
;;
example)
CMAKE_TARGET=${TARGET_NAME:-atvoss_examples}
;;
st)
CMAKE_TARGET=${TARGET_NAME:-st}
;;
legacy)
CMAKE_TARGET="$TARGET_NAME"
;;
esac
mkdir -p "$BUILD_DIR" "$OUTPUT_DIR"
if [[ ! -f "$BUILD_DIR/CMakeCache.txt" ]]; then
echo -e "${INFO}Configuring project...${NC}"
if [[ "$CMAKE_TARGET" == "abs" ]] || [[ "$CMAKE_TARGET" == "atvoss_examples" ]]; then
cmake -S "$CMAKE_SOURCE_DIR" -B "$BUILD_DIR" \
-DCMAKE_BUILD_TYPE="$CMAKE_BUILD_TYPE" \
-DCMAKE_INSTALL_PREFIX="$OUTPUT_DIR" \
-DCOMPILE_DYNAMIC_OPTIMIZED_MATMUL=ON \
"${CMAKE_OPTIONS[@]}"
else
cmake -S "$CMAKE_SOURCE_DIR" -B "$BUILD_DIR" \
-DCMAKE_BUILD_TYPE="$CMAKE_BUILD_TYPE" \
-DCMAKE_INSTALL_PREFIX="$OUTPUT_DIR" \
"${CMAKE_OPTIONS[@]}"
fi
fi
echo -e "${INFO}Building target: $CMAKE_TARGET (${MODE}${TARGET_NAME:+: $TARGET_NAME})...${NC}"
if ! cmake --build "$BUILD_DIR" --target "$CMAKE_TARGET" -j; then
echo "构建失败,终止。"
exit 1
fi
if ! cmake --install "$BUILD_DIR" --component "$CMAKE_TARGET"; then
echo "构建失败,终止。"
exit 1
fi
POST_BUILD_INFO="${INFO}Target '$CMAKE_TARGET' built successfully.${NC}"
if [[ "$MODE" == "host_ut" && -n "$TARGET_NAME" ]]; then
UT_EXECUTABLE="$BUILD_DIR/tests/ut/host/$TARGET_NAME"
if [[ -x "$UT_EXECUTABLE" ]]; then
echo -e "\n${INFO}Running unit test: $TARGET_NAME${NC}"
$UT_EXECUTABLE
fi
fi
echo -e "\n$POST_BUILD_INFO"
if [[ "$TARGET_NAME" == "atvoss_examples" ]]; then
ST_TEST_LIST=(
"abs"
"muls"
"rms_norm"
)
for test_name in "${ST_TEST_LIST[@]}"; do
echo "Running system test: $test_name"
UT_EXECUTABLE="$CMAKE_SOURCE_DIR/output/bin/$test_name"
if [[ ! -f "$UT_EXECUTABLE" || ! -x "$UT_EXECUTABLE" ]]; then
echo "Error: $UT_EXECUTABLE not found or not executable."
exit 1
fi
SCRIPT_FILE="${test_name}.sh"
cat > "$SCRIPT_FILE" <<EOF
$UT_EXECUTABLE --shape=32
EOF
chmod +x "$SCRIPT_FILE"
cannsim record ./$SCRIPT_FILE -s Ascend950 --gen-report
cat ./cannsim*${test_name}*/cannsim.log
if grep -r "Accuracy verification passed" ./cannsim*${test_name}*; then
echo "$test_name passed."
else
echo "$test_name failed: 'Accuracy verification passed' not found."
exit 1
fi
done
echo "All system tests passed!"
fi
if [[ "$MODE" == "st" && ! -n "$TARGET_NAME" ]]; then
ST_TEST_LIST=(
"test_block_cast12"
"test_tile_rms_norm_14"
"test_compute_buffer_reuse"
)
for test_name in "${ST_TEST_LIST[@]}"; do
echo "Running system test: $test_name"
UT_EXECUTABLE="$CMAKE_SOURCE_DIR/output/bin/$test_name"
if [[ ! -f "$UT_EXECUTABLE" || ! -x "$UT_EXECUTABLE" ]]; then
echo "Error: $UT_EXECUTABLE not found or not executable."
exit 1
fi
SCRIPT_FILE="${test_name}.sh"
cat > "$SCRIPT_FILE" <<EOF
$UT_EXECUTABLE
EOF
chmod +x "$SCRIPT_FILE"
cannsim record ./$SCRIPT_FILE -s Ascend950 --gen-report
if grep -r "Accuracy verification passed" ./cannsim*${test_name}*; then
echo "$test_name passed."
else
echo "$test_name failed: 'Accuracy verification passed' not found."
exit 1
fi
done
echo "All system tests passed!"
fi