feat: 修复Mac打包编译

This commit is contained in:
duanshuwen
2026-04-11 17:22:29 +08:00
parent b1ca06bb07
commit 37ed157e4a
10 changed files with 191 additions and 1780 deletions

View File

@@ -0,0 +1,145 @@
# package:mac 打包诊断报告
**诊断时间**: 2026-04-11
**项目路径**: `/Users/duanshuwen/Documents/workspace/electron/zn-ai`
**执行命令**: `pnpm run package:mac`
---
## 1. 结论摘要
**本次打包失败不是因为项目源码缺少文件或 `electron-builder.yml` 配置项缺失,而是因为**
1. **网络下载中断**`electron-builder` 在构建 DMG 时需要下载 `dmgbuild-bundle-x86_64`,该请求被服务器中断(`ReadError: The server aborted pending request`)。
2. **并发锁竞争**`mac.target` 同时配置了 `x64``arm64` 两种架构,`electron-builder` 并行打包时两个进程争抢 `proper-lockfile` 的缓存锁,导致下载失败后的清理阶段抛出 `Lock file is already being held` 错误。
3. **(非致命)代码签名证书已过期**:本地唯一的 `Apple Development` 证书状态为 `CSSMERR_TP_CERT_EXPIRED`,因此 `electron-builder` 跳过了正式签名,仅做了 ad-hoc 签名。这不会导致打包中断,但会影响最终 app 在 macOS Gatekeeper 下的可运行性。
---
## 2. 关键错误日志
```text
• downloading release=dmg-builder@1.2.0 file=dmgbuild-bundle-x86_64-75c8a6c.tar.gz
...
ReadError: The server aborted pending request
...
Error: Lock file is already being held
at /Users/duanshuwen/Documents/workspace/electron/zn-ai/node_modules/proper-lockfile/lib/lockfile.js:68:47
...
ELIFECYCLE Command failed with exit code 1.
```
---
## 3. 配置与文件检查结果
| 检查项 | 状态 | 说明 |
|--------|------|------|
| `package.json` | 正常 | 存在且 `package:mac` 脚本定义正确 |
| `electron-builder.yml` | 正常 | 配置完整,`mac` / `dmg` / `win` / `linux` 分平台配置齐全 |
| `resources/icons/icon.icns` | 正常 | `mac.icon` 指向的文件存在 |
| `entitlements.mac.plist` | 正常 | 文件存在并已配置 |
| `dist` / `dist-electron` | 正常 | `vite build` 阶段成功通过,产物已生成 |
| 发布产物 | 部分生成 | `zip`x64 / arm64已成功生成但 DMGx64 / arm64因下载失败未完成 |
---
## 4. 详细原因分析
### 4.1 网络问题导致 dmg-builder 下载中断
`electron-builder` 在首次构建 DMG 时需要拉取预编译的 `dmg-builder` bundle`dmgbuild-bundle-x86_64-75c8a6c.tar.gz`)。由于该资源托管在 GitHub / AWS CDN 上,在国内网络环境下极易出现连接被重置或请求被服务器中断的情况。
### 4.2 并发构建加剧锁竞争
`electron-builder.yml` 中配置了同时打包两种架构:
```yaml
mac:
target:
- target: dmg
arch:
- x64
- arm64
- target: zip
arch:
- x64
- arm64
```
这导致 `electron-builder` 会并行启动多个打包任务。当它们同时尝试下载/解压同一个 `dmg-builder` 缓存时,`proper-lockfile` 产生竞争;一旦其中一个下载失败,另一个在清理阶段也会因无法获取锁而报错,最终整体构建失败。
### 4.3 代码签名证书过期(仅提示,不中断构建)
日志中出现的:
```text
skipped macOS application code signing reason=cannot find valid "Developer ID Application" identity ...
"Apple Development: 562304744@qq.com (Z27TQS657B)" (CSSMERR_TP_CERT_EXPIRED)
```
这说明本地证书已过期,不会影响打包流程本身,但生成的 `.app` 没有有效的开发者签名,分发后用户打开时会遇到 "已损坏,无法打开" 的 Gatekeeper 提示。
---
## 5. 解决方案与建议
### 方案 A分架构单独打包推荐最稳定
先避免并发锁竞争,同时降低单次构建对网络的敏感度:
```bash
# 仅打包 arm64Apple Silicon
cd zn-ai
npx electron-builder --mac --arm64 --publish never
# 仅打包 x64Intel
npx electron-builder --mac --x64 --publish never
```
若网络仍不稳定,可配置代理或手动下载缓存(见方案 B
### 方案 B配置 electron-builder 缓存
如果网络受限,可预先设置缓存目录并手动下载所需 bundle
```bash
export ELECTRON_BUILDER_CACHE="$HOME/.electron-builder-cache"
```
然后手动将 `dmgbuild-bundle-x86_64-75c8a6c.tar.gz` 放置到缓存目录的 `cache/dmg-builder` 子目录下,再执行打包。
### 方案 C修改 `electron-builder.yml` 降低并发
`mac.target` 里先只保留当前常用架构(如 `arm64`),需要时再切换:
```yaml
mac:
target:
- target: dmg
arch:
- arm64
- target: zip
arch:
- arm64
```
### 方案 D修复代码签名分发前必须
若计划将应用分发给其他用户,需要:
1. 在 Apple Developer 后台续期或重新申请 **Developer ID Application** 证书;
2.`notarize` 改为 `true` 并配置正确的 `teamId`
3. 在构建机器上安装新证书后重新打包。
---
## 6. 附录:构建产物现状
截至诊断时,`release/` 目录下已生成:
- `NIANXX-1.0.0-mac-x64.zip` (133 MB)
- `NIANXX-1.0.0-mac-arm64.zip` (129 MB)
- 对应的 `.blockmap` 文件
**未生成**
- `NIANXX-1.0.0-mac-x64.dmg`
- `NIANXX-1.0.0-mac-arm64.dmg`
原因即上述网络下载中断 + 并发锁竞争。
---
*报告结束*