a8148856 by 柴进

:pencil: spec 注释补充部署坑: 嵌套 symlink 被 NAS 传输打碎

lehe 那台 macOS 26 新包仍崩, 诊断发现不是打包问题:
  Frameworks/libtiff.6.dylib -> PIL/.dylibs/libtiff.6.dylib (broken)

PyInstaller 6.x 实际结构:
  PIL/__dot__dylibs/  <真目录>
  PIL/.dylibs -> __dot__dylibs  <内层 symlink, 被 NAS 吃掉了>
  Frameworks/libtiff.6.dylib -> PIL/.dylibs/libtiff.6.dylib  <外层 symlink>

内层 symlink 丢失 → 整条链断. 其他 macOS 26 机器能跑是因为挂载
NAS 的协议/客户端不同, 保 symlink.

记进 spec 注释, 下次再有人打包踩这坑直接看到结论.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8af666ed
......@@ -11,6 +11,15 @@ build_mac_universal.sh / build_windows.bat 只负责环境准备,
PyInstaller 把 @rpath 改写成 @loader_path/.. (= Contents/Frameworks/),
因此 .dylibs/*.dylib 必须平铺到 bundle 根目录。
部署坑 (不是打包问题, 但会让人误以为打包挂了):
- PyInstaller 6.x 会把 PIL/.dylibs 编码成 PIL/__dot__dylibs 目录,
再建一个 PIL/.dylibs -> __dot__dylibs 的符号链接.
- Frameworks/libtiff.6.dylib 又通过符号链接指向 PIL/.dylibs/libtiff.6.dylib,
是**两层嵌套 symlink**.
- 走 NAS (某些 SMB 挂载) / 邮件 / 某些解压工具传 .app 时, 内层 symlink
可能被吞掉, 导致打开时 dlopen 找不到 libtiff.6.dylib.
- 传输务必用 `tar czf` 或 `rsync -a`, 别用 cp / Finder 拖拽过 NAS.
策略 (三重保险):
1. PyInstaller 官方工具 collect_dynamic_libs(destdir='.') —— 推荐做法
2. 显式枚举 PIL/.dylibs/ 和 PIL/.libs/ —— 兜底
......