在Gradle中需将生成的Java代码目录(如build/generated-sources/xxx)通过sourceSets.main.java.srcDir显式注册,并确保生成任务在compileJava前执行,否则编译报错。

Gradle 中如何让生成的 Java 代码参与编译
Gradle 默认只编译 src/main/java 和 src/main/groovy 下的手写源码,不会自动识别 build 目录或临时生成的 Java 文件。若你在构建过程中通过 annotation processor、protobuf、openapi-generator 等工具生成了 .java 文件,必须显式告诉 Gradle:这些文件也是源码的一部分。
在 sourceSets 中注册 generated-sources 目录
这是最常用也最可靠的方式——把生成目录添加到 main 源集(source set)中。Gradle 会将其与手写源码一并纳入 compileJava 任务。
- 生成路径需真实存在(Gradle 不会自动创建目录,建议用
mkdir -p或 task 的outputs.dir声明) - 推荐统一放在
build/generated-sources/xxx下,避免污染src/ - 必须在
sourceSets.main.java.srcDir中注册,不能只靠compileJava.classpath补依赖
示例(build.gradle):
sourceSets {
main {
java {
srcDir 'build/generated-sources/annotations'
srcDir 'build/generated-sources/openapi'
}
}
}
注意:srcDir 是追加,不是覆盖;已有的 src/main/java 仍有效。
立即学习“Java免费学习笔记(深入)”;
确保生成任务在 compileJava 之前执行
如果生成逻辑是自定义 task(如 generateProto),必须声明执行顺序,否则 Gradle 可能跳过或报 cannot find symbol 错误。
- 用
compileJava.dependsOn generateProto显式建依赖 - 更健壮的做法是绑定输出:
compileJava.classpath += files(generateProto.outputs.files) - 避免仅靠
mustRunAfter—— 它不保证输入可用,只控制调度顺序
常见错误现象:javac: file not found 或引用生成类时报 package xxx does not exist,基本都是这步漏了。
annotationProcessor 生成的代码要额外处理
像 Lombok、MapStruct、Dagger 这类注解处理器,生成的代码默认写入 build/classes/java/main(即字节码阶段),但有些框架(如旧版 MapStruct)会生成源码到 build/generated-sources/annotations。此时:
- 确认注解处理器是否真生成了
.java(而非直接生成.class) - 若生成了
.java,仍需按上文方式注册srcDir - 不要混淆
annotationProcessor配置项和源码路径 —— 前者只影响编译期 classpath,不解决源码可见性
容易被忽略的一点:IntelliJ IDEA 默认不自动识别 build/generated-sources 为源目录,需手动右键 → Mark as Generated Sources Root,否则编辑器报红但 Gradle 编译正常——这种不一致常让人误判问题所在。


















