127 lines
3.8 KiB
RPMSpec
127 lines
3.8 KiB
RPMSpec
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
|
"""PyInstaller 打包配置:SVFS Studio(PySide6 桌面工具,无 WebEngine)。
|
|||
|
|
|
|||
|
|
用法(或直接用 packaging/build.py 编排)::
|
|||
|
|
|
|||
|
|
uv sync --extra gui
|
|||
|
|
uv pip install pyinstaller
|
|||
|
|
uv run pyinstaller --noconfirm packaging/svfs_studio.spec
|
|||
|
|
# 目录版产物: dist/SVFS-Studio/SVFS-Studio.exe
|
|||
|
|
|
|||
|
|
单文件版(启动稍慢,Qt 会先解包到临时目录)::
|
|||
|
|
|
|||
|
|
SVFS_ONEFILE=1 uv run pyinstaller --noconfirm packaging/svfs_studio.spec
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import os
|
|||
|
|
import re
|
|||
|
|
|
|||
|
|
from PyInstaller.utils.hooks import collect_submodules
|
|||
|
|
|
|||
|
|
# spec 文件在 <repo>/packaging/ 下,仓库根与 src 由此反推
|
|||
|
|
REPO = os.path.dirname(os.path.dirname(os.path.abspath(SPEC)))
|
|||
|
|
SRC = os.path.join(REPO, "src")
|
|||
|
|
ONEFILE = os.environ.get("SVFS_ONEFILE", "") == "1"
|
|||
|
|
|
|||
|
|
ICON = os.path.join(REPO, "resources", "ico", "logo.ico")
|
|||
|
|
|
|||
|
|
a = Analysis(
|
|||
|
|
[os.path.join(REPO, "packaging", "run_studio.py")],
|
|||
|
|
pathex=[SRC],
|
|||
|
|
binaries=[],
|
|||
|
|
datas=[
|
|||
|
|
# app_icon() / repo_root() 在冻结环境下从包内找 resources/(见 sample.py)
|
|||
|
|
(os.path.join(REPO, "resources", "ico"), "resources/ico"),
|
|||
|
|
(os.path.join(REPO, "resources", "images"), "resources/images"),
|
|||
|
|
],
|
|||
|
|
hiddenimports=[
|
|||
|
|
# 界面里通过 getattr(build_<key>) 取视图工厂,收集整个包最稳妥
|
|||
|
|
*collect_submodules("svfs_studio"),
|
|||
|
|
*collect_submodules("sqlite_vfs"),
|
|||
|
|
],
|
|||
|
|
hookspath=[],
|
|||
|
|
hooksconfig={},
|
|||
|
|
runtime_hooks=[],
|
|||
|
|
excludes=["tkinter"],
|
|||
|
|
noarchive=False,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# ----------------------------------------------------------------------
|
|||
|
|
# 体积裁剪(白名单制):PySide6 的钩子会把 wheel 里**所有** Qt 模块的
|
|||
|
|
# DLL/pyd 整包搬进来,而本应用只用 QtCore/QtGui/QtWidgets:
|
|||
|
|
# * 未使用的 Qt 模块 DLL(Qml/Quick/Quick3D/Pdf/Network/OpenGL/Svg/
|
|||
|
|
# VirtualKeyboard/ShaderTools…,约 25M)
|
|||
|
|
# * 未使用的 python 绑定 pyd
|
|||
|
|
# * opengl32sw.dll(20M 软件渲染回退;Widgets 走光栅绘制用不到,
|
|||
|
|
# 无显卡的机器出问题就把它加回 KEEP 外的例外)
|
|||
|
|
# * Qt 自带译文(*.qm,6.7M;界面文案全部硬编码中文)
|
|||
|
|
# * 依赖被删模块的插件(networkinformation/tls/qsvg)
|
|||
|
|
# ----------------------------------------------------------------------
|
|||
|
|
KEEP_QT6_DLLS = {"Qt6Core", "Qt6Gui", "Qt6Widgets"}
|
|||
|
|
KEEP_PYDS = {"QtCore", "QtGui", "QtWidgets"}
|
|||
|
|
|
|||
|
|
QT_DLL_RE = re.compile(r"PySide6[/\\](Qt6[^/\\]*\.dll)$", re.IGNORECASE)
|
|||
|
|
PYD_RE = re.compile(r"PySide6[/\\]([^/\\]*\.pyd)$", re.IGNORECASE)
|
|||
|
|
DROP_STUDIO = re.compile(
|
|||
|
|
r"PySide6[/\\](?:"
|
|||
|
|
r"opengl32sw\.dll"
|
|||
|
|
r"|d3dcompiler_47\.dll"
|
|||
|
|
r"|translations[/\\]"
|
|||
|
|
r"|plugins[/\\](?:networkinformation|tls)[/\\]"
|
|||
|
|
r"|plugins[/\\]imageformats[/\\]qsvg\.dll"
|
|||
|
|
r"|plugins[/\\]iconengines[/\\]qsvgicon\.dll"
|
|||
|
|
r")",
|
|||
|
|
re.IGNORECASE,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _keep(entry_name):
|
|||
|
|
if DROP_STUDIO.search(entry_name):
|
|||
|
|
return False
|
|||
|
|
match = QT_DLL_RE.search(entry_name)
|
|||
|
|
if match:
|
|||
|
|
return match.group(1).rsplit(".", 1)[0] in KEEP_QT6_DLLS
|
|||
|
|
match = PYD_RE.search(entry_name)
|
|||
|
|
if match:
|
|||
|
|
return match.group(1).rsplit(".", 1)[0] in KEEP_PYDS
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
|
|||
|
|
a.binaries = [entry for entry in a.binaries if _keep(entry[0])]
|
|||
|
|
a.datas = [entry for entry in a.datas if _keep(entry[0])]
|
|||
|
|
|
|||
|
|
pyz = PYZ(a.pure)
|
|||
|
|
|
|||
|
|
exe_kwargs = dict(
|
|||
|
|
name="SVFS-Studio",
|
|||
|
|
console=False, # GUI 程序,不弹控制台
|
|||
|
|
icon=ICON if os.path.exists(ICON) else None,
|
|||
|
|
upx=False,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if ONEFILE:
|
|||
|
|
exe = EXE(
|
|||
|
|
pyz,
|
|||
|
|
a.scripts,
|
|||
|
|
a.binaries,
|
|||
|
|
a.datas,
|
|||
|
|
[],
|
|||
|
|
**exe_kwargs,
|
|||
|
|
)
|
|||
|
|
else:
|
|||
|
|
exe = EXE(
|
|||
|
|
pyz,
|
|||
|
|
a.scripts,
|
|||
|
|
[],
|
|||
|
|
exclude_binaries=True,
|
|||
|
|
**exe_kwargs,
|
|||
|
|
)
|
|||
|
|
coll = COLLECT(
|
|||
|
|
exe,
|
|||
|
|
a.binaries,
|
|||
|
|
a.datas,
|
|||
|
|
strip=False,
|
|||
|
|
upx=False,
|
|||
|
|
name="SVFS-Studio",
|
|||
|
|
)
|