TG-PlatformPlus/build_package.py

243 lines
7.1 KiB
Python
Raw Normal View History

2026-03-19 16:00:40 +08:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
GPCT-standalone 自动打包脚本
支持: Windows (PyInstaller) + NSIS 安装包生成
"""
import os
import sys
import json
import shutil
import subprocess
from datetime import datetime
from pathlib import Path
# 配置
PROJECT_DIR = Path("C:/PPRO/TG-PlatformPlus")
VENV_DIR = PROJECT_DIR / "venv"
DIST_DIR = PROJECT_DIR / "dist"
BUILD_DIR = PROJECT_DIR / "build"
SPEC_DIR = PROJECT_DIR / "spec"
NSIS_SCRIPT = PROJECT_DIR / "GPCT-standalone.nsi"
VERSION_FILE = PROJECT_DIR / "version.json"
def run_command(cmd, cwd=None, check=True):
"""执行命令并返回结果"""
print(f"执行: {cmd}")
result = subprocess.run(
cmd,
shell=True,
cwd=cwd or PROJECT_DIR,
capture_output=True,
text=True,
encoding='utf-8'
)
if result.returncode != 0 and check:
print(f"[错误] 命令执行失败:")
print(f"stdout: {result.stdout}")
print(f"stderr: {result.stderr}")
sys.exit(1)
return result
def activate_venv():
"""激活虚拟环境"""
venv_python = VENV_DIR / "Scripts" / "python.exe"
if not venv_python.exists():
print(f"[错误] 未找到虚拟环境 Python: {venv_python}")
sys.exit(1)
return venv_python
def clean_build():
"""清理旧的构建文件"""
print("\n[1/6] 清理旧的构建文件...")
dirs_to_clean = [DIST_DIR, BUILD_DIR]
for dir_path in dirs_to_clean:
if dir_path.exists():
shutil.rmtree(dir_path)
print(f" - 已删除: {dir_path}")
def update_version():
"""更新版本信息"""
print("\n[2/6] 更新版本信息...")
if VERSION_FILE.exists():
with open(VERSION_FILE, 'r', encoding='utf-8') as f:
version_data = json.load(f)
# 更新发布时间
version_data['releaseTime'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(VERSION_FILE, 'w', encoding='utf-8') as f:
json.dump(version_data, f, ensure_ascii=False, indent=4)
print(f" - 版本: {version_data.get('version', 'N/A')}")
print(f" - 发布时间: {version_data['releaseTime']}")
else:
print(f" [警告] 未找到版本文件: {VERSION_FILE}")
def build_with_pyinstaller():
"""使用 PyInstaller 打包"""
print("\n[3/6] 使用 PyInstaller 打包...")
python_exe = activate_venv()
# 查找 spec 文件
spec_files = list(SPEC_DIR.glob("*.spec"))
if not spec_files:
print(f"[错误] 未找到 spec 文件在: {SPEC_DIR}")
sys.exit(1)
spec_file = spec_files[0]
print(f" - 使用 spec 文件: {spec_file}")
# 执行 PyInstaller
cmd = f'"{python_exe}" -m PyInstaller "{spec_file}" --clean'
result = run_command(cmd)
if "completed successfully" in result.stdout or (DIST_DIR / "GPCT-standalone").exists():
print(" - PyInstaller 打包成功")
else:
print(f" [警告] 请检查输出: {result.stdout}")
def copy_additional_files():
"""复制额外文件到输出目录"""
print("\n[4/6] 复制额外文件...")
output_dir = DIST_DIR / "GPCT-standalone" / "_internal"
# 创建 dataFile 目录
datafile_dir = output_dir / "dataFile"
datafile_dir.mkdir(parents=True, exist_ok=True)
# 复制 dataFile 文件
src_datafile = PROJECT_DIR / "dataFile"
if src_datafile.exists():
for file in ["config.json", "data.db"]:
src = src_datafile / file
if src.exists():
shutil.copy2(src, datafile_dir / file)
print(f" - 已复制: {file}")
# 复制加密狗 DLL
dog_dll = PROJECT_DIR / "Syunew3D_x64.dll"
if dog_dll.exists():
shutil.copy2(dog_dll, output_dir / "Syunew3D_x64.dll")
print(f" - 已复制: Syunew3D_x64.dll")
# 复制 influxd.exe
influxd = PROJECT_DIR / "influxd.exe"
if influxd.exists():
shutil.copy2(influxd, output_dir / "influxd.exe")
print(f" - 已复制: influxd.exe")
def build_nsis_installer():
"""构建 NSIS 安装包"""
print("\n[5/6] 构建 NSIS 安装包...")
if not NSIS_SCRIPT.exists():
print(f" [跳过] 未找到 NSIS 脚本: {NSIS_SCRIPT}")
return
# 查找 makensis
makensis_paths = [
r"C:\Program Files (x86)\NSIS\makensis.exe",
r"C:\Program Files\NSIS\makensis.exe",
]
makensis = None
for path in makensis_paths:
if os.path.exists(path):
makensis = path
break
if not makensis:
# 尝试从环境变量查找
result = subprocess.run("where makensis", shell=True, capture_output=True, text=True)
if result.returncode == 0:
makensis = result.stdout.strip().split('\n')[0]
if not makensis:
print(" [跳过] 未找到 NSIS (makensis.exe),请安装 NSIS")
return
print(f" - 使用 NSIS: {makensis}")
# 执行 NSIS 编译
cmd = f'"{makensis}" "{NSIS_SCRIPT}"'
result = run_command(cmd, check=False)
if result.returncode == 0:
print(" - NSIS 安装包构建成功")
# 查找生成的安装包
installer = PROJECT_DIR / "GPCT-standalone-Setup.exe"
if installer.exists():
print(f" - 安装包位置: {installer}")
else:
print(f" [警告] NSIS 构建可能失败: {result.stderr}")
def verify_build():
"""验证构建结果"""
print("\n[6/6] 验证构建结果...")
exe_path = DIST_DIR / "GPCT-standalone" / "GPCT-standalone.exe"
if exe_path.exists():
size = exe_path.stat().st_size / (1024 * 1024) # MB
print(f" - 可执行文件: {exe_path}")
print(f" - 文件大小: {size:.2f} MB")
# 检查关键文件
internal_dir = DIST_DIR / "GPCT-standalone" / "_internal"
critical_files = [
"config.json",
"data.db",
"Syunew3D_x64.dll"
]
print(" - 关键文件检查:")
for file in critical_files:
file_path = internal_dir / file
if file_path.exists():
print(f" [OK] {file}")
else:
print(f" [缺失] {file}")
return True
else:
print(f" [错误] 未找到可执行文件: {exe_path}")
return False
def main():
"""主函数"""
print("=" * 50)
print(" GPCT-standalone 自动打包脚本")
print("=" * 50)
# 检查项目目录
if not PROJECT_DIR.exists():
print(f"[错误] 项目目录不存在: {PROJECT_DIR}")
sys.exit(1)
# 执行构建步骤
clean_build()
update_version()
build_with_pyinstaller()
copy_additional_files()
build_nsis_installer()
success = verify_build()
print("\n" + "=" * 50)
if success:
print(" 打包完成!")
print(f" 输出目录: {DIST_DIR / 'GPCT-standalone'}")
else:
print(" 打包过程中出现错误")
print("=" * 50)
return 0 if success else 1
if __name__ == "__main__":
sys.exit(main())