Skip to content

自定义编译器 ​

Jugg 支持通过自定义编译器 SPI 扩展内置增量编译链。自定义编译器可以在 asset、resource、source、minify、dex 等阶段前后插入逻辑,处理项目特有的生成、转换或校验需求。本页说明接入能力和常见插入点,加载与阶段边界见自定义编译器原理。

支持的接入方式 ​

场景当前支持情况用户可见结果
本地 jar 自定义编译器支持本地扩展逻辑可进入 Jugg 编译链
远端 jar 自定义编译器支持远端扩展下载校验后参与编译
阶段前置处理支持可在内置阶段前消费或改写输入
阶段后置处理支持可在内置阶段后处理产物
源码编译前生成 Java支持项目提供的适配器Java/Kotlin 注解输入可交给项目处理器,生成 Java 继续参与本轮编译
扩展执行失败支持扩展编译逻辑抛出异常时,当前任务失败并给出可见提示

接入方式 ​

自定义编译器以 jar 提供。扩展需要实现 ICompilerCreator,由它为当前编译上下文创建 ICompiler;Jugg 通过 SPI 加载 jar 中的实现。

项目后台只需在 customCompilers 配置中声明 jar 文件名、路径和 md5。路径可以是本地绝对路径、相对项目目录的路径或 HTTP / HTTPS 地址。

ARouter 的 @Route、@Autowired、@Interceptor 已有内置增量处理,无需下发适配器。项目需保留自己的处理器依赖:APT/KAPT 使用 AROUTER_MODULE_NAME 或 moduleName,KSP 使用项目实际的 AROUTER_MODULE_NAME 或 MODULE_NAME 参数。Jugg 比较本轮源码与现有业务 class 中的相关注解值、字段类型、路由身份和必要继承关系,确认变化后才收集完整模块输入、运行项目处理器;生成 Java/Kotlin 继续参与本轮编译。同值常量、显式默认值、属性顺序、等价 import/alias、普通方法体、注释和格式变化不会重新生成。已消费索引不会反复加入普通轮次。

含 Kotlin 的模块在生成时纳入完整 Java/Kotlin 业务源码,因此新 Kotlin 类型即使没有 ARouter 注解、尚未生成 class,也能参与本轮类型解析。使用 APT/KAPT 时,混合模块通过 KAPT 完成生成,支持 Kotlin typealias 导入;纯 Java 模块使用 Java 注解处理路径。使用 KSP 时,Jugg 运行项目版本的 KSP1 compiler plugin 或 KSP2 Analysis API 引擎,透传当前变体参数,并纳入 commonMain/androidMain 输入;只消费本轮成功生成物。两条路径均仅运行选定的 ARouter processor;同时声明两种 ARouter 处理器时明确失败。生成成功后,产物才进入后续源码编译。

ARouter 生成成功且生成类集合检查通过后,Jugg 会将本轮生成源码同步到当前变体的生成源码目录,供 IDE 查看与跳转。同步只覆盖本轮文件,保留其他处理器的产物。同步失败时打印 warn,编译继续使用 Jugg 保存的生成源码;IDE 中的部分生成源码可能仍是旧版本。源码同步成功不代表后续编译或部署成功。

只修改路由常量时,已有常量引用分析先把使用方送入跟编。即使使用方文本未变化,Jugg 仍读取当前常量值,确实影响注解结果才重新生成。ARouter 与 Kuikly 在同一轮共用源码读取和语法分析结果。

业务 class 由正常 Java/Kotlin 编译维护。Jugg 按声明身份及源码归属关联同文件多类、嵌套类和移动后的声明;新增声明按空旧输入比较。全部实际注解属性及默认值都参与比较,包括 name、desc 和定制的 app;即使不同输入最终生成相同代码,也允许重新执行处理器。普通 ARouter runtime import 和已有部署 overlay 不会单独触发生成或告警。

无法读取相关旧 class、声明归属有歧义或无法解析相关值和类型时,本模块本轮跳过 ARouter 生成并显示 warn,其他注解器和正常源码编译继续;旧索引可能滞后。如果普通编译随后更新了业务 class,再次提交相同输入不保证补齐旧索引,完整 Gradle 构建可恢复一致状态。当前语义解析不覆盖完整 Java/Kotlin 语言,也不承诺任意 fork 的新增结构依赖均可识别。

APT 成功但语言编译失败时,已生成源码由原有待完成产物跟踪保留。下一次请求仍比较当前源码与业务 class;存在差异时允许再次执行 APT,pending 期间的新路由修改也会重新判断。D8 或部署失败后,输入相同则沿用既有下游重试。

APT/KAPT 路径按 APK 基线选择 AndroidX 或旧 Support Fragment,必要时转换 processor JAR。两种类型都有、没有查询结果或多 APK 无法确定归属时使用 AndroidX;本轮编译类路径缺少目标 Fragment 时明确失败。真实 APT/KAPT/KSP 执行失败或生成源码编译错误停止本轮任务。删除路由等导致生成类集合收缩时保留旧生成目录,并要求完整 Gradle 构建。路由注册索引部署沿用现有 App 重启策略。

已加载的 ARouter 自定义处理器实例存在时,Jugg 默认处理器避让,由该实例接管;仅保留配置而未成功加载不触发避让。源码预处理适配器需按当前 Jugg 接口重新编译后使用。迁移到内置处理应移除该项配置,保留其他扩展。当前识别上述三种注解,按项目实际定义读取属性并调用项目处理器,定制 app 和不同的生成调用参数数量不会单独被拒绝。早期 @Param 或无法解析的新增结构需要核对实际结果。支持范围见注解器。

NOTE

自定义编译器运行在 Jugg 编译流程内,适合补充增量链路,不适合替代完整 Gradle task graph。

触发与结果 ​

text
自定义编译器配置可用
  -> 加载并校验扩展 jar
  -> 按配置插入编译阶段
  -> 参与本轮增量编译
  -> 成功产物继续交给后续阶段

选择插入点时,应按用户目标选择阶段,而不是按 jar 加载时机判断。

常见插入点 ​

目标推荐区间
最早或最后处理本轮输入和产物atFirst / atLast
assets 和 native lib 前后处理beforeAsset / afterAsset
资源前后处理beforeRes / afterRes
Java/Kotlin 前后处理beforeSource / afterSource
混淆前后处理beforeMinify / afterMinify
dex 前后处理beforeDex / afterDex

相关页面 ​