#!/bin/bash #==================================================== # System Required: OpenWrt # Description: OpenWrt Compile Script # Author: Modified from 281677160 #==================================================== # 字体颜色配置 Green="\033[32m" Red="\033[31m" Yellow="\033[33m" Blue="\033[36m" Purple="\033[35m" Font="\033[0m" GreenBG="\033[42;37m" RedBG="\033[41;37m" BlueBG="\033[44;37m" OK="${Green}[OK]${Font}" ERROR="${Red}[ERROR]${Font}" # 变量 export GITHUB_WORKSPACE="$PWD" export HOME_PATH="${GITHUB_WORKSPACE}/openwrt" export OPERATES_PATH="${GITHUB_WORKSPACE}/operates" export GITHUB_ENV="${GITHUB_WORKSPACE}/bendienv" export CURRENT_PATH="${GITHUB_WORKSPACE##*/}" export BENDI_VERSION="1" # 打印函数 function print_ok() { echo -e "\n${OK} ${Blue} $1 ${Font}\n" } function print_error() { echo -e "\n${ERROR} ${RedBG} $1 ${Font}\n" } function ECHO_INFO() { echo -e "${Blue}[INFO]${Font} ${Green} $1 ${Font}" } function ECHO_WARN() { echo -e "${Yellow}[WARN]${Font} ${Yellow} $1 ${Font}" } function ECHO_ERROR() { echo -e "${Red}[ERROR]${Font} ${Red} $1 ${Font}" } # 进度条显示 function progress_show() { local current=$1 local total=$2 local width=50 local percentage=$((current * 100 / total)) local completed=$((width * current / total)) local remaining=$((width - completed)) printf "\r[" printf "%${completed}s" | tr ' ' '#' printf "%${remaining}s" | tr ' ' '-' printf "] %d%%" ${percentage} } # 判断命令执行结果 function judge() { if [[ 0 -eq $? ]]; then print_ok "$1" else print_error "$1" exit 1 fi } # 检查系统环境 function check_system() { source /etc/os-release if [[ ! "${UBUNTU_CODENAME}" =~ (bionic|focal|jammy) ]]; then print_error "请使用 Ubuntu 18.04/20.04/22.04 系统" exit 1 fi if [[ "$USER" == "root" ]]; then print_error "请勿使用root用户编译,请使用普通用户" exit 1 fi # 检查磁盘空间 local available_space=$(df -h $PWD | awk 'NR==2 {print $4}' | sed 's/G//') if [[ ${available_space%.*} -lt 20 ]]; then print_error "可用空间小于20G,编译可能会失败,建议使用大于20G的可用空间" read -p "是否继续编译?[y/N]:" continue_build case $continue_build in [yY]) ECHO_WARN "继续编译..." ;; *) ECHO_INFO "取消编译" exit 0 ;; esac fi } # 初始化环境 function init_env() { echo '#!/bin/bash' >${GITHUB_ENV} sudo chmod +x ${GITHUB_ENV} if [[ `sudo grep -c "sudo ALL=(ALL:ALL) NOPASSWD:ALL" /etc/sudoers` -eq '0' ]]; then sudo sed -i 's?%sudo.*?%sudo ALL=(ALL:ALL) NOPASSWD:ALL?g' /etc/sudoers fi # 创建必要的目录 mkdir -p ${HOME_PATH} mkdir -p ${OPERATES_PATH} } # 编译主函数 function compile_firmware() { cd ${HOME_PATH} # 显示编译信息 echo -e "\n" echo -e "${Blue}┌──────────────── 编译信息 ────────────────┐${Font}" echo -e "${Blue}│ ${Green}CPU 型号:${Font} $(cat /proc/cpuinfo | grep 'model name' | uniq | cut -d: -f2 | xargs)" echo -e "${Blue}│ ${Green}CPU 核心:${Font} $(nproc) 线程" echo -e "${Blue}│ ${Green}内存大小:${Font} $(free -h | awk '/Mem/ {print $2}')" echo -e "${Blue}│ ${Green}可用空间:${Font} $(df -h $PWD | awk 'NR==2 {print $4}')" echo -e "${Blue}└─────────────────────────────────────────┘${Font}" echo -e "\n" # 清理编译目录 ECHO_INFO "清理编译目录..." rm -rf ./tmp rm -rf ./build_dir/target* # 更新 feeds ECHO_INFO "更新 feeds..." ./scripts/feeds update -a ./scripts/feeds install -a # 下载依赖 ECHO_INFO "下载依赖文件..." make defconfig make download -j$(nproc) # 开始编译 ECHO_INFO "开始编译固件..." echo -e "${Yellow}预计需要2-3小时,请耐心等待...${Font}" START_TIME=$(date +%s) if [[ "$(nproc)" -le "12" ]]; then make -j$(nproc) V=s 2>&1 | tee build.log else make -j16 V=s 2>&1 | tee build.log fi END_TIME=$(date +%s) ELAPSED=$((END_TIME - START_TIME)) Hours=$((ELAPSED / 3600)) Minutes=$(((ELAPSED % 3600) / 60)) Seconds=$((ELAPSED % 60)) # 检查编译结果 if [[ -f bin/targets/*/*/openwrt-*-sysupgrade.bin ]]; then print_ok "固件编译完成!" echo -e "${Green}编译用时: ${Hours}小时${Minutes}分${Seconds}秒${Font}" collect_firmware else print_error "固件编译失败!" echo -e "${Red}请查看build.log文件了解详细错误信息${Font}" exit 1 fi } # 收集固件 function collect_firmware() { cd ${HOME_PATH} # 创建固件目录 mkdir -p ${GITHUB_WORKSPACE}/firmware # 复制编译好的固件 ECHO_INFO "正在收集固件..." cp -rf bin/targets/*/* ${GITHUB_WORKSPACE}/firmware/ # 生成固件信息 cd ${GITHUB_WORKSPACE}/firmware FIRMWARE_INFO="${GITHUB_WORKSPACE}/firmware/固件信息.txt" echo "编译日期: $(date "+%Y年%m月%d日 %H:%M")" > "${FIRMWARE_INFO}" echo "固件源码: ${SOURCE_CODE}" >> "${FIRMWARE_INFO}" echo "固件版本: $(cat ${HOME_PATH}/package/base-files/files/etc/openwrt_version 2>/dev/null)" >> "${FIRMWARE_INFO}" echo "固件架构: $(ls bin/targets/)" >> "${FIRMWARE_INFO}" # 显示固件信息 echo -e "\n" echo -e "${Blue}┌──────────────── 固件信息 ────────────────┐${Font}" echo -e "${Blue}│ ${Green}固件位置:${Font} ${GITHUB_WORKSPACE}/firmware" echo -e "${Blue}│ ${Green}固件大小:${Font} $(du -sh ${GITHUB_WORKSPACE}/firmware | cut -f1)" echo -e "${Blue}│ ${Green}编译用时:${Font} ${Hours}小时${Minutes}分${Seconds}秒" echo -e "${Blue}└─────────────────────────────────────────┘${Font}" echo -e "\n" } # 更新源代码 function update_code() { cd ${HOME_PATH} ECHO_INFO "正在更新源代码..." git pull if [[ $? -eq 0 ]]; then print_ok "源代码更新完成" else print_error "源代码更新失败" exit 1 fi } # 选择配置文件 function select_config() { cd ${HOME_PATH} echo -e "\n" echo -e "${Blue}┌──────────────── 配置选择 ────────────────┐${Font}" echo -e "${Blue}│ ${Yellow}1.${Font} x86_64 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}2.${Font} Rockchip ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}3.${Font} Raspberry Pi ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}4.${Font} 自定义配置 ${Blue}│${Font}" echo -e "${Blue}└─────────────────────────────────────────┘${Font}" echo -e "\n" read -p "请选择配置文件[1-4]: " config_choose case $config_choose in 1) cp configs/x86_64.config .config ;; 2) cp configs/rockchip.config .config ;; 3) cp configs/rpi4.config .config ;; 4) make menuconfig ;; *) print_error "无效的选择" select_config ;; esac # 保存配置 make defconfig } # 显示主菜单 function show_main_menu() { clear echo -e "\n" echo -e "${Blue}┌──────────────────────────────────────────┐${Font}" echo -e "${Blue}│ OpenWrt 编译助手 │${Font}" echo -e "${Blue}├──────────────────────────────────────────┤${Font}" echo -e "${Blue}│ │${Font}" echo -e "${Blue}│ ${Yellow}1.${Font} 更新系统软件包 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}2.${Font} 下载/更新 OpenWrt 源码 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}3.${Font} 选择编译配置 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}4.${Font} 开始编译固件 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}5.${Font} 打包 Amlogic/Rockchip 固件 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}6.${Font} 清理编译目录 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}7.${Font} 高级设置 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}0.${Font} 退出脚本 ${Blue}│${Font}" echo -e "${Blue}│ │${Font}" echo -e "${Blue}└──────────────────────────────────────────┘${Font}" echo -e "\n" } # 显示高级设置菜单 function show_advanced_menu() { clear echo -e "\n" echo -e "${Blue}┌──────────────── 高级设置 ────────────────┐${Font}" echo -e "${Blue}│ ${Yellow}1.${Font} 修改默认 IP 地址 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}2.${Font} 修改默认主题 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}3.${Font} 添加/删除软件包 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}4.${Font} 设置 OpenClash 配置 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}5.${Font} 自定义 feeds 配置 ${Blue}│${Font}" echo -e "${Blue}│ ${Yellow}0.${Font} 返回主菜单 ${Blue}│${Font}" echo -e "${Blue}└─────────────────────────────────────────┘${Font}" echo -e "\n" } # 处理主菜单选择 function process_main_menu() { local choose read -p "请输入选择[0-7]: " choose case $choose in 1) update_system ;; 2) update_code ;; 3) select_config ;; 4) compile_firmware ;; 5) package_armbian ;; 6) clean_build ;; 7) process_advanced_menu ;; 0) ECHO_INFO "感谢使用,再见!" exit 0 ;; *) print_error "无效的选择" ;; esac } # 处理高级设置菜单 function process_advanced_menu() { show_advanced_menu local choose read -p "请输入选择[0-5]: " choose case $choose in 1) modify_ip ;; 2) modify_theme ;; 3) modify_packages ;; 4) setup_openclash ;; 5) modify_feeds ;; 0) return ;; *) print_error "无效的选择" process_advanced_menu ;; esac } # 更新系统 function update_system() { ECHO_INFO "正在更新系统..." sudo apt update sudo apt upgrade -y print_ok "系统更新完成" } # 清理编译目录 function clean_build() { cd ${HOME_PATH} ECHO_INFO "正在清理编译目录..." make clean rm -rf ./tmp print_ok "清理完成" } # Amlogic/Rockchip 固件打包 function package_armbian() { clear echo -e "\n" echo -e "${Blue}┌─────────── Amlogic/Rockchip 打包 ──────────┐${Font}" echo -e "${Blue}│ │${Font}" echo -e "${Blue}│ ${Yellow}支持的设备:${Font} ${Blue}│${Font}" echo -e "${Blue}│ ${Green}● Amlogic:${Font} S905x3, S905x2, S922x, etc ${Blue}│${Font}" echo -e "${Blue}│ ${Green}● Rockchip:${Font} R66S, R68S, H66K, etc ${Blue}│${Font}" echo -e "${Blue}│ │${Font}" echo -e "${Blue}└──────────────────────────────────────────┘${Font}" echo -e "\n" # 检查必要文件 if [[ ! -f "${HOME_PATH}/bin/targets/armvirt/64/openwrt-armvirt-64-default-rootfs.tar.gz" ]]; then print_error "未找到 armvirt-64 rootfs 文件,请先编译固件!" return fi # 下载打包工具 if [[ ! -d "amlogic" ]]; then ECHO_INFO "下载打包工具..." git clone --depth 1 https://github.com/ophub/amlogic-s9xxx-openwrt.git amlogic fi # 选择设备 echo -e "${Yellow}请选择设备类型:${Font}" echo -e "1. Amlogic S905x3" echo -e "2. Amlogic S905x2" echo -e "3. Amlogic S922x" echo -e "4. Rockchip R66S/R68S" echo -e "5. Rockchip H66K" echo -e "0. 返回主菜单" read -p "请输入选择[0-5]: " device_choose case $device_choose in 1) device="s905x3";; 2) device="s905x2";; 3) device="s922x";; 4) device="r68s";; 5) device="h66k";; 0) return;; *) print_error "无效的选择" return ;; esac # 开始打包 ECHO_INFO "开始打包固件..." cd amlogic sudo ./make -d $device -k 5.15.100 if [[ $? -eq 0 ]]; then print_ok "固件打包完成!" echo -e "${Green}固件位置:${Font} amlogic/output/images/" else print_error "固件打包失败!" fi } # 错误处理函数 function error_handle() { local error_code=$1 local error_msg=$2 echo -e "\n" print_error "错误代码: $error_code" print_error "错误信息: $error_msg" # 记录错误日志 echo "[$(date '+%Y-%m-%d %H:%M:%S')] Error $error_code: $error_msg" >> error.log case $error_code in 1) ECHO_INFO "尝试修复..." make clean ;; 2) ECHO_INFO "尝试更新源..." ./scripts/feeds update -a ;; *) ECHO_INFO "未知错误,请查看日志" ;; esac } # 添加日志记录 function log_message() { local level=$1 local message=$2 echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" >> build.log } # 主程序入口 function main() { # 检查系统环境 check_system # 初始化环境 init_env # 主循环 while true; do show_main_menu process_main_menu echo -e "\n" read -p "按回车键继续..." done } # 捕获错误信号 trap 'error_handle $? "意外退出"' ERR # 启动主程序 main "$@"