欢迎提交可复现的问题、补充设备测试、修正文档,或改进代码。开始前先搜索已有 Issue 和 PR,避免重复工作。
问题反馈使用问题模板,写清游戏名与版本、设备与系统、包号、复现步骤和实际现象。诊断导出方法见使用教程。
准备修复代码或实现功能时,先查看可领取任务,在对应 Issue 说明范围并按协作循环认领。不对应任务卡的新功能先开 Issue 写一句方案,维护方 1 小时内回「做 / 不做 / 换做法」后再动手;错字、失效链接等文档小修可以直接提 PR。可领取任务开出 24 小时没人认领,维护方会收回自己做。
从最新 origin/main 创建自己的分支,名称可用 docs/<主题>、runtime/<主题> 等。Android 也从最新 origin/main 开始;旧 android/integration 已于 10-27 冻结。不要直接推送 main,也不要修改他人的分支。
动手前阅读仓库规范、代码风格和相关模块设计,按问题检索坑记录与研究目录。AI 代理还应先读 AGENTS.md。性能、能耗或稳定性改动须遵守测量与开发经验。
在仓库根目录检查开发工具:
bash tools/doctor.sh检查只读取环境,不安装或下载依赖。开发与测试主要使用 Apple 芯片 Mac;完整要求及安装方法见开发测试套件。当前工具链的主要入口如下。
| 工具 | 版本与配置来源 |
|---|---|
| Xcode | 统一使用 Xcode 27.1,路径和部署目标见 tools/toolchain.env |
| .NET SDK | 微软官方 .NET 10 SDK,具体版本与滚动策略见 global.json;Homebrew 源码构建版的 NativeAOT 链接限制见环境检查输出 |
| Python | 3.12 或更新版本;改写器依赖见 tools/rewriter-requirements.txt |
| bash | 5 或更新版本;macOS 自带的 bash 3.2 不满足开发检查要求 |
编译配置中的最低部署版本与已经验证的游戏运行范围分别维护;玩家使用要求见中文 README。下面三条构建路径按改动对象选择。
make host 生成 build/s2arm-host,默认用于原生层开发;需要完整系统服务与图形接入时加 S2A_CS=1。它构建运行组件,Mac 启动器应用另按下一节构建。
make host
make host S2A_CS=1
make testmake test 运行仓库登记的单元测试,部分检查需要额外工具或测试资源。怎样用自己的游戏启动、记录日志和判读结果,见开发测试套件。
先跑一键准备:检查 Xcode / Metal、.NET SDK(按 global.json 的版本与滚动规则,由 dotnet 自己判定)、Homebrew 工具、Rust,建构建用 venv(缺省本树 build/venv)装齐钉版 Python 依赖(含字体生成器的 fonttools / skia-pathops),并准备 C 改写器固定依赖(build/rewriter-deps)。缺什么逐项列出并给装法;Metal 编译器版本与锁文件不同只出 note。
python3 launchers/macos/prepare_build.py
build/venv/bin/python3 launchers/macos/build_app.py产物为 build/macos/S2Arm.app,build_app.py 缺运行环境时自己调 bundle_runtime.py。命令行出包与跑测试前把 S2A_PY 指向同一个解释器(环境变量,或写进 tools/machine.local,见 tools/machine.local.example)。依赖表、组件审计和调试方法见 Mac 构建指南。
只需要出包时,可先运行专用环境检查,再将示例路径替换为自己的路径:
python3 pack/jobs/applenv.py
bash pack/oneclick/oneclick.sh "/absolute/path/to/game" --keys "/absolute/path/to/prod.keys"这条命令生成 IPA 与资源包。具体参数、输出目录、签名和真机运行步骤见开发测试套件及使用教程。Android 构建入口见平台文档。
仓库根目录的 LICENSE 是 Apache License 2.0。版权人写 S2Arm contributors(仓库没有另写一个个人或公司作为整体版权人)。第三方组件各自的许可不因此改变,清单在 NOTICE 和 第三方依赖。
新写的源文件在文件头加两行,年份用首次提交的年份:
SPDX-License-Identifier: Apache-2.0
Copyright 2026 S2Arm contributors
不要为了补头去批量改已经在库里的文件。第三方文件、从上游原样拿来的文件,保留原来的版权声明和 SPDX-License-Identifier,不要改成 Apache-2.0。改到第三方文件时,在文件头说明改了什么(Apache-2.0 第 4(b) 条)。
| 改动目录 | 要跑的检查 |
|---|---|
runtime/ |
make host + make test + bash runtime/gate.sh |
graphics/ |
bash graphics/gate.sh |
translator/ |
make test(改写器相关单测) |
services/ |
bash services/gate.sh;改了跨平台接缝还需 bash tests/platform_scan_test.sh |
pack/ |
python3 pack/jobs/applenv.py + make test(pack 相关单测) |
launchers/ |
python3 launchers/macos/prepare_build.py + build/venv/bin/python3 launchers/macos/build_app.py |
android/ |
bash android/test.sh(无设备 CPU 测,见 安卓平台文档);Linux 上另跑 bash android/linux_ctest.sh |
docs/ 或 *.md |
python3 tests/docs_consistency_test.py;本地链接可用 make lint 自查(自愿工具,见下文「验证改动」) |
| 任意改动 | bash tools/contrib_check.sh --base origin/main(一级自检,提 PR 必跑) |
Linux 暂不支持。跑不了的步骤写清原因和未测范围,不省略。
先运行与问题对应的最小充分检查,确认修复覆盖原场景。文档和配置检查内容、链接、格式及实际配置行为;运行代码需要验证受影响的调用路径。界面、设备、图形和性能结论应附对应运行证据,不能用编译成功代替。
完成本地 Git 提交、确认已跟踪文件没有未提交修改后,运行贡献者自检:
bash tools/contrib_check.sh --base origin/main自检按改动范围选择本机可运行的检查,在流程末尾将摘要写入 build/contrib_check/summary.md。若前置检查提前退出,摘要可能未刷新,应以本次终端报错为准,不引用旧摘要。退出码及含义见下方从实际自检脚本生成的规则块。缺工具或其他阻塞要写清原因、影响和未测范围;修复后重跑相关检查。自检未通过时可以提草稿 PR,说明卡点。
需要维护者机器、游戏资产或真机的第二层检查由维护者处理。PR 审查后,维护者通过合入队列统一运行门禁;贡献者无需自行重复整套维护者门禁,职责与路由见协作循环。
格式工具由开发者自愿使用,不是新增合入要求:
make style-setup # 手动安装固定版本工具,需要网络
make format-check # 检查增量格式
make lint # 静态问题、文档链接与日志事件设计- 分道成批。 按改动范围分三道:只改文档的、只改工具 / 测试 / 出包脚本的(tool 档)、动到产品代码的(full 档)。同一道里排着的分支合成一批,只跑一份门禁;两档上限见下方生成规则块,可用相应环境变量覆盖。
- 推测流水。 full 道排着不止一批时,下一批不等上一批出结论,直接在上一批的确切合并结果上同时跑门禁。上一批原样合入后,下一批立刻推送;上一批红了,下一批作废、留队重跑,不会因此被退回。
你看到「一个一个在验证」,通常是下面几种情况:
- 红批归责。 先排除偶发和已知红,再核干净 main。能定位改动文件/路由时隔离相关支;确属 main 的红不归责任何一支。相关支的分批、并行深度和逐支核规则见下方生成块。推送时 main 前进则补核受影响步骤,不把旧输入结论用于新输入。
- 单跑。 急件(主线修复、换链合批)由维护者设为单跑,下一轮只取这一支。今天共 5 次。
- 换链窗口。 会改直连翻译链号的分支不随到随合,攒到窗口里一起合,链号一次只换一次。
- 道里只有你一支。 队列空的时候就是单支批。
以下内容由 python3 tools/docs_consistency.py --render 从实际脚本生成;修改后用同一工具核对。
- 批上限:快档
TRAIN_BATCH_MAX缺省 10 支;full 档TRAIN_FULL_MAX缺省 5 支。 - 红批归责:先按红行/红步定位并隔离相关支;无关支只继承输入未变的检查结论。相关支多于
TRAIN_BISECT_MIN(缺省 2)时,实际seqchk会对半分批,只核红步及两半共路由的步骤;并行深度低于TRAIN_PAR_DEPTH(缺省 2)时两半同时跑,到上限后先后跑;不满足分批条件时逐支核。路由不明则跑整份门禁。 - 自检退出码:
0第一层本机已证通过(待宿主/第二层仍单列);1有红;2不完整或参数/基线错误;75环境未就绪;130被中断。
你能让批次更顺:
- 入队前在合并后的状态下跑自检(
bash tools/contrib_check.sh --base origin/main)。红的分支进车会让整批陪跑一轮归责。 - 一个 PR 只做一件事,并在入队前合入最新
origin/main。冲突会被直接退回,不进门禁。 - 尽量少改公用登记文件(路由表、源文件清单这类每加一个文件就要改一处的清单)。两个分支同改一行就会冲突,这类文件正在逐个改成按目录自动发现。
- 修好了
docs/名单_能力强信号/<程序号>.tsv登记过的问题(某款的满屏 / 60 帧已知坏),请在同一个 PR 里删掉那一行并写明复测依据; 实现改了这条不会自动撤,会标「过时·待重新实测」并保持关(python3 tools/caps_policy.py retest列出复测清单)。
按 PR 模板写清关联 Issue、问题、最终改动、实际验证和未测项,附上本次一级自检摘要;若前置检查提前退出,附上本次终端报错。改共用目录时说明苹果路径受影响的范围及验证依据。标题可用 fix(native): 修复地址窗口探测 这样的格式。
分支要短:一个 PR 只做一件事,目标几小时内合入;做不完就拆成几个能各自验收的 PR。开了 24 小时还没合入,巡检会提醒「合最新 main 或拆小」;48 小时标 待拆。main 红了先修 main:你的合入把 main 弄红了,当轮修,修好前不在同一块继续堆改动。细则见 协作循环 §3.4。
保持一个 PR 的目标集中,避免混入无关格式化或目录搬迁。公共 ABI 改动要同步调用双方、文档和测试;改 Ryujinx 时按补丁流程提交源码、补丁、series 与改动清单,不只提交 tree/ 的修改。
- 游戏文件、固件、密钥、资源包和存档不进仓库,也不上传到 Issue、PR 或评论;诊断附件提交前检查脱敏结果。
- 从游戏派生的东西同样不进仓库:反编译 / 反汇编 / 重编译输出、改写后的游戏模块、从游戏着色器编出的 metallib / 着色器包、游戏截图和录像。测试只用原创的合成夹具。
- 项目永远不提供:打好的 IPA / APK 成品、AltStore / SideStore 软件源、预先改写好的游戏模块、获取密钥或固件的方法。Issue / PR 里请求这些的,一律不回应具体做法。
- 签名私钥、描述文件、令牌和个人配置保存在本地。
.gitignore只防止常见误加入,提交前仍须检查实际差异和附件。 - 清理只处理归属明确、可重建的产物,保留游戏库、存档与他人的运行目录。进程组信号使用
tools/safe_killpg.sh;测试与门禁不得隐式下载依赖。 - 新增或升级第三方代码时,保留来源、版本和许可,并更新第三方依赖。
AI 辅助贡献见 LLM_POLICY.md,社区交流见 CODE_OF_CONDUCT.md。内部协调和维护者合入流程继续见联合开发者指南与协作循环。
旧仓库上的补丁可以用 python3 tools/port_old_patch.py <补丁文件> 把路径换成当前目录结构,再 git apply。映射不到的文件会列出来;正文对不上的部分需要手工合并。