Files
peoplelib/BUILD.md
T
lofyer 7ca023023e
构建与发布 / 单测与集成测试 (push) Waiting to run
构建与发布 / 打包 ${{ matrix.platform }} ${{ matrix.arch }} (arm64, linux, ubuntu-24.04-arm) (push) Blocked by required conditions
构建与发布 / 打包 ${{ matrix.platform }} ${{ matrix.arch }} (arm64, macos, macos-15) (push) Blocked by required conditions
构建与发布 / 打包 ${{ matrix.platform }} ${{ matrix.arch }} (x64, linux, ubuntu-24.04) (push) Blocked by required conditions
构建与发布 / 打包 ${{ matrix.platform }} ${{ matrix.arch }} (x64, windows, windows-2025) (push) Blocked by required conditions
构建与发布 / 发布 GitHub Release (push) Blocked by required conditions
feat: 增加 Linux 打包与 GitHub 构建发布链
新增 build-linux.js,直接从官方 zip 转写 tar 保住可执行位,
Windows 上也能构建 Linux 包。新增 build-release.js 作为发布件
唯一出口,排除便携版 data/、回读产物校验内容、生成校验和。
GitHub Actions 分测试、四目标打包、标签发布三段。
2026-08-05 19:07:11 +08:00

245 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 开发与构建
面向开发者的源码运行、打包、配置与架构说明。只想使用应用的用户请看 [README](README.md)。
## 源码运行与打包
源码开发需要 Node.js 22.19+
```bash
npm install
npm start
```
生成 Windows 免安装版到 `dist/`
```bash
npm run portable
```
输出目录固定为 `dist/PeopleLib-windows-x64/`,不随版本号变化,重复构建会保留其中的 `data/` 目录。构建前需退出该目录下正在运行的 `PeopleLib.exe`,否则会因文件占用而中止。
发布件不要手工压缩目录上传,用下面的发布打包入口生成,它会排除 `data/` 并附带校验和。
### Linuxx64 / arm64
```bash
npm run build:linux -- --arch x64
npm run build:linux -- --arch arm64
```
产出 `dist/PeopleLib-linux-<arch>.tar.gz`,解压后运行其中的 `PeopleLib.sh`
脚本直接把官方 Electron zip 里的条目转写进 tar,不落地中间目录,因此在 Windows 上也能构建出可用的 Linux 包。可执行位存在 zip 的 external attributes 里,先解压到 NTFS 再打包会把这些位全部丢掉,产物解压后 `PeopleLib``chrome-sandbox` 都不可执行。
多数发行版开启了非特权用户命名空间,无需额外配置。内核禁用该特性时(`kernel.unprivileged_userns_clone=0`),需给沙箱补 setuid
```bash
sudo chown root:root PeopleLib-linux-x64/chrome-sandbox
sudo chmod 4755 PeopleLib-linux-x64/chrome-sandbox
```
### macOSApple Silicon
**只能在 macOS 上执行**,且需要 Xcode 命令行工具(`xcode-select --install`):
```bash
npm install
npm run build:mac
```
产出 `dist/PeopleLib-macos-arm64/PeopleLib.app``dist/PeopleLib-macos-arm64.dmg`
不能在 Windows 或 Linux 上交叉构建,原因有两条,都无法绕开:
- DMG 由 `hdiutil` 生成,该工具只存在于 macOS。
- Apple Silicon 内核会拒绝执行未签名的二进制。打包过程要重命名可执行文件、修改 `Info.plist`,Electron 的原始签名必然失效,必须用 macOS 的 `codesign` 重新签名。
脚本使用 ad-hoc 签名(`codesign --sign -`),可以在本机及自行放行的机器上运行,但未经 Apple 公证。首次打开需右键点按图标选择「打开」,或执行:
```bash
xattr -dr com.apple.quarantine /Applications/PeopleLib.app
```
图标 `icons/dist/book-ai-*.icns` 已随仓库提供。源 PNG 变更后用 `npm run icons:icns` 重新生成,该脚本在任意平台都能运行,不依赖 macOS 的 `iconutil`
## 发布打包
`build-release.js` 是发布件的唯一出口,负责调用平台构建脚本、校验产物内容、生成校验和:
```bash
npm run release -- --platform windows --arch x64
npm run release -- --platform macos --arch arm64
npm run release -- --platform linux --arch x64
npm run release -- --platform linux --arch arm64
```
`--skip-build` 可复用已有的构建产物。输出落在 `dist/release/<platform>-<arch>/`,含发布件、`SHA256SUMS.txt``release-manifest.json`
发布前的校验是硬要求,不要跳过直接压缩目录上传:
- Windows 便携版把用户书库放在程序同级 `data/`,本机构建目录里通常有内容,手工压缩会把整个书库连同笔记打进公开发布件。脚本按前缀排除 `data/`,并在打包后回读压缩包确认。
- Linux 产物必须回读 tar 确认 `PeopleLib``PeopleLib.sh``chrome-sandbox` 带可执行位,丢了就是解压后点不开。
- 三个平台都会检查有没有混入 `_test`
汇总多平台产物时用回验模式,它逐个比对哈希、体积与版本,再汇总到 `dist/release-upload/`
```bash
npm run release -- --verify dist/release-downloads
```
## 持续集成
`.github/workflows/build.yml` 在推送 `main`、提交 PR、打 `v*` 标签和手动触发时运行,分三个阶段:
1. `validate``npm ci` 后跑单测与全部 Electron 集成套件。集成测试要开真实窗口,无头 runner 上用 `xvfb-run` 提供 X server。
2. `package`:四个目标并行打包(`windows-2025``macos-15``ubuntu-24.04``ubuntu-24.04-arm`),各自调用 `npm run release`,产物作为 artifact 保留 30 天。
3. `release`:仅在推送 `v*` 标签时执行,回验各平台校验和后创建 GitHub Release 并上传。
两个容易踩的点:
- 仓库 `.npmrc` 指向 npmmirrorGitHub runner 在境外拉不动,工作流用 `npm_config_registry``ELECTRON_MIRROR` 覆盖回官方源。
- 标签名必须与 `package.json``version` 一致(`v2.0.0` 对应 `2.0.0`),且标签要指向被构建的那个提交,两处校验不过直接中止发布。
Release 先建草稿、上传完再转正式,上传中途失败不会在页面上留下一个资产不全的版本。应用根据最新 Release 标签判断是否需要更新。
## 固定构建变体
PeopleLib 采用固定构建变体,不使用远程开关在应用发布后改变功能范围:
| 构建 | 定位 | 功能范围 |
|---|---|---|
| 桌面完整版 | Windows、macOS | 多源检索、下载与任务中心、数据源账号、代理、本地书库、阅读和笔记 |
| 移动阅读版 | iPadOS、Android | 本地导入、书库、阅读、笔记、书签和批注 |
移动阅读版固定关闭以下能力:
```js
{
remoteSearch: false,
remoteDownload: false,
sourceAccounts: false,
proxy: false
}
```
这些能力必须在构建时确定。移动端不展示相关入口、不注册对应桥接 API、不发起数据源请求,也不能通过服务端配置重新开启。桌面端继续保留完整功能。
移动端不能直接复用 Electron 包,需要使用独立的移动端外壳。下载、文件系统、安全存储和阅读文件访问均应通过 iPadOS/Android 原生桥接实现。首个移动版本只提供本地阅读能力;从系统文件选择器、分享面板或用户自行管理的云盘导入文件,不提供应用内在线检索和下载。
移动阅读版必须由专用脚本生成,不能依赖开发者手工删除页面或模块。计划提供以下固定入口:
```bash
npm run build:android
npm run build:ios
```
两个命令应调用同一套移动构建脚本,并把平台与固定变体显式传入,例如:
```bash
node build-mobile.js --platform android --variant reader-only
node build-mobile.js --platform ios --variant reader-only
```
`build-mobile.js` 必须完成:
1. 校验变体只能是 `reader-only`,拒绝从环境变量或远程配置开启受限能力。
2. 生成移动端能力清单,并在编译前固定关闭检索、下载、数据源账号和代理。
3. 使用移动端入口组装资源,不注册桌面端 IPC,不复制在线数据源模块。
4. 调用 Android 或 iOS 原生工程构建工具,并把产物输出到固定的 `dist/PeopleLib-android/``dist/PeopleLib-ios/`
5. 对最终产物运行自动化检查,确认不存在检索、下载、数据源账号和代理入口。
Android 构建可以在 Windows、macOS 或 Linux 上执行;iOS/iPadOS 构建依赖 Xcode、签名与 Apple SDK,只能在 macOS 上执行。
当前仓库尚未包含 `build-mobile.js` 与移动端原生工程,所以上述命令是必须补齐的目标构建入口,目前不能生成移动安装包。
## 配置
### 代理
在应用内「设置」填写代理地址,例如 `http://127.0.0.1:7897`。留空表示直连。配置会持久化,重启后仍生效,并应用于所有数据源请求与封面加载。
网络受限环境下,多数数据源需要代理才能访问。
### Z-Library 账号
「设置」中填入邮箱与密码即可登录。登录后可获取下载直链(免费账号有每日下载额度限制)。
> 凭据以 base64 混淆后保存在本地 `zlib-auth.json`**这只是防止肉眼直读,不是加密**。请勿在不受信任的机器上使用。
## 数据位置
| 模式 | 路径 |
|---|---|
| 开发运行(Windows | `%APPDATA%/PeopleLib` |
| 开发运行(macOS | `~/Library/Application Support/PeopleLib` |
| 打包运行(Windows 便携版) | 可执行文件同级的 `data/` 目录 |
| 打包运行(macOS | `~/Library/Application Support/PeopleLib` |
macOS 不采用便携布局:`.app` 内部在 DMG 挂载时只读,且覆盖升级会连同用户书库一并删除。
该目录包含:
- `library.json` 书库索引
- `settings.json` 应用设置(代理等)
- `zlib-auth.json` Z-Library 凭据与会话
- `covers/` 封面缓存
## 项目结构
```
main.js 主进程:窗口、IPC、代理与证书处理、文件下载
preload.js 渲染进程 API 桥接
src/
settings.js 设置持久化
library/store.js 书库存储
sources/
index.js 数据源注册表
http.js 统一 HTTP 层:超时、Cookie、代理
mirror.js 镜像故障转移
zlib-auth.js Z-Library 凭据存储
<source>.js 各数据源实现
ui/ 渲染进程界面
```
### 数据源接口
每个数据源模块导出以下结构:
```js
module.exports = {
id: 'example',
name: '示例源',
supportsSearch: true,
async list(page) // 浏览:{ items, maxPage, page }
async search(keyword, page) // 搜索:{ items, maxPage, page }
async detail(postId) // 详情:{ title, authors, cover, tags, brief, links }
async download(postId) // 下载:{ files, links }
};
```
新增数据源只需实现该接口,并在 `src/sources/index.js` 中注册。
### 网络层说明
- 主进程使用 Electron 的 `net.fetch`(Chromium 网络栈),代理通过 `session.setProxy` 生效
- 纯 Node 环境回退到 undici `ProxyAgent`(Electron 下不启用,该组合存在兼容问题)
- 所有请求默认 15 秒超时,可按调用点覆盖
- 失效镜像进入 5 分钟冷却,之后自动重试,避免站点恢复后被永久跳过
- **应用启动时全局忽略 TLS 证书错误**。这是为了兼容大量使用自签名或过期证书的镜像站点,代价是失去对中间人攻击的防护,请仅在受信任的网络环境中使用。
## 测试
单元测试:
```bash
npm test
```
数据源联通性检查,对主要数据源依次执行搜索、详情、下载链路,输出每一步耗时与结果:
```bash
npx electron test-search.js --proxy http://127.0.0.1:7897
```