Files
2026-09-22 16:08:12 +08:00

131 lines
5.0 KiB
RPMSpec
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.
# -*- mode: python ; coding: utf-8 -*-
"""PyInstaller 打包配置。
由 ``packaging/build_pyinstaller.py`` 调用 —— 选项通过**环境变量**传进来
(spec 文件本身不接受命令行参数,这是 PyInstaller 的既定用法):
=========================== ==========================================
环境变量 作用
=========================== ==========================================
``CLG_NAME`` 产物名(默认 chongming-license-gui)
``CLG_ONEFILE`` ``1`` = 单文件(默认),``0`` = 目录模式
``CLG_CONSOLE`` ``1`` = 带控制台窗口(排查启动问题用)
``CLG_ICON`` .ico 路径(由 ``_common.build_app_icon()`` 生成)
=========================== ==========================================
"""
import os
from pathlib import Path
ROOT = Path(SPECPATH).resolve().parent # noqa: F821 - SPECPATH 由 PyInstaller 注入
NAME = os.environ.get("CLG_NAME", "chongming-license-gui")
ONEFILE = os.environ.get("CLG_ONEFILE", "1") == "1"
CONSOLE = os.environ.get("CLG_CONSOLE", "0") == "1"
ICON = os.environ.get("CLG_ICON") or None
# PySide6 装了整套 Addons(Qt3D / WebEngine / Charts…),本工具一个都不用。
# PyInstaller 的 PySide6 hook 只打包"被 import 到的" Qt 模块,但显式排除能兜住
# 间接依赖,避免几百 MB 的模块被拖进来。
# 注:排除不存在的模块是安全的(PyInstaller 只按名字匹配)。
EXCLUDES = [
# 3D / 图形 / 可视化
"PySide6.Qt3DAnimation", "PySide6.Qt3DCore", "PySide6.Qt3DExtras",
"PySide6.Qt3DInput", "PySide6.Qt3DLogic", "PySide6.Qt3DRender",
"PySide6.QtCharts", "PySide6.QtDataVisualization", "PySide6.QtGraphs",
"PySide6.QtGraphsWidgets", "PySide6.QtCanvasPainter",
# Web / QML / Quick(体积最大的一批)
"PySide6.QtWebEngineCore", "PySide6.QtWebEngineWidgets",
"PySide6.QtWebEngineQuick", "PySide6.QtWebView", "PySide6.QtWebChannel",
"PySide6.QtWebSockets", "PySide6.QtHttpServer",
"PySide6.QtQml", "PySide6.QtQuick", "PySide6.QtQuick3D",
"PySide6.QtQuickControls2", "PySide6.QtQuickWidgets", "PySide6.QtQuickTest",
# 多媒体 / 设备 / 传感器
"PySide6.QtMultimedia", "PySide6.QtMultimediaWidgets", "PySide6.QtSpatialAudio",
"PySide6.QtTextToSpeech", "PySide6.QtBluetooth", "PySide6.QtNfc",
"PySide6.QtPositioning", "PySide6.QtLocation", "PySide6.QtSensors",
"PySide6.QtSerialPort", "PySide6.QtSerialBus", "PySide6.QtRemoteObjects",
"PySide6.QtScxml", "PySide6.QtStateMachine", "PySide6.QtAxContainer",
# 文档 / 设计器 / 测试 / 数据库 / 容器
"PySide6.QtPdf", "PySide6.QtPdfWidgets", "PySide6.QtDesigner",
"PySide6.QtUiTools", "PySide6.QtHelp", "PySide6.QtTest",
"PySide6.QtSql", "PySide6.QtDBus", "PySide6.QtConcurrent",
"PySide6.QtNetworkAuth", "PySide6.QtXml", "PySide6.QtSvgWidgets",
"PySide6.QtOpenGL", "PySide6.QtOpenGLWidgets",
# 与本工具无关的标准库大件
"tkinter", "pydoc_data",
]
a = Analysis( # noqa: F821
[str(ROOT / "packaging" / "launcher.py")],
# 用源码树解析本包,而不是依赖 editable 安装(冻结工具对 .pth 式
# editable 安装的解析并不可靠)
pathex=[str(ROOT / "src")],
binaries=[],
datas=[], # 无数据文件:图标与样式表都是运行时生成的
# PySide6.QtSvg 是显式 import,正常能被扫到;这里再钉一遍 —— 少了它
# 图标会全部变空白,而且不报错
hiddenimports=["PySide6.QtSvg"],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=EXCLUDES,
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure) # noqa: F821
if ONEFILE:
# 单文件:自解压到临时目录再运行(分发最省事,首次启动稍慢)
exe = EXE( # noqa: F821
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name=NAME,
debug=False,
bootloader_ignore_signals=False,
strip=False,
# UPX 压缩容易触发杀软误报,也会损坏部分 Qt DLL,明确关掉
upx=False,
upx_exclude=[],
runtime_tmpdir=None,
console=CONSOLE,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=ICON,
)
else:
# 目录模式:启动更快,适合放在固定办公机上长期使用
exe = EXE( # noqa: F821
pyz,
a.scripts,
[],
exclude_binaries=True,
name=NAME,
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
console=CONSOLE,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=ICON,
)
coll = COLLECT( # noqa: F821
exe,
a.binaries,
a.datas,
strip=False,
upx=False,
upx_exclude=[],
name=NAME,
)