Files
BootRepairTool/build.py
2026-02-14 14:39:44 +08:00

207 lines
5.7 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
BootRepairTool 打包脚本
使用 Python 3.9 + PyInstaller 打包
"""
import sys
import os
import subprocess
import shutil
# 需要的 Python 版本
REQUIRED_PYTHON_VERSION = (3, 9)
def check_python_version():
"""检查 Python 版本是否为 3.9"""
current = sys.version_info[:2]
if current != REQUIRED_PYTHON_VERSION:
print(f"错误: 需要使用 Python {REQUIRED_PYTHON_VERSION[0]}.{REQUIRED_PYTHON_VERSION[1]}")
print(f"当前版本: Python {current[0]}.{current[1]}")
print("\n请使用以下命令运行:")
print(f" python3.9 {sys.argv[0]}")
return False
print(f"✓ Python 版本检查通过: {sys.version.split()[0]}")
return True
def install_dependencies():
"""安装打包所需的依赖"""
print("\n[1/5] 安装依赖...")
deps = ["pyinstaller"]
for dep in deps:
print(f" 安装 {dep}...")
try:
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", dep])
print(f"{dep} 安装成功")
except subprocess.CalledProcessError as e:
print(f"{dep} 安装失败: {e}")
return False
return True
def clean_build():
"""清理之前的构建文件"""
print("\n[2/5] 清理构建文件...")
dirs_to_remove = ["build", "dist"]
files_to_remove = ["*.pyc", "*.spec"]
for d in dirs_to_remove:
if os.path.exists(d):
shutil.rmtree(d)
print(f" 删除 {d}/")
# 清理 __pycache__
for root, dirs, files in os.walk("."):
if "__pycache__" in dirs:
pycache_path = os.path.join(root, "__pycache__")
shutil.rmtree(pycache_path)
print(f" 删除 {pycache_path}/")
print(" ✓ 清理完成")
def build_executable():
"""使用 PyInstaller 打包"""
print("\n[3/5] 开始打包...")
# 打包命令 - 输出为 .bin 文件wrapper 脚本将调用它
cmd = [
sys.executable, "-m", "PyInstaller",
"--name=LinuxGrubRepair.bin",
"--onefile",
"--console",
"--clean",
"--noconfirm",
"frontend.py"
]
print(f" 执行: {' '.join(cmd)}")
try:
subprocess.check_call(cmd)
print(" ✓ 打包成功")
return True
except subprocess.CalledProcessError as e:
print(f" ✗ 打包失败: {e}")
return False
def create_launcher():
"""创建启动器脚本,解决 X11 字体渲染问题"""
print("\n[4/5] 创建启动器脚本...")
launcher_content = '''#!/bin/bash
# ==============================================================================
# BootRepairTool 启动脚本
# 解决 Arch Linux 等系统上的 X11 字体渲染问题
# ==============================================================================
# 获取脚本实际所在目录(处理软链接情况)
SCRIPT_SOURCE="${BASH_SOURCE[0]}"
while [ -L "$SCRIPT_SOURCE" ]; do
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_SOURCE")" && pwd)"
SCRIPT_SOURCE="$(readlink "$SCRIPT_SOURCE")"
[[ $SCRIPT_SOURCE != /* ]] && SCRIPT_SOURCE="$SCRIPT_DIR/$SCRIPT_SOURCE"
done
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_SOURCE")" && pwd)"
# 如果是从 /bin 软链接启动,则使用实际安装目录
if [ "$SCRIPT_DIR" = "/bin" ] || [ "$SCRIPT_DIR" = "/usr/bin" ]; then
SCRIPT_DIR="/opt/boot-repair-tool"
fi
# 设置字体渲染环境变量,解决 "BadLength (poly request too large)" 错误
export XLIB_SKIP_ARGB_VISUALS=1
# 禁用某些 X11 RENDER 扩展功能
export GDK_NATIVE_WINDOWS=1
# 设置 tkinter 使用基本字体渲染
export TCL_DONT_USE_RENDER_EXTENSION=1
# 如果使用 Wayland强制使用 XWayland
if [ "$XDG_SESSION_TYPE" = "wayland" ]; then
export GDK_BACKEND=x11
fi
# 执行实际程序
exec "${SCRIPT_DIR}/LinuxGrubRepair.bin" "$@"
'''
dist_path = os.path.join(os.getcwd(), "dist")
launcher_path = os.path.join(dist_path, "LinuxGrubRepair")
with open(launcher_path, 'w') as f:
f.write(launcher_content)
# 设置可执行权限
os.chmod(launcher_path, 0o755)
print(f" ✓ 启动器创建完成: {launcher_path}")
return True
def show_result():
"""显示打包结果"""
print("\n[5/5] 打包完成!")
dist_path = os.path.join(os.getcwd(), "dist")
launcher_name = "LinuxGrubRepair"
bin_name = "LinuxGrubRepair.bin"
launcher_path = os.path.join(dist_path, launcher_name)
bin_path = os.path.join(dist_path, bin_name)
if os.path.exists(launcher_path) and os.path.exists(bin_path):
bin_size = os.path.getsize(bin_path)
bin_size_mb = bin_size / (1024 * 1024)
print(f"\n 启动器: {launcher_path}")
print(f" 程序文件: {bin_path}")
print(f" 文件大小: {bin_size_mb:.2f} MB")
print("\n 使用方式:")
print(f" sudo ./{launcher_name}")
print("\n 注意: 启动器脚本已配置 X11 环境变量,可解决字体渲染问题")
else:
print(" 未找到生成的文件")
def main():
"""主函数"""
print("=" * 50)
print("BootRepairTool 打包脚本")
print("=" * 50)
# 检查 Python 版本
if not check_python_version():
sys.exit(1)
# 安装依赖
if not install_dependencies():
print("依赖安装失败")
sys.exit(1)
# 清理旧构建
clean_build()
# 打包
if not build_executable():
print("打包失败")
sys.exit(1)
# 创建启动器
if not create_launcher():
print("创建启动器失败")
sys.exit(1)
# 显示结果
show_result()
if __name__ == "__main__":
main()