Electron Forge打包含tfjs-node的Electron应用遇dylib链接错误求助
问题背景
本地运行Electron项目完全正常,但使用electron-forge打包时触发以下错误:
An unhandled rejection has occurred inside Forge:
Error: /var/folders/7w/spt6jhj57gl2gs0vcfcc_jqh0000gp/T/electron-packager/tmp-OpAoHn/Electron.app/Contents/Resources/app/node_modules/@tensorflow/tfjs-node/deps/lib/libtensorflow_framework.2.dylib: file "../../../../../../../../../../../../var/folders/7w/spt6jhj57gl2gs0vcfcc_jqh0000gp/T/electron-packager/tmp-OpAoHn/Electron.app/Contents/Resources/app/node_modules/@tensorflow/tfjs-node/deps/lib/libtensorflow_framework.2.7.0.dylib" links out of the package
at Filesystem.insertLink (/path/node_modules/@electron/asar/lib/filesystem.js:106:13)
at handleFile (/path/node_modules/@electron/asar/lib/asar.js:132:20)
at next (/path/node_modules/@electron/asar/lib/asar.js:148:11)
at next (/path/node_modules/@electron/asar/lib/asar.js:149:12)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async MacApp.asarApp (/path/node_modules/@electron/packager/dist/platform.js:200:9)
at async MacApp.buildApp (/path/node_modules/@electron/packager/dist/platform.js:124:9)
at async MacApp.initialize (/path/node_modules/@electron/packager/dist/platform.js:117:13)
at async MacApp.create (/path/node_modules/@electron/packager/dist/mac.js:321:9)
at async Promise.all (index 0)
at async packager (/path/node_modules/@electron/packager/dist/packager.js:237:22)
尝试过删除dylib文件(能打包但运行必崩)、切换Python版本,不想采用删除文件的钩子方案,因为业务依赖这些二进制文件,目标是让打包后的应用可移植到其他机器,无需命令行依赖。
环境信息
- 系统:OSX 14.4(M2芯片Mac)
- Python版本:2.7.18(此前用3.11.5,后更换为tfjs-node要求的2.7版本)
- 项目核心依赖:
"@tensorflow/tfjs-node": "^4.17.0", "@electron-forge/cli": "^7.3.0", "@electron-forge/plugin-auto-unpack-natives": "^7.3.0", "node-gyp": "^10.0.1"
更新:依赖检查结果
用otool -L命令检查dylib的外部依赖,确认所有依赖均为系统自带库:
1038:10:55~:: otool -L /private/var/folders/7w/spt6jhj57gl2gs0vcfcc_jqh0000gp/T/electron-packager/tmp-sePJID/Electron.app/Contents/Resources/app/node_modules/@tensorflow/tfjs-node/deps/lib/libtensorflow_framework.2.7.0.dylib /private/var/folders/7w/spt6jhj57gl2gs0vcfcc_jqh0000gp/T/electron-packager/tmp-sePJID/Electron.app/Contents/Resources/app/node_modules/@tensorflow/tfjs-node/deps/lib/libtensorflow_framework.2.7.0.dylib: @rpath/libtensorflow_framework.2.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1200.3.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.0.0) /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0) /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1853.0.0) /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1853.0.0) 1039:10:59~:: otool -L /private/var/folders/7w/spt6jhj57gl2gs0vcfcc_jqh0000gp/T/electron-packager/tmp-sePJID/Electron.app/Contents/Resources/app/node_modules/@tensorflow/tfjs-node/deps/lib/libtensorflow.2.7.0.dylib /private/var/folders/7w/spt6jhj57gl2gs0vcfcc_jqh0000gp/T/electron-packager/tmp-sePJID/Electron.app/Contents/Resources/app/node_modules/@tensorflow/tfjs-node/deps/lib/libtensorflow.2.7.0.dylib: @rpath/libtensorflow.2.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1200.3.0) @rpath/libtensorflow_framework.2.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.0.0) /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0) /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1853.0.0) /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1853.0.0)
解决方案
1. 修复dylib符号链接路径
错误根源是libtensorflow_framework.2.dylib等符号链接指向了打包临时目录的绝对路径,超出了asar包的范围。需要将符号链接改为同目录下的相对路径:
- 在项目根目录创建
scripts/fix-dylib-links.js脚本:
const fs = require('fs'); const path = require('path'); const tfjsLibPath = path.join(__dirname, '../node_modules/@tensorflow/tfjs-node/deps/lib'); // 修复libtensorflow_framework符号链接 const frameworkSymlink = path.join(tfjsLibPath, 'libtensorflow_framework.2.dylib'); if (fs.existsSync(frameworkSymlink)) { fs.unlinkSync(frameworkSymlink); fs.symlinkSync('libtensorflow_framework.2.7.0.dylib', frameworkSymlink); } // 修复libtensorflow符号链接 const tensorflowSymlink = path.join(tfjsLibPath, 'libtensorflow.2.dylib'); if (fs.existsSync(tensorflowSymlink)) { fs.unlinkSync(tensorflowSymlink); fs.symlinkSync('libtensorflow.2.7.0.dylib', tensorflowSymlink); } console.log('Dylib符号链接修复完成');
- 在
package.json的forge配置中添加前置打包钩子:
"config": { "forge": { "hooks": { "prePackage": "./scripts/fix-dylib-links.js" } } }
2. 确认auto-unpack-natives插件配置
已添加的@electron-forge/plugin-auto-unpack-natives插件会自动将native模块从asar包中解压,避免运行时加载问题,确保配置正确:
"plugins": [ ["@electron-forge/plugin-auto-unpack-natives", {}], // 其他插件配置... ]
3. 手动指定asar解压目录(可选)
如果上述方案仍有问题,可以在forge配置中强制指定tfjs-node的dylib目录不被asar压缩:
"packagerConfig": { "asar": { "unpack": "node_modules/@tensorflow/tfjs-node/deps/lib/**/*" } }
验证
执行npm run make打包后,检查打包产物内的Contents/Resources/app.asar.unpacked/node_modules/@tensorflow/tfjs-node/deps/lib目录,确认符号链接为相对路径,且对应的dylib文件存在。
内容的提问来源于stack exchange,提问作者Braden Roseborough

