如何在buildSrc中访问Java插件特性解决runtimeClasspath未解析问题?
问题描述
我尝试将根build.gradle.kts文件中生成fat(又称uber)jar的代码迁移至buildSrc目录下,为此创建了文件buildSrc/src/main/kotlin/executableJar.kt,代码如下:
import org.gradle.api.Project import org.gradle.api.file.DuplicatesStrategy import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.bundling.Jar import org.gradle.kotlin.dsl.register fun Project.makeExecutableJar (name: String, main: String?, sset: SourceSet) : TaskProvider<Jar> { return tasks.register<Jar>(name) { dependsOn(configurations.runtimeClasspath) archiveFileName.set("$name.jar") main?.let { manifest.attributes["Main-Class"] = it } duplicatesStrategy = DuplicatesStrategy.INCLUDE sset.allSource.forEach { println("==> Source: ${it.absolutePath}") } from(sset.output) from(sset.runtimeClasspath.filter { println("==> Include: ${it.name}") it.name.endsWith(".jar")}.map { zipTree(it) } ) } }
但在IDEA中,代码里的configurations.runtimeClasspath出现“unresolved reference”错误,该特性依赖Java插件。于是我在buildSrc/build.gradle.kts中添加了java插件,修改后的文件内容如下:
plugins { `kotlin-dsl` java } repositories { mavenCentral() gradlePluginPortal() }
然而问题仍未解决。我猜测需要添加显式的dependency { implementation(...) }声明,但找不到对应的依赖ID,请问如何在buildSrc中访问Java插件特性?
解决方案
1. 修正buildSrc的依赖配置
在buildSrc/build.gradle.kts中移除不必要的java插件,添加gradleApi()依赖——它包含了Gradle所有核心插件(包括Java插件)的API,让buildSrc能识别Java插件提供的扩展(比如runtimeClasspath配置):
plugins { `kotlin-dsl` } repositories { mavenCentral() gradlePluginPortal() } dependencies { implementation(gradleApi()) }
2. 优化代码中的配置访问方式
为了避免类型解析问题,建议用类型安全的方式获取runtimeClasspath配置,替代直接访问configurations.runtimeClasspath:
import org.gradle.api.Project import org.gradle.api.file.DuplicatesStrategy import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.bundling.Jar import org.gradle.kotlin.dsl.register fun Project.makeExecutableJar(name: String, main: String?, sset: SourceSet): TaskProvider<Jar> { return tasks.register<Jar>(name) { // 显式获取runtimeClasspath配置 val runtimeClasspath = configurations.getByName("runtimeClasspath") dependsOn(runtimeClasspath) archiveFileName.set("$name.jar") main?.let { manifest.attributes["Main-Class"] = it } duplicatesStrategy = DuplicatesStrategy.INCLUDE sset.allSource.forEach { println("==> Source: ${it.absolutePath}") } from(sset.output) from(runtimeClasspath.filter { println("==> Include: ${it.name}") it.name.endsWith(".jar") }.map { zipTree(it) }) } }
3. 确保主项目应用Java插件
你的makeExecutableJar函数依赖Java插件提供的runtimeClasspath配置,所以必须在主项目的build.gradle.kts中先应用Java插件:
plugins { java }
内容的提问来源于stack exchange,提问作者wholerabbit
相关产品推荐
相关产品推荐

