Flutter Hook 在 macOS 打包动态库时如何保留文件名中的点号?
结论
先检查 Flutter SDK 中生成 framework 名称的实现。DynamicLoadingBundled() 没有用于保留文件名点号的配置参数。如果打包时路径被改写,第三方代码仍按原路径加载,就会找不到库。
已核对的 Flutter master 源码中,frameworkUri() 允许 framework 名称包含点号。应先确认项目使用的 Flutter 版本是否包含这项修改。题目只提供了 Dart 版本,无法确定项目使用的 Flutter 修订,也不能直接指定某个 stable 版本一定能解决。Flutter framework 命名源码
为什么文件名会发生变化?
对于 DynamicLoadingBundled(),Flutter 的 macOS 打包逻辑会取出 code asset 所指向文件的文件名,交给 frameworkUri() 生成 framework 路径。注册的文件路径不是最终包内的路径,原 framework 的目录结构也不保证保留。Flutter macOS code assets 打包源码
题目中的变化:
bare-dns.2.1.4 → bare-dns214
与名称清理时过滤点号的行为一致,但仍需检查实际使用的 Flutter SDK,确认构建是否经过了这段逻辑。
需要区分两种加载方式:Dart 根据 code asset 映射加载库,以及第三方代码自行调用 dlopen() 加载库。第三方代码自行拼接的路径字符串不会随 Dart 的资源映射自动更新。
如何确认并处理?
1. 检查 Flutter 版本和名称清理规则
先记录 Flutter 的版本与修订:
flutter --version
再检查该 SDK 中的文件:
packages/flutter_tools/lib/src/isolated/native_assets/macos/native_assets_host.dart
重点查看 frameworkUri() 清理文件名所用的正则表达式。已核对的 master 实现包含:
fileName = fileName.replaceAll(RegExp(r'[^A-Za-z0-9._-]'), '');
字符集包含 .,因此这条规则会保留版本号中的点号。如果本地实现排除了点号,优先使用包含相应修改的 Flutter SDK,重新构建并验证。开发分支的源码不能证明当前安装的 stable 版本也包含相同逻辑。对应源码
2. 无法更换 SDK 时,调整第三方加载路径
如果第三方库允许配置动态库路径,可以让它使用实际打包后的路径。题目中产物的目标名称是:
bare-dns214.framework/bare-dns214
这只能解决加载入口的路径不匹配,还需要检查其他依赖库是否齐全,以及如何定位到应用的 Contents/Frameworks。不要直接把相对路径交给加载器并假定它会从应用目录开始查找。
如果加载路径硬编码在第三方库中,就需要修改其加载逻辑并重新编译,或使用允许点号的 Flutter 打包实现。
3. 必须保留原始布局时,考虑自定义嵌入流程
如果第三方组件依赖完整的原始 framework 布局,可以考虑通过 macOS 工程的复制、嵌入和签名流程管理这些 framework。采用这一方案时,应避免 DynamicLoadingBundled() 重复打包同一份库,并明确 Dart 侧或第三方代码如何加载它。
也可以临时修改 Flutter SDK 的名称清理规则,但需要固定 SDK 修订,并确保修改后的 Flutter tool 实际生效。仅编辑源码文件不能证明构建已经使用新规则。
如何验证修复结果?
重新构建后,检查最终 .app,不要只看 Hook 的输出目录。以下命令中的应用路径需要替换为实际路径:
APP="/path/to/MyApp.app"
find "$APP/Contents/Frameworks" -name '*bare-dns*' -print
如果保留点号的处理已经生效,应能找到名称包含 bare-dns.2.1.4 的 framework 和二进制。
如果文件已经存在但仍加载失败,可以继续检查 Mach-O 依赖:
otool -L "$APP/Contents/Frameworks/bare-dns.2.1.4.framework/bare-dns.2.1.4"
otool -L 展示链接依赖,不能列出代码运行时传给 dlopen() 的所有路径;这部分需要结合实际加载错误和第三方加载逻辑排查。
不要只靠手动重命名最终产物来修复问题。Flutter 的打包过程还涉及 install name、依赖引用和代码签名,仅修改目录名或二进制名称可能导致这些信息不一致。macOS 打包及依赖重写实现
备注:内容仅供参考。
