Gradle Kotlin项目必须使用build.gradle.kts而非build.gradle,因Kotlin DSL是类型安全、IDE支持更优的强制约定;混用会触发“Could not compile script”等解析错误。

Gradle Kotlin 项目必须用 build.gradle.kts,不能混用 Groovy 的 build.gradle;否则 Gradle 会直接报错“Could not compile script”或“Unresolved reference: plugins”。
为什么用 build.gradle.kts 而不是 build.gradle
Kotlin DSL(.kts)是类型安全、可补全、IDE 支持更稳的写法。Groovy 版本的 build.gradle 在 Kotlin 项目里会被 Gradle 拒绝加载——哪怕只有一行 Groovy 语法,也会在 gradle build 阶段触发解析失败。Kotlin DSL 不是“可选增强”,而是 Kotlin 项目的强制约定。
- Gradle 7.0+ 默认禁用 Groovy 构建脚本(除非显式启用
org.gradle.configuration-cache=false) -
settings.gradle和settings.gradle.kts不能共存;同理,build.gradle和build.gradle.kts必须二选一 - Android 项目若用 Kotlin DSL,
android块必须用android { ... }函数调用形式,不能写成 Groovy 风格的闭包赋值
plugins 块必须放在最顶部,且不能用 apply plugin:
Kotlin DSL 中 plugins 是顶层块,不是函数调用,也不支持字符串插件 ID 的动态拼接。常见错误是把 Groovy 写法照搬过来:
// ❌ 错误:Groovy 风格残留,Kotlin DSL 不认
apply(plugin = "java")
// ✅ 正确:必须用 id() + 字符串字面量,且在文件最上方
plugins {
id("java")
id("org.jetbrains.kotlin.jvm") version "1.9.24"
id("org.springframework.boot") version "3.3.5" apply false
}
-
apply false表示只声明插件,不自动应用(常用于父项目统一声明,子模块按需启用) - 插件 ID 必须是字符串字面量,
id("org.jetbrains.kotlin.jvm")可以,id("$kotlinPluginId")会编译失败 - 如果用了
version,就不能再在dependencies里重复引入该插件的 classpath(比如org.jetbrains.kotlin:kotlin-gradle-plugin)
dependencies 里作用域关键字不能省略,implementation ≠ compile
Kotlin DSL 不允许省略依赖作用域(scope),compile 已被废弃多年,继续用会触发警告甚至构建失败:
// ❌ 错误:compile 已移除,Gradle 8.4+ 直接拒绝
compile 'junit:junit:4.13.2'
// ✅ 正确:明确区分用途
dependencies {
implementation("org.slf4j:slf4j-api:2.0.13")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
runtimeOnly("ch.qos.logback:logback-classic:1.5.6")
}
-
implementation:仅当前模块编译期可见,不传递给依赖方 -
api:用于库模块,把依赖暴露给下游使用者(如api("com.google.guava:guava:33.2.0-jre")) -
testImplementation和testRuntimeOnly必须严格配对,否则./gradlew test会因类找不到而失败
多模块项目中 settings.gradle.kts 和 build.gradle.kts 的分工容易搞反
新手常把模块路径写进根 build.gradle.kts,但实际应由 settings.gradle.kts 管理结构,根 build.gradle.kts 只负责统一配置:
// ✅ settings.gradle.kts(唯一职责:声明哪些模块参与构建)
rootProject.name = "my-system"
include(":core", ":api", ":web")
project(":web").projectDir = file("modules/web")
// ✅ 根 build.gradle.kts(只放公共配置,不写具体模块逻辑)
plugins { id("org.jetbrains.kotlin.jvm") version "1.9.24" apply false }
subprojects {
repositories { mavenCentral() }
group = "com.example"
version = "0.1.0"
}
-
include()的参数是模块名,不是路径;路径映射靠project(":name").projectDir单独设置 - 子模块的
build.gradle.kts必须自己声明plugins,不能指望父项目“继承” - 若在
settings.gradle.kts里漏写某个模块,它根本不会被 Gradle 加载,./gradlew projects也看不到
最容易被忽略的是:Kotlin DSL 的语法校验发生在 Gradle 解析阶段,而不是运行时——这意味着一个括号没闭合、一个引号用成了中文符号,都会让整个构建卡死在 Configure project : 阶段,连错误堆栈都可能不完整。建议每次修改后先执行 ./gradlew --dry-run tasks 快速验证语法是否合法。











