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

如何在兼容配置缓存的Gradle中为JAR清单添加Class-Path条目?

如何在兼容配置缓存的Gradle中为JAR清单添加Class-Path条目?

我完全理解你的困扰——给JAR的Manifest加Class-Path是个非常常见的需求,之前用doFirst的老方法在配置缓存下失效确实头疼,不过现在Gradle的Provider API正好能完美解决这个问题,而且完全兼容配置缓存。

为什么之前的尝试会失败?

你遇到的配置不可变错误,核心原因是直接在配置阶段触发了依赖解析:当你调用configurations.runtimeClasspath.files时,Gradle会提前锁定这个配置,后续任何修改依赖的操作都会被拒绝。而配置缓存要求我们尽可能使用延迟计算的方式,避免在配置阶段触碰配置的可变状态。

兼容配置缓存的解决方案

我们可以用Gradle的Provider API来延迟计算Class-Path条目,这样既不会提前锁定配置,又能让配置缓存正常工作。下面是针对多项目Groovy构建脚本的实现:

subprojects {
    // 只对应用了Java插件的子项目生效
    plugins.withType(JavaPlugin) {
        jar {
            // 用Provider延迟计算runtimeClasspath的JAR名称列表
            def classPathEntries = providers.provider {
                configurations.runtimeClasspath.files.collect { it.name }.join(' ')
            }

            // 显式声明输入,确保增量构建和配置缓存正常追踪变化
            inputs.files(configurations.runtimeClasspath)
                .withNormalizer(ClasspathNormalizer)
                .optional() // 允许子项目没有runtime依赖的情况

            // 将Manifest的Class-Path属性绑定到延迟计算的Provider
            manifest {
                attributes(
                    'Class-Path': classPathEntries
                )
            }
        }
    }
}

关键细节解释

  1. 延迟计算的Provider:providers.provider { ... }里的代码不会在配置阶段执行,只会在任务即将执行前的安全时机运行,这时候依赖解析已经完成,但不会提前锁定配置,后续修改依赖的操作依然有效。
  2. 输入声明:inputs.files(configurations.runtimeClasspath)告诉Gradle,这个任务的输出(JAR的Manifest)依赖于runtimeClasspath的内容,确保增量构建和配置缓存能正确识别变化,避免不必要的重建。
  3. 多项目适配:通过plugins.withType(JavaPlugin)确保只有Java子项目会应用这个配置,符合你的多项目构建场景。

如果你用Kotlin DSL

如果你的项目用的是Kotlin构建脚本,对应的实现如下:

subprojects {
    plugins.withType<JavaPlugin> {
        tasks.jar {
            val classPathEntries = providers.provider {
                configurations.runtimeClasspath.get().files.joinToString(" ") { it.name }
            }

            inputs.files(configurations.runtimeClasspath)
                .withNormalizer(ClasspathNormalizer::class)
                .optional()

            manifest {
                attributes(
                    "Class-Path" to classPathEntries
                )
            }
        }
    }
}

验证效果

这个方案完全符合Gradle配置缓存的最佳实践:

  • 不会再出现配置不可变的错误,后续添加/修改依赖的操作依然正常工作;
  • 配置缓存能正确缓存这个任务的状态,大幅提升后续构建速度;
  • 支持增量构建:只有当runtimeClasspath变化时,才会重新生成JAR的Manifest。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 12:44:32