#!/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 " 登录后触发功能/性能测试"