You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 15:35:14