ZB100ImageGenerator.spec 2.36 KB
# -*- mode: python ; coding: utf-8 -*-
"""
PyInstaller spec for ZB100ImageGenerator.

跨平台构建配置的唯一真相源 (macOS + Windows)。
build_mac_universal.sh / build_windows.bat 只负责环境准备,
实际构建调用 `pyinstaller ZB100ImageGenerator.spec`。

修复点:
- macOS 上 PIL/_imaging.so 依赖 @rpath/libtiff.6.dylib 等原生库,
  PyInstaller 会把 @rpath 改写为 @loader_path/.. (= Contents/Frameworks/),
  因此 .dylibs/*.dylib 必须平铺到 bundle 根目录,而不是保留
  PIL/.dylibs/ 结构 —— 否则 dlopen 在启动时失败。
"""
import sys
from pathlib import Path

IS_MAC = sys.platform == 'darwin'
IS_WIN = sys.platform == 'win32'

# ----- 图标 -----
if IS_MAC:
    ICON = 'zb100_mac.icns'
elif IS_WIN:
    ICON = 'zb100_windows.ico'
else:
    ICON = None

# ----- 数据文件 -----
datas = [('config.json', '.')]
if IS_WIN:
    datas.append(('zb100_windows.ico', '.'))

# ----- Pillow 原生库:平铺到 bundle 根 -----
pil_native_libs = []
try:
    import PIL
    pil_dir = Path(PIL.__file__).parent
    for sub in ('.dylibs', '.libs'):
        d = pil_dir / sub
        if d.is_dir():
            for lib in d.iterdir():
                if lib.suffix.lower() in ('.dylib', '.so', '.dll'):
                    pil_native_libs.append((str(lib), '.'))
except Exception as e:
    print(f'[spec] WARN 枚举 PIL 原生库失败: {e}')

print(f'[spec] 将 {len(pil_native_libs)} 个 PIL 原生库平铺到 bundle 根目录')

a = Analysis(
    ['image_generator.py'],
    pathex=[],
    binaries=pil_native_libs,
    datas=datas,
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    [],
    exclude_binaries=True,
    name='ZB100ImageGenerator',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=[ICON] if ICON else None,
)
coll = COLLECT(
    exe,
    a.binaries,
    a.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name='ZB100ImageGenerator',
)

if IS_MAC:
    app = BUNDLE(
        coll,
        name='ZB100ImageGenerator.app',
        icon=ICON,
        bundle_identifier=None,
    )