mirai/docs/contributing
Him188 8ff64d4a7f
Remove native (#2700)
* Remove native target

* Add foojay-resolver-convention

* disable windows
2023-06-16 13:40:46 +01:00
..
building Remove native (#2700) 2023-06-16 13:40:46 +01:00
mock [mock] Add doc about disk allocation 2022-12-25 00:24:18 +08:00
ImplementingProtocol.md [docs] Update docs for contributing 2022-07-31 19:31:56 +08:00
README.md Remove native (#2700) 2023-06-16 13:40:46 +01:00
SimpleInstructions.md Remove native (#2700) 2023-06-16 13:40:46 +01:00
VerifyingABI.md [docs] Update docs for contributing 2022-07-31 19:31:56 +08:00

贡献

本文是关于向 mirai 贡献的指南。mirai 欢迎并感谢一切形式的贡献。

当前仓库 mamoe/mirai 包含 mirai 核心模块:

名称 描述
mirai-core-utils 一些工具类,供其他模块使用
mirai-core-api mirai 机器人核心 API
mirai-core mirai 机器人核心实现
mirai-core-all 上述三个模块的集合,用于启动器
mirai-console 插件模式机器人框架后端
mirai-console-terminal mirai-console 的终端前端
mirai-console-intellij IntelliJ IDEA 插件
mirai-console-gradle Gradle 插件
mirai-bom Maven BOM
mirai-logging 常用日志库转接器

若你想以非提交代码方式帮助 mirai可以为 mirai-console 编写插件并发布到论坛,或在论坛帮助新入门的朋友使用 mirai 等。

若希望提交代码,请继续阅读。

Git 分支

  • 1.x1.x 版本的开发 (已停止)
  • dev2.x 版本的开发(主分支);
  • -release 后缀:某个版本的小更新分支。如 2.10-release 会包含 2.10.x 小版本的更新;
  • 其他分支:正在开发中或留档的开发进度。

通常请基于 dev 分支进行修改。

基于版本规范 若一个修改适合发布为小版本更新mirai 会从 dev 中提取该修复到目标 -release 分支。

安装 JDK

需要安装 JDK 才能编译 mirai。mirai 主分支最新提交在如下环境测试可以编译:

操作系统 JDK 架构
macOS 12.0.1 AdoptOpenJDK 17 aarch64
macOS 12.0.1 Amazon Corretto 11 amd64
Windows 10 OpenJDK 17 amd64
Ubuntu 20.04 AdoptOpenJDK 17 amd64

若在其他环境下无法正常编译, 请尝试选择上述一个环境配置。

我不熟悉 Gradle 或 Kotlin / 我赶时间

SimpleInstructions 查看你可能想做的事情的简单命令。

mirai-core 术语

根据语境mirai-core 有时候可能指 mirai-core 这个模块,有时候可能指 mirai-core-utilsmirai-core-apimirai-core 这三个模块的整体。 本文中,mirai-core 将特指 mirai-core 模块,而用 'core' 或者 'mirai core' 指相关三个模块的整体。

core 多平台架构

core 三个模块都使用 Kotlin HMPP 功能,同时支持 JVM 和 Android 两种平台。你可以在 Kotlin 官方文档 了解 HMPP 模式。

core 的编译目标层级结构如图所示:

    common
    /    \      
  jvm   android 
发布平台名称 描述
jvm JVM
android Android (Dalvik)

备注:

  • common 包含全平台通用代码,绝大部分代码都位于 common
  • jvmBase 包含针对 JVM 平台的通用代码;

开发提示

建议使用 IntelliJ IDEA 或 Android Studio并安装最新的 Kotlin 插件。

建议设置 IntelliJ 的内存为至少 6GB否则 IDE 可能会频繁冻结编辑器收集垃圾。(可在 Help -> Edit Custom VM Options 中添加 -Xmx6000m

关闭部分项目以提升速度

你可以在项目根目录创建 local.properties,中按照如下配置,关闭部分项目来提升开发速度。在关闭后,请终止所有 Gradle 后台进程,以保证更改正确应用。

# 关闭 IntelliJ IDEA 插件模块,这可以避免下载 1~2GB 的依赖
projects.mirai-console-intellij.enabled=false
# 关闭 Gradle 插件模块
projects.mirai-console-gradle.enabled=false
# 关闭 mirai 依赖测试模块
projects.mirai-deps-test.enabled=false
# 也可以用其他模块的路径替换 module-path可关闭该模块
projects.module-path.enabled=false
# 特殊配置,关闭 mirai-console 后端,这同时也会关闭全部 console 相关的项目
projects.mirai-console.enabled=false
# 特殊配置,关闭 mirai-logging这会关闭所有日志转接模块
projects.mirai-logging.enabled=false
# 特殊配置,是否取消指定 jvmToolchain在本地 jvmTest 中需要访问 JDK 9+ 的内容时需要携带此配置
mirai.enable.jvmtoolchain.special=false

通常关闭 IDEA 插件和 Gradle 插件可以显著提高初始化速度IDEA 插件项目在初始化时需要下载 1G 左右编译依赖)。

关闭 core 的部分构建目标

可以在上述 local.properties 中,配置 projects.mirai-core.targets= 使用以下配置语法关闭部分构建目标。关闭后可以减轻 IDE 负担,也可以避免下载工具链而加快初始化速度。

所有目标默认都启用。

注意,在关闭一个目标后,将无法编辑该目标的相关源集的源码。 因此若非主机性能太差或在 CI 机器运行,不建议关闭目标。

  • xxx:显式启用 xxx 目标
  • !xxx:显式禁用 xxx 目标
  • others:显式启用其他所有所有目标
  • !others:禁用没有显式启用的所有目标

其中 xxx 表示构建目标名称。可用的目标名称有(区分大小写):jvmandroid

# 只启用 `jvm` 目标,禁用其他所有目标 (Android)
projects.mirai-core.targets=jvm;!others

# 启用 `jvm` 和 `android` 目标
projects.mirai-core.targets=jvm;android

直接启动 mirai-core 本地测试

一般情况下, 只要 JVM 平台测试通过其他平台也能测试通过。

在 JVM 平台直接启动 mirai-core, 见 mirai-core/jvmTest

构建 mirai 项目 JAR

查看 Building

部署 mirai 到本地仓库

要部署 mirai 项目到本地 Maven 仓库Maven Local只需使用如下命令其中 2.99.0-local 可为任意想在本地仓库发布的版本号。

./gradlew publishMiraiArtifactsToMavenLocal "-Dmirai.build.project.version=2.99.0-local"

注意,因为构建默认启用多线程,此操作可能会占用约 32GB 内存。如果主机条件不足,或希望减少内存占用,可以如下方式禁用多线程加速:

./gradlew publishMiraiArtifactsToMavenLocal "-Dmirai.build.project.version=2.99.0-local" "-Porg.gradle.parallel=false"

随后可通过 implementation("net.mamoe:mirai-core:2.99.0-local") 引入项目。

由于 mirai 项目结构复杂构建可能由于各种原因失败mirai 提供依赖可用性测试。 部署一份版本为 2.99.0-deps-test 的 mirai 到本地仓库,执行 ./gradlew :mirai-deps-test:test 即可运行相关测试。若测试通过,则代表部署的项目可通过各种方式正常引入到其他项目。

通过 Gradle Composite Build 引入 mirai

若在 Gradle 通过 Composite Build 引入 mirai则在编译时可能遇到依赖冲突问题。 mirai 使用特定版本的 Ktor 2、kt-bignum 等库,会将它们的包名增加前缀 net.mamoe.mirai.internal.deps. 来避免产生冲突。 但这个操作仅对部署的版本有效,在 Gradle 中构建时,仍然可能会有依赖冲突。但若在测试中没遇到问题,一般不用担心。

要详细了解这个过程以及实现原理,请查看 源码(含注释)。

寻找待解决的问题

可以在 issues 查看 mirai 遇到的所有问题,或在里程碑查看版本计划.

里程碑 为各版本的开发计划. 在完成所有任务后就会发布该版本.

Backlog 为没有设定目标版本的计划. 如果有相关 PR, 这些计划就可能会被确定到一个最近的版本.

开发文档

本节列举为了帮助开发某些模块的文档。

提交高质量的 commit 以及 PR

mirai 由社区驱动,审核者在业余时间审核 PR。这些规范性建议将帮助你提交高质量的 commit 和 PR同时节约你和审核者的时间最大程度地帮助 mirai也能帮助你在其他项目提交同样高质量的 PR。

如果你不太保证自己能达到这些要求也没关系mirai 感谢你花费的每一分钟,维护者会审核 PR 并尽可能帮助你。

代码规范

  • 请在 Kotlin 模块使用纯 Kotlin 实现。
  • 尽量不要引用新的库
  • 遵守 Kotlin 官方代码规范(提交前使用 IDE 格式化代码即可 (commit 时勾选 'Reformat code')

为 Java 做兼容

mirai 使用 Kotlin 编写,大量使用 Kotlin 协程等语言级特性。为了能兼容 Javamirai 使用 Kotlin 编译器插件 KJBB 。KJBB 会为 Kotlin 挂起函数生成一个辅助方法来允许 Java 调用。在开发时只需要:

  • 安装 IDE 插件 kotlin-jvm-blocking-bridge

  • 若要添加一个 suspend 函数, 为它添加 @JvmBlockingBridge 注解即可允许 Java 调用

确保二进制兼容性

请在提交前进行 ABI 验证

代码注释语言

内部实现的注释可以使用英文或中文(无变体要求)。公开 API 的注释KDoc请只使用简体中文且无需提供翻译。

编写高质量的文档

mirai 在乎质量,这也包括文档质量。根据 mirai 的历史 PR许多贡献者容易忽视下列问题

  • 汉字与英文或数字之间需要有空格
  • KDoc 语法衍生于 Markdown 语法,没有空行的换行会被压缩为一行,因此需要有正确的标点符号结束一句话

可以阅读 中文技术文档的写作规范 了解如何编写高质量的中文文档。为了方便,在 mirai 代码文档和注释中可以使用英文标点符号。但在编写 docs 目录中等的 .md 正式文档时,请遵守写作规范。

PR 标题

编写 PR 标题时,可以使用英文或中文。正确描述 PR 的修改,避免 "修复了一个 bug" 这类模糊标题即可。

会如何合并 PR

由于仓库庞大mirai 主分支(dev)维护线性提交历史来确保历史的可读性。这意味着主分支不允许有 merge 操作,只允许基于分支最新提交的提交。

一般 PR 会以 squash 方式合并,即 PR 的所有 commit 都会被合并为一个 commit并由审核者拟定标题。这个标题通常会直接采用 PR 标题(如果符合规范)。

若提交的 PR 需要以多个步骤完成,且 PR 的提交概述符合约定,审核者通常会以 rebase 方式合并 PR即 PR 的 commit 会被重置到基于最新 dev 分支并按顺序并入。

commit message

由于很多 PR 会以 squash 方式合并可以不需要遵守本节的提交概述commit message的约定。

编写提交概述以及 PR 的标题时,可以使用英文或中文。

由于代码量庞大,请在提交概述包含涉及模块名称。模块名称可以是 [core][console][idea][gradle][build] 。如有必要,还可以添加子模块名称如 [core/native] 表示 mirai-core 中的 native 部分。

mirai 不要求将 commit 为了区分新功能或修复 bug 而特地使用 fix:feat: 等前缀(允许你认为的合理的使用,或是你更喜欢这样区分)。只需要用最合适的语言描述修改。如 Optimize gradle properties

请以标准英文句子语法编写提交概述,可省略末尾标点符号。如 Configure shadow relocation, and add checks for multiplatform publishing.Optimize gradle properties

确保 PR 只解决一类问题

一个 PR 只能解决一个(类)问题,比如 "支持视频消息"、" 修复无法发送图片的问题"、"修复一些消息类型无法序列化的问题"。 等。当解决一类问题时,请规范 commit 来区分解决这类问题的步骤(如果有必要)。

确保 commit 的可阅读性

一个 PR 只能包含能通过 commit message 描述的对一个部分的修改。比如 "更新 console 文档" 、"Add logger for NetworkHandler" 等。

commit 必须不带有或指明必要的副作用。例如名称为 "修复无法发送图片的问题" 的 commit 却修改了对消息长度的限制是不好的。此时一个恰当的概述为 " 调整消息长度限制, 修复无法发送图片的问题" (修改内容 + 修改带来的影响)。

若要修复某一个 issue请不要仅提交 "fix #123"。请附带具体修复内容,把修复 issue 作为"修改带来的影响"。例如 "调整消息长度限制, 修复无法发送图片的问题, fix #123"。("fix #123" 会触发 GitHub 自动链接 issue 到 PR

PR 在有审核后避免 force push

PR 在有人审核review请不要进行 force pushgit push -f ),否则将可能会导致审核人需要重新审核你的全部代码——这会浪费大量时间。请在收到 approve 的 review 并且 PR 被标记 ready-to-merge 之后再进行 force push 优化提交历史。当然即使不优化提交历史PR 也会在合适的时机使用 squash 方式合并。

在有审核之前可任意 force push。