/* * 第 9 章 · build.gradle.kts * ------------------------------------------------------------ * 演示: * 1) 给自定义 task 加 @CacheableTask 让它能进 Build Cache * 2) Worker API 的并行执行 * 3) Configuration Cache 安全的 task 写法(用 Provider,不直接读 env) */ plugins { java } java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } } repositories { mavenCentral() } // ============================================================ // 示例 1:可缓存的"行数统计" task // ============================================================ @CacheableTask abstract class CountLinesTask : DefaultTask() { @get:InputDirectory @get:org.gradle.api.tasks.PathSensitive(org.gradle.api.tasks.PathSensitivity.RELATIVE) abstract val sourceDir: org.gradle.api.file.DirectoryProperty @get:Input abstract val fileExtension: org.gradle.api.provider.Property @get:OutputFile abstract val report: org.gradle.api.file.RegularFileProperty @TaskAction fun count() { val ext = fileExtension.get() val total = sourceDir.asFileTree.matching { include("**/*." + ext) }.sumOf { it.readLines().size } report.get().asFile.writeText("总行数(*.$ext)=$total\n") logger.lifecycle("✅ 行数统计完成:$total(已写入缓存友好型 task)") } } tasks.register("countLines") { group = "perf" description = "可缓存:第二次运行如果输入未变会 FROM-CACHE" sourceDir.set(layout.projectDirectory.dir("src")) fileExtension.set("java") report.set(layout.buildDirectory.file("reports/lines.txt")) } // ============================================================ // 示例 2:演示"Configuration Cache 友好"的写法 // ============================================================ // ❌ 错误示范(会被 Configuration Cache 警告) // tasks.register("badEnv") { // val env = System.getenv("USER") // 在配置阶段直接读,破坏可缓存性 // doLast { println("Hello, $env") } // } // ✅ 正确示范:用 Provider 懒求值 val userEnv = providers.environmentVariable("USER") tasks.register("greet") { group = "perf" description = "Configuration Cache 友好版" doLast { println("👋 Hello, ${userEnv.orNull ?: "anonymous"}") } } // ============================================================ // 示例 3:Worker API 并行处理多个文件 // ============================================================ interface MockWorkParameters : org.gradle.workers.WorkParameters { val index: org.gradle.api.provider.Property } abstract class MockWorkAction : org.gradle.workers.WorkAction { override fun execute() { val i = parameters.index.get() // 模拟一个耗时 600ms 的"压缩/转换"操作 Thread.sleep(600) println(" worker-${Thread.currentThread().id} 完成任务 #$i") } } abstract class ParallelDemoTask : DefaultTask() { @get:javax.inject.Inject abstract val workerExecutor: org.gradle.workers.WorkerExecutor @TaskAction fun go() { val queue = workerExecutor.noIsolation() val total = 8 logger.lifecycle("派发 $total 个 worker 任务...") repeat(total) { i -> queue.submit(MockWorkAction::class.java) { index.set(i) } } logger.lifecycle("派发完毕,等待 worker 收尾。") } } tasks.register("parallelDemo") { group = "perf" description = "Worker API 并行示例:8 个任务,并行 4-8 个 worker,1s 内完成" } // ============================================================ // 示例 4:观察哪些 task 会跑 / 哪些会 UP-TO-DATE // ============================================================ tasks.register("explainCache") { group = "perf" description = "提示如何观察缓存命中" doLast { println(""" ▶ 试试以下命令观察输出: ./gradlew countLines # 第一次:真正执行 ./gradlew countLines # 第二次:UP-TO-DATE ./gradlew clean countLines --build-cache # 第三次:FROM-CACHE ▶ 想看慢在哪儿? ./gradlew build --scan ./gradlew build --profile """.trimIndent()) } }