You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
8.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env bash
set -euo pipefail
# ============================================================
# 比赛平台提交脚本
# 将 nudt-compiler-cpp 的优化代码同步到 warning 仓库,
# 自动处理平台兼容性修复,然后提交并推送
# ============================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
NUDT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
WARNING_DIR="/home/lzk/warning"
# 死代码文件(平台 flat 编译会报错)
DEAD_FILES=(
"src/mir/LinearScanAlloc.cpp"
"src/mir/GreedyAlloc.cpp"
"src/mir/InstLiveness.cpp"
)
usage() {
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " -n, --dry-run 仅显示将要做的操作,不实际执行"
echo " -s, --skip-build 跳过本地构建验证"
echo " -p, --push 同步后直接推送(需要密码)"
echo " -m, --msg MSG 自定义 commit message默认自动生成"
echo " -h, --help 显示帮助"
echo ""
echo "工作流程: 同步 src → 删死代码 → 修复头文件 → 提交 → [推送]"
exit 0
}
DRY_RUN=false
SKIP_BUILD=false
DO_PUSH=false
CUSTOM_MSG=""
while [[ $# -gt 0 ]]; do
case "$1" in
-n|--dry-run) DRY_RUN=true; shift ;;
-s|--skip-build) SKIP_BUILD=true; shift ;;
-p|--push) DO_PUSH=true; shift ;;
-m|--msg) CUSTOM_MSG="$2"; shift 2 ;;
-h|--help) usage ;;
*) echo -e "${RED}未知选项: $1${NC}"; usage ;;
esac
done
# ============================================================
# 前置检查
# ============================================================
echo -e "${GREEN}=== 提交前检查 ===${NC}"
if [[ ! -d "$WARNING_DIR/.git" ]]; then
echo -e "${RED}错误: warning 仓库不存在: $WARNING_DIR${NC}"
exit 1
fi
# 检查 warning 仓库是否干净
if ! git -C "$WARNING_DIR" diff-index --quiet HEAD -- 2>/dev/null; then
echo -e "${YELLOW}警告: warning 仓库有未提交改动${NC}"
git -C "$WARNING_DIR" status --short
echo ""
read -rp "继续?(未提交改动将被覆盖)[y/N] " yn
if [[ "$yn" != "y" && "$yn" != "Y" ]]; then
echo "已取消"
exit 0
fi
fi
# 检查 nudt 的 src/ 是否有未提交改动(核心代码)
if ! git -C "$NUDT_DIR" diff --quiet HEAD -- src/ 2>/dev/null; then
echo -e "${YELLOW}警告: nudt/src/ 有未提交改动${NC}"
git -C "$NUDT_DIR" diff --stat HEAD -- src/
echo ""
read -rp "继续?(确认改动已保存)[y/N] " yn
if [[ "$yn" != "y" && "$yn" != "Y" ]]; then
echo "已取消"
exit 0
fi
fi
# ============================================================
# 第1步同步源码
# ============================================================
step1_sync() {
echo -e "${GREEN}=== 第1步: 同步源码到 warning ===${NC}"
if $DRY_RUN; then
echo " [dry-run] rm -rf $WARNING_DIR/src/"
echo " [dry-run] cp -r $NUDT_DIR/src $WARNING_DIR/"
return
fi
rm -rf "$WARNING_DIR/src/"
cp -r "$NUDT_DIR/src" "$WARNING_DIR/"
# 同步 .gitignore包含 T2025* 排除)
cp "$NUDT_DIR/.gitignore" "$WARNING_DIR/.gitignore"
echo " 源码已同步"
}
# ============================================================
# 第2步删除死代码
# ============================================================
step2_deadcode() {
echo -e "${GREEN}=== 第2步: 删除死代码文件 ===${NC}"
for f in "${DEAD_FILES[@]}"; do
local path="$WARNING_DIR/$f"
if [[ -f "$path" ]]; then
if $DRY_RUN; then
echo " [dry-run] rm $path"
else
rm "$path"
echo " 已删除: $f"
fi
else
echo " 跳过(不存在): $f"
fi
done
}
# ============================================================
# 第3步修复头文件路径
# ============================================================
step3_headers() {
echo -e "${GREEN}=== 第3步: 修复头文件路径 ===${NC}"
local old_dom="$WARNING_DIR/src/ir/analysis/DominatorTree.h"
local new_dom="$WARNING_DIR/src/include/ir/analysis/DominatorTree.h"
if [[ -f "$old_dom" ]]; then
if $DRY_RUN; then
echo " [dry-run] mv $old_dom$new_dom"
else
mkdir -p "$(dirname "$new_dom")"
cp "$old_dom" "$new_dom"
rm "$old_dom"
echo " 已移动 DominatorTree.h → src/include/ir/analysis/"
fi
elif [[ -f "$new_dom" ]]; then
echo " DominatorTree.h 已在正确位置"
else
echo -e " ${YELLOW}警告: DominatorTree.h 不存在${NC}"
fi
# 删除残留的 ANTLR 头文件(如果从 build 目录带过来)
local stale_headers=(
"$WARNING_DIR/src/include/SysYLexer.h"
"$WARNING_DIR/src/include/SysYParser.h"
"$WARNING_DIR/src/include/SysYVisitor.h"
"$WARNING_DIR/src/include/SysYBaseVisitor.h"
)
# 这些头文件是需要的,不删。但确保它们和 build/generated 版本一致
}
# ============================================================
# 第4步本地构建验证可选
# ============================================================
step4_verify() {
if $SKIP_BUILD; then
echo -e "${YELLOW}=== 第4步: 跳过本地构建验证 ===${NC}"
return
fi
echo -e "${GREEN}=== 第4步: 本地构建验证 ===${NC}"
if $DRY_RUN; then
echo " [dry-run] cmake + make"
return
fi
# 提取 ANTLR runtime
local antlr_zip="$WARNING_DIR/third_party/antlr4-runtime-4.13.2.zip"
local antlr_dir="$WARNING_DIR/third_party/antlr4-runtime-4.13.2"
if [[ -f "$antlr_zip" ]] && [[ ! -d "$antlr_dir/runtime" ]]; then
echo " 解压 ANTLR runtime..."
unzip -qo "$antlr_zip" -d "$antlr_dir/" 2>/dev/null || true
# 修复嵌套目录
if [[ -d "$antlr_dir/antlr4-runtime-4.13.2/runtime" ]]; then
mv "$antlr_dir/antlr4-runtime-4.13.2/runtime" "$antlr_dir/" 2>/dev/null || true
rm -rf "$antlr_dir/antlr4-runtime-4.13.2" 2>/dev/null || true
fi
fi
local build_dir="$WARNING_DIR/build_verify"
mkdir -p "$build_dir/generated/antlr4"
# ANTLR 代码生成
java -jar "$WARNING_DIR/third_party/antlr-4.13.2-complete.jar" \
-Dlanguage=Cpp -visitor -no-listener -Xexact-output-dir \
-o "$build_dir/generated/antlr4" \
"$WARNING_DIR/src/antlr4/SysY.g4" 2>&1 | tail -1
# CMake 构建
cmake -S "$WARNING_DIR" -B "$build_dir" \
-DCMAKE_BUILD_TYPE=Release -DCOMPILER_PARSE_ONLY=OFF 2>&1 | tail -1
if cmake --build "$build_dir" -j "$(nproc)" 2>&1 | tail -5; then
echo -e " ${GREEN}构建成功${NC}"
# 快速功能验证
local test_file="$NUDT_DIR/2026test/functional/00_main.sy"
if [[ -f "$test_file" ]]; then
if "$build_dir/bin/compiler" "$test_file" -S -o /tmp/submit_test.s 2>/dev/null; then
echo -e " ${GREEN}00_main 编译通过${NC}"
else
echo -e " ${RED}00_main 编译失败!${NC}"
fi
fi
else
echo -e " ${RED}构建失败!请修复后再提交${NC}"
exit 1
fi
# 清理验证构建目录
rm -rf "$build_dir"
}
# ============================================================
# 第5步提交
# ============================================================
step5_commit() {
echo -e "${GREEN}=== 第5步: 提交 ===${NC}"
if $DRY_RUN; then
echo " [dry-run] git add -A && git commit"
return
fi
cd "$WARNING_DIR"
# 清理可能遗留的构建目录
rm -rf build_teammate build_clang build_verify
git add -A
if git diff-index --quiet HEAD --; then
echo " 没有改动需要提交"
return
fi
local commit_msg
if [[ -n "$CUSTOM_MSG" ]]; then
commit_msg="$CUSTOM_MSG"
else
local nudt_commit=$(git -C "$NUDT_DIR" log --oneline -1)
commit_msg="perf: 同步优化版编译器源码
$(git -C "$NUDT_DIR" log --oneline -5 | sed 's/^/ /')
自动提交: 删除死代码 + 修复头文件路径 + 同步优化"
fi
git commit -m "$commit_msg"
echo -e " ${GREEN}已提交${NC}"
git log --oneline -1
}
# ============================================================
# 第6步推送
# ============================================================
step6_push() {
if ! $DO_PUSH; then
echo -e "${YELLOW}=== 跳过推送(使用 -p 启用) ===${NC}"
echo " 手动推送: cd $WARNING_DIR && git push origin main:lzk --force"
return
fi
echo -e "${GREEN}=== 推送 ===${NC}"
if $DRY_RUN; then
echo " [dry-run] git push origin main:lzk --force"
return
fi
cd "$WARNING_DIR"
git push origin main:lzk --force
echo -e " ${GREEN}推送完成${NC}"
}
# ============================================================
# 执行
# ============================================================
echo ""
step1_sync
step2_deadcode
step3_headers
step4_verify
step5_commit
step6_push
echo ""
echo -e "${GREEN}=== 完成 ===${NC}"
echo " 平台地址: https://compiler.xtnl.org.cn/#/"
echo " 登录后触发功能/性能测试"