Files
xuetang/app/packaging/doctor_workstation.spec
T
2026-09-08 11:40:15 +08:00

128 lines
4.5 KiB
RPMSpec

# -*- mode: python ; coding: utf-8 -*-
"""Cross-platform PyInstaller onedir spec for the video-enabled workstation.
PyInstaller's official PySide6 QtWebEngine hooks are activated by the explicit
hidden imports below. Those hooks retain QtWebEngineProcess, Chromium .pak/
ICU resources, locales, Qt plugins, and the macOS framework/helper layout.
The explicit QtMultimedia imports likewise activate PyInstaller's official Qt
dependency scan, which collects the QtMultimedia/QtMultimediaWidgets extension
modules, Qt6Multimedia shared libraries/frameworks, multimedia plugins, and
their platform media backends.
"""
import os
import sys
from pathlib import Path
PROJECT_ROOT = Path(SPEC).resolve().parent.parent
SOURCE_ROOT = PROJECT_ROOT / "src"
ENTRY_POINT = SOURCE_ROOT / "doctor_workstation" / "__main__.py"
VIDEO_DIST = PROJECT_ROOT / "video_companion" / "dist"
RESOURCES = PROJECT_ROOT / "resources"
ENTITLEMENTS = PROJECT_ROOT / "packaging" / "macos" / "entitlements.plist"
VERSION_FILE = PROJECT_ROOT / "packaging" / "windows" / "version_info.txt"
MEDIA_SMOKE_HOOK = PROJECT_ROOT / "packaging" / "runtime_media_smoke.py"
if not ENTRY_POINT.is_file():
raise SystemExit(f"Application entry point is missing: {ENTRY_POINT}")
if not (VIDEO_DIST / "index.html").is_file():
raise SystemExit("Build video_companion before running PyInstaller")
if not MEDIA_SMOKE_HOOK.is_file():
raise SystemExit(f"Frozen multimedia smoke hook is missing: {MEDIA_SMOKE_HOOK}")
# Some Windows developer tools add an unrelated OpenSSL installation to PATH.
# PyInstaller's dependency scanner would then pair Python's ``_ssl.pyd`` with
# those incompatible DLLs. Put the running interpreter's DLL directory first
# and collect the exact same files explicitly so the build is reproducible.
python_runtime_binaries = []
if sys.platform == "win32":
python_dll_dir = Path(sys.base_prefix) / "DLLs"
for dll_name in ("libssl-3-x64.dll", "libcrypto-3-x64.dll"):
dll_path = python_dll_dir / dll_name
if not dll_path.is_file():
raise SystemExit(f"Python runtime dependency is missing: {dll_path}")
python_runtime_binaries.append((str(dll_path), "."))
os.environ["PATH"] = os.pathsep.join((str(python_dll_dir), os.environ.get("PATH", "")))
qt_webengine_hiddenimports = [
# Importing these modules lets PyInstaller's official Qt hooks collect the
# helper executable/app, resources, locales, frameworks, and plugins.
"PySide6.QtWebChannel",
"PySide6.QtWebEngineCore",
"PySide6.QtWebEngineWidgets",
"PySide6.QtNetwork",
"PySide6.QtPrintSupport",
]
qt_multimedia_hiddenimports = [
# These are intentionally explicit instead of relying on imports hidden by
# the application's optional media fallback. PyInstaller's official
# hooks collect Qt6Multimedia*.dll/.dylib/framework, plugins/multimedia,
# and the platform FFmpeg/native backend dependencies.
"PySide6.QtMultimedia",
"PySide6.QtMultimediaWidgets",
]
analysis = Analysis(
[str(ENTRY_POINT)],
pathex=[str(SOURCE_ROOT)],
binaries=python_runtime_binaries,
datas=[
(str(VIDEO_DIST), "video_companion_dist"),
(str(RESOURCES), "resources"),
],
hiddenimports=qt_webengine_hiddenimports + qt_multimedia_hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[str(MEDIA_SMOKE_HOOK)],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(analysis.pure)
is_macos = sys.platform == "darwin"
exe = EXE(
pyz,
analysis.scripts,
[],
exclude_binaries=True,
name="DoctorWorkstation",
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=os.environ.get("MACOS_CODESIGN_IDENTITY") if is_macos else None,
entitlements_file=str(ENTITLEMENTS) if is_macos else None,
version=str(VERSION_FILE) if sys.platform == "win32" else None,
)
collection = COLLECT(
exe,
analysis.binaries,
analysis.datas,
strip=False,
upx=False,
name="DoctorWorkstation",
)
if is_macos:
app = BUNDLE(
collection,
name="DoctorWorkstation.app",
icon=None,
bundle_identifier="com.zyt.doctor-workstation",
info_plist={
"CFBundleDisplayName": "甄养堂医生工作站",
"NSCameraUsageDescription": "用于视频面诊时采集医生画面。",
"NSMicrophoneUsageDescription": "用于视频面诊时采集医生语音。",
"NSHighResolutionCapable": True,
},
)