如何让Gradle仅在执行自定义任务时编译对应脚本?
针对你遇到的CI任务导致本地buildSrc重复编译耗时的问题,以下是几个实用的解决方案:
方案1:将CI任务拆分到独立插件模块,条件加载
把CI专用的自定义任务从buildSrc迁移到独立的Gradle插件模块,仅在需要执行CI任务时才加载该模块,彻底避免本地常规构建触发不必要的编译:
创建独立插件模块
在项目根目录下新建ci-plugins模块,在该模块的build.gradle.kts中配置Gradle插件开发环境:plugins { `java-gradle-plugin` kotlin("jvm") version "1.9.0" } gradlePlugin { plugins { create("ciTasksPlugin") { id = "com.yourproject.ci-tasks" implementationClass = "com.yourproject.ci.CiTasksPlugin" } } }在该模块中编写所有CI相关的自定义Kotlin任务逻辑。
条件加载插件模块
修改根目录的settings.gradle.kts,仅当命令行中包含CI任务时才引入该模块:val ciTaskNames = setOf("myCustomTask1", "myCustomTask2") val isCiTaskRequested = gradle.startParameter.taskNames.any { it in ciTaskNames } if (isCiTaskRequested) { include(":ci-plugins") }条件应用插件
在根项目的build.gradle.kts中,同样通过条件判断加载CI插件:val ciTaskNames = setOf("myCustomTask1", "myCustomTask2") val isCiTaskRequested = gradle.startParameter.taskNames.any { it in ciTaskNames } if (isCiTaskRequested) { apply(plugin = "com.yourproject.ci-tasks") }这样本地执行
./gradlew build时,不会加载ci-plugins模块,自然不会编译相关代码;只有执行指定的CI任务时,才会触发该模块的编译和任务注册。
方案2:使用脚本插件动态加载CI任务
如果CI任务逻辑相对简单,可以将其写入单独的Kotlin脚本文件,仅在需要时动态加载:
编写CI任务脚本
在项目根目录创建ci-tasks.gradle.kts,在其中定义所有CI自定义任务:tasks.register("myCustomTask1") { doLast { // 任务逻辑 println("Executing CI task 1") } } tasks.register("myCustomTask2") { doLast { // 任务逻辑 println("Executing CI task 2") } }条件加载脚本
修改根项目的build.gradle.kts,仅当检测到CI任务被请求时才加载该脚本:val ciTaskNames = setOf("myCustomTask1", "myCustomTask2") val isCiTaskRequested = gradle.startParameter.taskNames.any { it in ciTaskNames } if (isCiTaskRequested) { apply(from = file("ci-tasks.gradle.kts")) }这种方式无需额外模块,实现成本更低,适合逻辑不复杂的CI任务。
方案3:buildSrc内部条件编译(局限性较强)
如果不想迁移代码,可以在buildSrc内部通过条件编译跳过CI相关代码的编译,但需注意代码依赖问题:
修改buildSrc的build.gradle.kts,根据任务请求情况排除CI代码目录:
val ciTaskNames = setOf("myCustomTask1", "myCustomTask2") val isCiTaskRequested = gradle.parent?.startParameter?.taskNames?.any { it in ciTaskNames } ?: false sourceSets { main { kotlin { if (!isCiTaskRequested) { exclude("**/ci/**") // 假设CI代码都放在ci包下 } } } }
注意:如果CI代码和buildSrc中其他代码有依赖关系,这种方式可能导致编译错误,仅适合CI代码完全独立的场景。
内容的提问来源于stack exchange,提问作者Elliot Nelson

