gradle默认仅识别标准路径,混用kotlin/java需显式配置sourcesets;kotlin插件不自动合并源目录,须在build.gradle.kts中统一java.srcdirs并清空kotlin.srcdirs,android项目须用android.sourcesets配置,否则编译失败或报错。

Gradle 默认能识别 src/main/java 和 src/main/kotlin,但一旦项目结构偏离约定(比如混用多语言、自定义路径、模块拆分),就必须显式配置 sourceSets,否则编译会漏掉文件或报 Cannot resolve symbol 错误。
为什么默认配置会失效
Gradle 的“约定优于配置”只在标准路径下生效。Kotlin 插件(kotlin("jvm") 或 kotlin("android"))虽然会自动挂载 src/main/kotlin,但它**不会自动合并 Java 和 Kotlin 源码目录**——两者默认是独立的源集。如果你把 Kotlin 文件放在 src/main/java 下,或把 Java 文件放在 src/main/kotlin 下,它们根本不会被对应编译器处理。
- IDE(如 IntelliJ)可能显示正常,但 Gradle 命令行编译失败
-
compileKotlin任务找不到 Kotlin 文件,compileJava任务找不到 Java 文件 - 跨语言调用(如 Kotlin 调 Java 类)时提示 unresolved reference
如何正确配置混合源码目录(Kotlin + Java)
在 build.gradle.kts 中显式声明所有源码根目录,让两个编译器共享同一逻辑源集:
sourceSets {
main {
java {
srcDirs("src/main/java", "src/main/kotlin")
}
kotlin {
// 显式清空默认路径,避免重复或冲突
srcDirs = emptySet()
}
resources.srcDirs("src/main/resources")
}
}
- 必须同时配置
java.srcDirs和清空kotlin.srcDirs,否则 Kotlin 插件仍会尝试单独编译src/main/kotlin,引发重复类错误 - 路径用字符串字面量,不建议用
file()或变量拼接,避免 Windows/Linux 路径分隔符问题 - 如果用了
kotlin("android")插件,还需额外加android.sourceSets.getByName("main").java.srcDirs(...)(Android 场景下sourceSets是双层嵌套)
Android 项目中容易忽略的 sourceSets 差异
Android 的 sourceSets 不是纯 Gradle 的 SourceSet,而是由 Android Gradle Plugin(AGP)二次封装的。直接写 sourceSets.main.java.srcDirs 可能不生效:
- 正确写法(Kotlin DSL):
android { sourceSets { getByName("main") { java.srcDirs("src/main/java", "src/main/kotlin") } } } - 错误写法:
sourceSets { main { java.srcDirs(...) } }—— 这个sourceSets块在 AGP 下会被忽略 - 若同时启用 Jetifier 或 Compose,还要确认
kotlinOptions.jvmTarget和compileOptions.sourceCompatibility一致,否则混合编译会触发Incompatible JVM target警告
调试 sourceSets 配置是否生效
最简单的方法是运行 ./gradlew help --task compileKotlin,然后看输出里 source 字段是否包含你预期的路径;更直接的是在构建脚本里临时加一行:
tasks.withType<org.jetbrains.kotlin.gradle.tasks.kotlincompile> {
doFirst {
println("Kotlin sources: ${source.files}")
}
}</org.jetbrains.kotlin.gradle.tasks.kotlincompile>
- 如果打印出空集合或只有默认路径,说明
sourceSets没被 Kotlin 编译任务读取 - Android 项目务必检查
android.sourceSets和顶层sourceSets是否冲突(二者共存时以前者为准) - CI 环境中常见问题是没清理
.gradle缓存,改完sourceSets后记得加--no-daemon --refresh-dependencies重试
真正麻烦的不是写几行配置,而是不同插件对 sourceSets 的接管层级不透明——Kotlin 插件、Java 插件、Android 插件都可能覆盖或忽略你的设置,必须按实际插件链逐层验证。











