diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..4cc4e25
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# 随仓库固定的第三方许可全文按 SHA-256 校验,Windows 检出不能转换换行。
+tools/licenses/** -text
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 96d0c62..076621c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,8 +1,11 @@
name: CI
+# PR 只读 Rust 缓存;main 推送负责写入,供后续 PR 和发行复用。
on:
pull_request:
branches: [main]
+ push:
+ branches: [main]
workflow_dispatch:
permissions:
@@ -16,6 +19,7 @@ jobs:
changes:
name: Changed paths
runs-on: ubuntu-latest
+ timeout-minutes: 5
outputs:
frontend: ${{ steps.filter.outputs.frontend }}
rust: ${{ steps.filter.outputs.rust }}
@@ -36,16 +40,18 @@ jobs:
needs: changes
if: needs.changes.outputs.rust == 'true'
runs-on: windows-latest
+ timeout-minutes: 45
steps:
- uses: actions/checkout@v7.0.1
- - uses: dtolnay/rust-toolchain@stable
+ - name: 安装 rust-toolchain.toml 固定的工具链
+ run: rustup toolchain install
+ - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
with:
- components: rustfmt, clippy
- - uses: Swatinem/rust-cache@v2
+ save-if: ${{ github.ref == 'refs/heads/main' }}
- name: fmt
run: cargo fmt --all -- --check
- name: clippy
- run: cargo clippy --workspace --all-targets -- -D warnings
+ run: cargo clippy --locked --workspace --all-targets -- -D warnings
- name: test
env:
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUNNER: powershell -NoProfile -ExecutionPolicy Bypass -File ${{ github.workspace }}/tools/run-windows-test.ps1
@@ -56,11 +62,10 @@ jobs:
needs: changes
if: needs.changes.outputs.frontend == 'true'
runs-on: ubuntu-latest
+ timeout-minutes: 15
steps:
- uses: actions/checkout@v7.0.1
- uses: pnpm/action-setup@v6.1.0
- with:
- version: 9
- uses: actions/setup-node@v7.1.0
with:
node-version: 24
@@ -80,14 +85,13 @@ jobs:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
+ timeout-minutes: 15
steps:
- uses: actions/checkout@v7.0.1
- uses: actions/setup-python@v7.1.0
with:
python-version: "3.12"
- uses: pnpm/action-setup@v6.1.0
- with:
- version: 9
- uses: actions/setup-node@v7.1.0
with:
node-version: 24
@@ -103,6 +107,7 @@ jobs:
needs: changes
if: needs.changes.outputs.ci == 'true'
runs-on: ubuntu-latest
+ timeout-minutes: 5
steps:
- uses: actions/checkout@v7.0.1
- name: 路径判断与汇总检查回归
@@ -115,6 +120,7 @@ jobs:
if: always()
needs: [changes, frontend, rust, native, ci]
runs-on: ubuntu-latest
+ timeout-minutes: 5
steps:
- uses: actions/checkout@v7.0.1
- name: 确认所需检查均已通过
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 13bc7d9..5986073 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -7,8 +7,9 @@ on:
tags: ['v*']
workflow_dispatch:
+# 只有 publish 需要写权限;构建 job 运行依赖脚本,保持只读。
permissions:
- contents: write
+ contents: read
concurrency:
group: release-${{ github.ref }}
@@ -18,33 +19,35 @@ jobs:
windows:
name: Windows x64 便携包与更新安装包
runs-on: windows-latest
+ timeout-minutes: 90
+ # 私钥只进需要的步骤,不暴露给依赖安装、构建脚本和测试。
env:
MPIDER_UPDATER_PUBLIC_KEY: ${{ vars.MPIDER_UPDATER_PUBLIC_KEY }}
- TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
- TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
steps:
- - uses: actions/checkout@v7.0.1
- - uses: pnpm/action-setup@v6.1.0
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
- version: 9
- - uses: actions/setup-node@v7.1.0
+ persist-credentials: false
+ - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: 24
cache: pnpm
- - uses: actions/setup-python@v7.1.0
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: '3.12'
- - uses: dtolnay/rust-toolchain@stable
- with:
- components: rustfmt, clippy
- targets: x86_64-pc-windows-msvc
- - uses: Swatinem/rust-cache@v2
+ - name: 安装 rust-toolchain.toml 固定的工具链
+ run: rustup toolchain install
+ - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
with:
key: release-windows-x64
workspaces: . -> target
cache-on-failure: true
+ # 标签之间不共享缓存;main 上的手动预演写入,标签只读取。
+ save-if: ${{ github.ref == 'refs/heads/main' }}
- name: 核对当前项目版本、标签与更新签名
+ env:
+ TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
run: node tools/release-updater.mjs prepare
- name: 安装验证依赖
@@ -52,11 +55,12 @@ jobs:
$PSNativeCommandUseErrorActionPreference = $true
pnpm install --frozen-lockfile
python -m pip install -r native/requirements.txt
- - name: 发行许可预检
+ - name: 发行依赖与许可预检
shell: pwsh
run: |
$PSNativeCommandUseErrorActionPreference = $true
python tools/collect-third-party-licenses.py --output (Join-Path $env:RUNNER_TEMP 'mpider-license-preflight') --cache dist-windows/.downloads
+ python tools/package-windows-release.py --prefetch --output dist-windows
- name: 类型、格式与 Rust 静态检查
run: |
$PSNativeCommandUseErrorActionPreference = $true
@@ -110,6 +114,9 @@ jobs:
- name: 构建带运行环境的 NSIS 与 MSI 安装包
shell: pwsh
+ env:
+ TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
+ TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: |
$PSNativeCommandUseErrorActionPreference = $true
# 与便携包共用 Windows x64 runner 的原生 target/release,复用已编译依赖。
@@ -128,7 +135,7 @@ jobs:
$sums | Set-Content release-assets/SHA256SUMS -Encoding ascii
- name: 留存完整发行包与验收记录
- uses: actions/upload-artifact@v7.0.2
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: mpider-windows-x64
if-no-files-found: error
@@ -137,7 +144,7 @@ jobs:
- name: 失败时留存已生成文件以便排查
if: failure()
- uses: actions/upload-artifact@v7.0.2
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: mpider-windows-partial
if-no-files-found: warn
@@ -154,12 +161,17 @@ jobs:
if: github.ref_type == 'tag'
needs: windows
runs-on: ubuntu-latest
+ timeout-minutes: 15
+ permissions:
+ contents: write
steps:
- - uses: actions/checkout@v7.0.1
- - uses: actions/setup-node@v7.1.0
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: 24
- - uses: actions/download-artifact@v8.0.2
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: mpider-windows-x64
path: release-assets
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8468c7f..3f95921 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,7 +4,7 @@
## 开发环境
-- Rust stable、Node.js 24+、pnpm 9+;只使用 pnpm,保留 `pnpm-lock.yaml`。
+- Rust(版本由 `rust-toolchain.toml` 固定,rustup 自动安装)、Node.js 24+、pnpm(版本由 `package.json` 的 `packageManager` 固定);只使用 pnpm,保留 `pnpm-lock.yaml`。
- 原生桥离线测试使用 Python 3.12,依赖固定在 `native/requirements.txt`。
- Windows 桌面构建还需要 MSVC C++ Build Tools、Windows SDK 与 WebView2,见[独立运行](docs/windows-standalone.md)。
- 当前原生采集只验证微信 4.1.15.56 x64。开发构建或跨平台测试通过不代表该平台可采集。
@@ -35,7 +35,7 @@ pnpm test
按改动范围补充有意义的回归。说明实际运行的平台、命令与结果,区分离线测试、桌面启动、真实请求和长期观察;没有验证的部分明确写出。
-日常 CI 仅由面向 main 的 PR 或手动操作触发,合并后的普通 main 推送不重复运行。PR 按路径选择任务:
+日常 CI 由面向 main 的 PR、main 推送或手动操作触发。main 推送按相同路径规则运行并写入 Rust 缓存,PR 只读取缓存。PR 按路径选择任务:
| 改动范围 | 执行的检查 |
| --- | --- |
diff --git a/README.md b/README.md
index f3127a3..b2bd07c 100644
--- a/README.md
+++ b/README.md
@@ -174,7 +174,7 @@ Tauri / React 提供界面,Rust 管理 SQLite、调度、请求策略和本地
## 开发与贡献
-开发需要 Node.js **24+**、**pnpm**、Rust stable;Windows 构建还需 Visual Studio C++ Build Tools 与 Windows SDK。改动在独立 Git worktree 中进行:
+开发需要 Node.js **24+**、**pnpm**、Rust(版本见 `rust-toolchain.toml`);Windows 构建还需 Visual Studio C++ Build Tools 与 Windows SDK。改动在独立 Git worktree 中进行:
```sh
pnpm install --frozen-lockfile
@@ -187,7 +187,7 @@ cargo test --locked -p mpider-core -p article-md -p mpider-tauri
pnpm tauri dev
```
-Windows 测试 runner、Python 离线测试和完整客户端构建见[Windows 构建说明](docs/windows-standalone.md)。日常 CI 在 PR 中按改动路径选择前端、Windows Rust、原生桥或 CI 配置检查,合并到 main 后不重复执行;纯公开资料只运行轻量路径判断与汇总,编入界面的更新记录、FAQ、实验室与请求策略文档仅触发前端检查。共享契约改动联动验证,手动触发可运行全部检查,详细规则见[贡献指南](CONTRIBUTING.md)。客户端发行仅面向 Windows x64,标签必须与项目版本一致,完成构建、离线测试、便携包解压自检与签名清单生成后创建 Release 草稿。
+Windows 测试 runner、Python 离线测试和完整客户端构建见[Windows 构建说明](docs/windows-standalone.md)。日常 CI 在 PR 中按改动路径选择前端、Windows Rust、原生桥或 CI 配置检查,合并到 main 后按相同规则运行并刷新 Rust 缓存;纯公开资料只运行轻量路径判断与汇总,编入界面的更新记录、FAQ、实验室与请求策略文档仅触发前端检查。共享契约改动联动验证,手动触发可运行全部检查,详细规则见[贡献指南](CONTRIBUTING.md)。客户端发行仅面向 Windows x64,标签必须与项目版本一致,完成构建、离线测试、便携包解压自检与签名清单生成后创建 Release 草稿。
[贡献指南](CONTRIBUTING.md) · [实现原理](docs/how-it-works.md) · [更新记录](CHANGELOG.md) · [第三方声明](THIRD-PARTY-NOTICES.md)
diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md
index 11370c1..0bf76a9 100644
--- a/THIRD-PARTY-NOTICES.md
+++ b/THIRD-PARTY-NOTICES.md
@@ -46,7 +46,7 @@ SOFTWARE.
| cffi | 2.0.0 | `runtime/session-deps/cffi-2.0.0.dist-info/licenses/`(LICENSE、AUTHORS) | [PyPI](https://pypi.org/project/cffi/2.0.0/) |
| pycparser | 2.23 | `runtime/session-deps/pycparser-2.23.dist-info/LICENSE` | [PyPI](https://pypi.org/project/pycparser/2.23/) |
-应用未修改这些运行环境组件。Frida 的 wxWindows 例外文本引用的 LGPL 全文从 [GNU 官方许可档案](https://www.gnu.org/licenses/old-licenses/lgpl-2.0.txt) 获取并固定摘要。微信与 Microsoft WebView2 不在便携包中再分发。
+应用未修改这些运行环境组件。Frida 的 wxWindows 例外文本引用的 LGPL 全文取自 [GNU 官方许可档案](https://www.gnu.org/licenses/old-licenses/lgpl-2.0.txt),原样保存在 `tools/licenses/Frida-COPYING.LIB` 并固定摘要,组装时不再联网获取。微信与 Microsoft WebView2 不在便携包中再分发。
## Rust、界面与字体依赖
diff --git a/docs/app-updates.md b/docs/app-updates.md
index 7ae026c..3a2d199 100644
--- a/docs/app-updates.md
+++ b/docs/app-updates.md
@@ -46,7 +46,7 @@ pnpm tauri signer generate -w ~/.tauri/mpider-updater.key
1. 核对发布提交与标签;本次项目版本为 `1.0.2`,标签应为 `v1.0.2`。保留历史 Release 与标签,不覆盖仍在服务用户的版本。
2. 按项目主线/开源发布流程准备发布提交。需要升级版本时,同时修改三个版本文件及锁文件;本功能不会自行修改项目版本。
-3. 将匹配当前项目版本的 `v*` 标签推送到 GitHub。工作流先核对版本与签名配置,再为 Windows x64 构建;缺少签名配置时标签发布立即失败。
+3. 打标签前在 main 手动运行 Release(`gh workflow run release.yml --ref main`)预演完整构建。预演只留存 artifact,不创建 Release,并写入后续标签可读取的 Rust 缓存。通过后将匹配当前项目版本的 `v*` 标签推送到 GitHub。工作流先核对版本与签名配置,再为 Windows x64 构建;缺少签名配置时标签发布立即失败。
4. Windows 构建成功后整理附件并生成 `latest.json`,创建 Release **预发布草稿**;保留完整便携 ZIP、自检与摘要,同时提供携带相同 Python 运行环境和完整许可证的 NSIS/MSI。Windows 更新默认使用 NSIS `-setup.exe`;MSI 仍提供手动安装。工作流不构建或上传 macOS 产物。
5. 检查产物、签名、Windows 清单并补充发布说明,再公开草稿。验收通过后发布为正式版本(取消预发布标记),客户端才会通过 latest 地址检测到该版本;保持预发布标记时不会被稳定更新通道选中。缺包、缺签名或缺平台时不生成可发布清单。
diff --git a/docs/windows-standalone.md b/docs/windows-standalone.md
index 63bb8a7..b74c90f 100644
--- a/docs/windows-standalone.md
+++ b/docs/windows-standalone.md
@@ -24,7 +24,7 @@ v1.0.2 包含独立监测、按公众号任务、Markdown/HTML 双格式导出
## 从源码构建
-构建环境:Windows x64、Visual Studio 2022 Build Tools(C++ 桌面开发及 Windows SDK)、Rust stable MSVC、Node.js 24+、pnpm 9+;组装完整发行包还需构建机 Python 3.9+。包管理器只使用 pnpm。
+构建环境:Windows x64、Visual Studio 2022 Build Tools(C++ 桌面开发及 Windows SDK)、Rust MSVC(版本见 `rust-toolchain.toml`)、Node.js 24+、pnpm(版本见 `package.json`);组装完整发行包还需构建机 Python 3.9+。包管理器只使用 pnpm。
在独立 Git worktree 中执行:
@@ -50,7 +50,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -File tools\build-windows.ps1 -Rel
## 发行包与验收边界
-`tools/windows-runtime.lock.json` 固定 Python 和 Windows wheels 的下载地址、版本与 SHA-256;构建时校验后原样保留 Python `LICENSE.txt`、wheel 的 `dist-info` 完整许可证,并补充 Frida wxWindows 许可引用的 GNU LGPL v2 全文。下载缓存只在忽略目录 `dist-windows/.downloads`。
+`tools/windows-runtime.lock.json` 固定 Python 和 Windows wheels 的下载地址、版本与 SHA-256;构建时校验后原样保留 Python `LICENSE.txt`、wheel 的 `dist-info` 完整许可证,并补充 Frida wxWindows 许可引用的 GNU LGPL v2 全文(随仓库保存在 `tools/licenses/`,同样校验 SHA-256)。下载缓存只在忽略目录 `dist-windows/.downloads`。
构建机还会从 Cargo/pnpm 依赖复制完整许可与字体 OFL,补回上游遗漏的许可文件;MPL 组件和部分缺声明组件的原版源码一并附带。详见包内 `THIRD-PARTY-NOTICES.md` 与 `licenses/dependencies/index.json`,该过程只在构建阶段依赖 Cargo/pnpm。
@@ -62,7 +62,7 @@ python tools/verify-windows-release.py --directory dist-windows\MPider-v1.0.2-wi
该检查只核对文件完整性、x64 PE、实际 Python/依赖版本以及虚构材料 AES-GCM 和当前用户 DPAPI 往返,不启动微信、不读取真实会话、不发送采集请求。**离线检查成功不代表真实采集或长期稳定性通过。**页面交互验收需在交互桌面另行进行,真实数据不得进入公开包。
-`.github/workflows/release.yml` 在 Windows 执行类型、Rust、Python、Node 离线检查后构建,并重新解压 ZIP 验证。手动触发只留存 Actions artifact;`v*` 标签必须与应用版本一致,只创建预发布草稿,核验后再公开。当前流程不发布 macOS 安装包,避免将旧代理工作流支持误认为新原生工作台支持。
+`.github/workflows/release.yml` 先下载并校验全部锁定依赖,再在 Windows 执行类型、Rust、Python、Node 离线检查后构建,并重新解压 ZIP 验证。手动触发只留存 Actions artifact;`v*` 标签必须与应用版本一致,只创建预发布草稿,核验后再公开。当前流程不发布 macOS 安装包,避免将旧代理工作流支持误认为新原生工作台支持。
## 数据与异常
diff --git a/native/requirements.txt b/native/requirements.txt
index c74c3e2..d14bfdc 100644
--- a/native/requirements.txt
+++ b/native/requirements.txt
@@ -1,3 +1,5 @@
-# 原生桥与会话协议的已验证依赖;不安装 frida-tools。
+# 原生桥与会话协议的已验证依赖,与 tools/windows-runtime.lock.json 保持一致;不安装 frida-tools。
frida==17.23.3
cryptography==50.0.2
+cffi==2.0.0
+pycparser==2.23
diff --git a/native/test_runtime_lock.py b/native/test_runtime_lock.py
new file mode 100644
index 0000000..bd6c05d
--- /dev/null
+++ b/native/test_runtime_lock.py
@@ -0,0 +1,19 @@
+import hashlib
+import json
+from pathlib import Path
+import unittest
+
+ROOT = Path(__file__).resolve().parent.parent
+
+
+class RuntimeLockTests(unittest.TestCase):
+ def test_vendored_licenses_match_locked_digests(self):
+ # 在 Windows 检出上提前发现换行被转换,避免等到长构建后的组装阶段才失败。
+ lock = json.loads((ROOT / "tools/windows-runtime.lock.json").read_text(encoding="utf-8"))
+ for item in lock["licenses"]:
+ data = (ROOT / item["path"]).read_bytes()
+ self.assertEqual(hashlib.sha256(data).hexdigest(), item["sha256"], item["filename"])
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/package.json b/package.json
index 36afda8..5dedf4f 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
"private": true,
"version": "1.0.2",
"type": "module",
+ "packageManager": "pnpm@10.29.2",
"description": "mpider 桌面外壳的前端 + Tauri CLI(前端源码在 frontend/,Tauri 壳在 src-tauri/)",
"engines": {
"node": ">=24"
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
new file mode 100644
index 0000000..6fc7331
--- /dev/null
+++ b/rust-toolchain.toml
@@ -0,0 +1,6 @@
+# CI、发行与本地开发共用同一版本;升级时改这里并单独验证 Clippy。
+[toolchain]
+channel = "1.99.1"
+profile = "minimal"
+components = ["rustfmt", "clippy"]
+targets = ["x86_64-pc-windows-msvc"]
diff --git a/tools/licenses/Frida-COPYING.LIB b/tools/licenses/Frida-COPYING.LIB
new file mode 100644
index 0000000..ede5d54
--- /dev/null
+++ b/tools/licenses/Frida-COPYING.LIB
@@ -0,0 +1,480 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ , 1 April 1990
+ Moe Ghoul, President of Vice
+
+That's all there is to it!
diff --git a/tools/package-windows-release.py b/tools/package-windows-release.py
index 86fadcb..986e792 100644
--- a/tools/package-windows-release.py
+++ b/tools/package-windows-release.py
@@ -75,28 +75,37 @@ def verify_pe(executable):
def main():
parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--exe", type=Path, required=True)
+ parser.add_argument("--exe", type=Path)
+ parser.add_argument("--prefetch", action="store_true", help="只下载并校验锁定的运行环境,在长构建前暴露网络问题")
parser.add_argument("--output", type=Path, default=ROOT / "dist-windows")
parser.add_argument("--revision", default="source-archive")
args = parser.parse_args()
- verify_pe(args.exe)
+ if not args.prefetch:
+ if args.exe is None:
+ parser.error("组装便携包需要 --exe")
+ verify_pe(args.exe)
version = json.loads((ROOT / "package.json").read_text(encoding="utf-8"))["version"]
lock = json.loads((ROOT / "tools/windows-runtime.lock.json").read_text(encoding="utf-8"))
+ requirements = (ROOT / "native/requirements.txt").read_text(encoding="utf-8").splitlines()
for item in lock["packages"]:
- if item["name"] in ("frida", "cryptography"):
- requirement = f"{item['name']}=={item['version']}"
- if requirement not in (ROOT / "native/requirements.txt").read_text(encoding="utf-8").splitlines():
- raise ValueError(f"运行依赖与锁定包不一致:{requirement}")
+ requirement = f"{item['name']}=={item['version']}"
+ if requirement not in requirements:
+ raise ValueError(f"运行依赖与锁定包不一致:{requirement}")
output = args.output.resolve()
output.mkdir(parents=True, exist_ok=True)
+ cache = output / ".downloads"
+ cache.mkdir(exist_ok=True)
+ if args.prefetch:
+ for item in (lock["python"], *lock["packages"]):
+ download(item, cache)
+ print(f"运行环境已就绪:{cache}")
+ return
package_name = f"MPider-v{version}-windows-x64"
stage = output / package_name
if stage.exists():
shutil.rmtree(stage)
runtime = stage / "runtime"
runtime.mkdir(parents=True)
- cache = output / ".downloads"
- cache.mkdir(exist_ok=True)
extract(download(lock["python"], cache), runtime)
# ._pth 维持嵌入式隔离;加入发行包内的依赖,忽略全局 Python/site-packages。
(runtime / "python312._pth").write_text("python312.zip\n.\nsession-deps\n", encoding="utf-8")
@@ -107,7 +116,11 @@ def main():
licenses = stage / "licenses"
licenses.mkdir()
for item in lock["licenses"]:
- shutil.copy2(download(item, cache), licenses / item["filename"])
+ # 全文随仓库固定:gnu.org 常拒绝构建机连接,不让发行卡在长构建之后。
+ source = ROOT / item["path"]
+ if digest(source) != item["sha256"]:
+ raise ValueError(f"许可全文摘要不匹配:{item['filename']}")
+ shutil.copy2(source, licenses / item["filename"])
subprocess.run([sys.executable, str(ROOT / "tools/collect-third-party-licenses.py"),
"--output", str(licenses / "dependencies"), "--cache", str(cache)], check=True)
# wheel 原有的完整 LICENSE/COPYING 及元数据原样留在 runtime/session-deps。
diff --git a/tools/windows-runtime.lock.json b/tools/windows-runtime.lock.json
index c781022..a6d783c 100644
--- a/tools/windows-runtime.lock.json
+++ b/tools/windows-runtime.lock.json
@@ -38,7 +38,8 @@
"licenses": [
{
"filename": "Frida-COPYING.LIB",
- "url": "https://www.gnu.org/licenses/old-licenses/lgpl-2.0.txt",
+ "path": "tools/licenses/Frida-COPYING.LIB",
+ "source": "https://www.gnu.org/licenses/old-licenses/lgpl-2.0.txt",
"sha256": "cc535c21133c895b56b374c8a1dc1eb948d99003ed2b47372069456b62f42b24"
}
]