diff --git a/.agents/tasks/fix-launch-task-exec-time-config.md b/.agents/tasks/fix-launch-task-exec-time-config.md new file mode 100644 index 0000000000..282d6a102b --- /dev/null +++ b/.agents/tasks/fix-launch-task-exec-time-config.md @@ -0,0 +1,107 @@ +--- +slug: fix-launch-task-exec-time-config +branch: master # working tree only; the user decides branch/commit +owner: claude +status: in-review +started: 2026-07-10 +--- + +## Goal + +`LaunchSpineCompiler` no longer mutates task state at execution time, so +consumer builds (e.g. `delivery-server`) stop seeing the Gradle 9.6 deprecations +that become errors in Gradle 10/11: + +1. *"Changing property value of task '…:launchSpineCompiler' property 'mainClass' + at execution time"* (error in Gradle 11). +2. *"Invocation of Task.dependsOn at execution time"* (error in Gradle 10, + configuration-cache incompatible). + +## Context + +Both warnings originate from the `doFirst { compileCommandLine(); +createParametersFile() }` block installed by `applyDefaults()` in +`gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/LaunchSpineCompiler.kt`: + +- `compileCommandLine()` sets `mainClass`, `classpath`, and `args` inside a task + action. `mainClass` is a tracked `Property` — Gradle nags on it now; the rest + will follow. +- `createParametersFile()` traverses `dependsOn` at execution time to locate + the `GenerateProtoTask`. + +None of the deferred values actually require execution-time assembly: +`mainClass` is the constant `CLI_APP_CLASS`; the classpath consists of two lazy +`Configuration`s; the only argument pair is `--params ` whose path is +fully known once the source-set name is fixed in `applyDefaults()`. + +Observed in `delivery-server` `build/reports/problems/problems-report.html` +(build `:admin-server:build`, Gradle 9.6.1), task `:grpc-api:launchSpineCompiler`. + +## Plan + +- [x] `LaunchSpineCompiler.kt` + - [x] Set `mainClass.set(CLI_APP_CLASS)` in the `init` block (constant). + - [x] Add `classpath(...)` for the two configurations in `applyDefaults()` + (configuration time; resolution stays lazy). + - [x] Register the `--params ` pair via `argumentProviders` in + `applyDefaults()` — evaluated when the command line is built, without + mutating `args`, and (as today) without entering the build-cache key, + keeping cached outputs relocatable. + - [x] Add `@get:Internal internal abstract val protoSourceDirs: + ConfigurableFileCollection` — explicit carrier for the proto source + dirs, replacing the `dependsOn` traversal. `Internal` because the proto + content is already fingerprinted via `requestFile`. + - [x] Add `consumeProtoFrom(GenerateProtoTask)` helper: `dependsOn(task)` + + `protoSourceDirs.from(task.sourceDirs)`. + - [x] `createParametersFile()`: read `protoSourceDirs` instead of + `dependsOn.first { it is GenerateProtoTask }`. + - [x] ~~Call `createParametersFile()` from the `exec()` override~~ — reverted; + the write stays a `doFirst` action (see Log for the classloader + constraint). `compileCommandLine()` deleted as planned. +- [x] `Plugin.kt` + - [x] `handleLaunchTaskDependency()`: use `consumeProtoFrom(...)` in both + branches (existing task / `afterEvaluate` creation). +- [x] Verify: full `./gradlew build` green (all module tests + functional + tests); regression test `PluginSpec."not mutate the launch task state + at execution time"` added (runs `launch-test` with `--warning-mode=all` + and asserts the two messages are absent); version bumped to + `2.0.0-SNAPSHOT.062`; dependency reports regenerated; A/B-proven with + a standalone consumer on Gradle 9.6.1: plugin `.060` emits both + warnings, `.062` emits none, launch task executed in both runs. + +## Log + +- 2026-07-10 — analysed delivery-server problems report; drafted plan; executing. +- 2026-07-10 — both files edited; note: the `--info` command-line log from + `compileCommandLine()` is gone; `createParametersFile()` still logs the + parameters file path. Build + `spine-code-review`/`kotlin-engineer` + reviews running. +- 2026-07-10 — functional tests failed (14/17): moving `createParametersFile()` + into the `exec()` override broke Spine `KnownTypes` loading — + `PipelineParameters.toJson()` resolves `desc.ref` resources via the thread + context classloader, which Gradle sets to the plugin classloader only + around `doFirst`/`doLast` actions, not around the `@TaskAction` method. + Fix: the parameters-file write stays a `doFirst` action (a file-system + side effect is not a task-state mutation, so no deprecation); constraint + recorded in a code comment at the call site. Re-running tests. +- 2026-07-10 — all green. Reviews: `kotlin-engineer` APPROVE, + `spine-code-review` APPROVE WITH CHANGES — applied: `check` with curated + message instead of raw cast in `handleLaunchTaskDependency`, KDoc precision, + version bump, deprecation regression test in `PluginSpec`. A/B verification + via a scratchpad consumer project (mavenLocal plugin `.060` vs `.062`, + `--warning-mode=all`): warnings present before, absent after. + Working tree ready for review; not committed (no commit authorization). +- 2026-07-10 — PR #81 opened (3 commits; pre-pr gate PASS). +- 2026-07-10 — CI failed on `Build on Ubuntu`, `Engine performance smoke test`, + and `JUnit Test Report` with `io.spine.type.UnknownTypeException` + + placeholder-descriptor warnings. Root cause: NOT this branch's code — + the exact descriptor-set build-cache bug documented in PR #80. This PR's + version bump `.061->.062` made CI restore the stale `known_types` descriptor + cached by PR #80's own `.061` build (`:test-env:generateProto FROM-CACHE`); + the repo's bootstrap ("dogfooding") Compiler pin `.059` still carries the + unfixed ToolBase `.402`, and the fix "reaches consumers only by advancing + the Compiler's pin" (PR #80). Tests pass locally where the poisoned shared + cache is not in play. Fix: bump `Compiler.fallbackVersion` and + `fallbackDfVersion` to `2.0.0-SNAPSHOT.061` (published from master with + ToolBase `.403`); the new plugin classpath also changes task classloader + hashes, so CI takes cache misses instead of the poisoned entries. diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt index 8dbffcdc46..ba16d2f8bd 100644 --- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt +++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt @@ -72,7 +72,7 @@ object Compiler : Dependency() { * The version of the Compiler dependencies. */ override val version: String - private const val fallbackVersion = "2.0.0-SNAPSHOT.059" + private const val fallbackVersion = "2.0.0-SNAPSHOT.061" /** * The distinct version of the Compiler used by other build tools. @@ -81,7 +81,7 @@ object Compiler : Dependency() { * transitive dependencies, this is the version used to build the project itself. */ val dogfoodingVersion: String - private const val fallbackDfVersion = "2.0.0-SNAPSHOT.059" + private const val fallbackDfVersion = "2.0.0-SNAPSHOT.061" /** * The artifact for the Compiler Gradle plugin. diff --git a/docs/dependencies/dependencies.md b/docs/dependencies/dependencies.md index 35786cef78..d3eb5e35e3 100644 --- a/docs/dependencies/dependencies.md +++ b/docs/dependencies/dependencies.md @@ -1,6 +1,6 @@ -# Dependencies of `io.spine.tools:compiler-api:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-api:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.22.0. @@ -1099,14 +1099,14 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-api-tests:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-api-tests:2.0.0-SNAPSHOT.062` ## Runtime ## Compile, tests, and tooling @@ -1476,14 +1476,14 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-backend:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-backend:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.22.0. @@ -2586,14 +2586,14 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-cli:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-cli:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.22.0. @@ -3855,14 +3855,14 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-gradle-api:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-gradle-api:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.22.0. @@ -4879,14 +4879,14 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-gradle-plugin:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-gradle-plugin:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.22.0. @@ -5947,14 +5947,14 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-jvm:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-jvm:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.22.0. @@ -7074,14 +7074,14 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-params:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-params:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.22.0. @@ -8172,14 +8172,14 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-protoc-plugin:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-protoc-plugin:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -9012,14 +9012,14 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-test-env:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-test-env:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.22.0. @@ -10118,14 +10118,14 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:compiler-testlib:2.0.0-SNAPSHOT.061` +# Dependencies of `io.spine.tools:compiler-testlib:2.0.0-SNAPSHOT.062` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.22.0. @@ -11331,6 +11331,6 @@ This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Jul 07 17:24:16 WEST 2026** using +This report was generated on **Fri Jul 10 19:37:13 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file diff --git a/docs/dependencies/pom.xml b/docs/dependencies/pom.xml index 605248601f..4c5d8e45e1 100644 --- a/docs/dependencies/pom.xml +++ b/docs/dependencies/pom.xml @@ -10,7 +10,7 @@ all modules and does not describe the project structure per-subproject. --> io.spine.tools compiler -2.0.0-SNAPSHOT.061 +2.0.0-SNAPSHOT.062 2015 @@ -381,12 +381,12 @@ all modules and does not describe the project structure per-subproject. io.spine.tools compiler-cli-all - 2.0.0-SNAPSHOT.059 + 2.0.0-SNAPSHOT.061 io.spine.tools compiler-protoc-plugin - 2.0.0-SNAPSHOT.059 + 2.0.0-SNAPSHOT.061 io.spine.tools diff --git a/gradle-plugin/src/functionalTest/kotlin/io/spine/tools/compiler/gradle/plugin/PluginSpec.kt b/gradle-plugin/src/functionalTest/kotlin/io/spine/tools/compiler/gradle/plugin/PluginSpec.kt index 4da51def47..ffd4e26044 100644 --- a/gradle-plugin/src/functionalTest/kotlin/io/spine/tools/compiler/gradle/plugin/PluginSpec.kt +++ b/gradle-plugin/src/functionalTest/kotlin/io/spine/tools/compiler/gradle/plugin/PluginSpec.kt @@ -28,6 +28,7 @@ package io.spine.tools.compiler.gradle.plugin import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain +import io.kotest.matchers.string.shouldNotContain import io.spine.tools.compiler.gradle.api.CompilerTaskName import io.spine.tools.compiler.gradle.api.Names.GRADLE_PLUGIN_ID import io.spine.testing.SlowTest @@ -103,8 +104,8 @@ class PluginSpec { createProject("empty-test") } - private fun createLaunchTestProject() { - createProject("launch-test") + private fun createLaunchTestProject(vararg options: String) { + createProject("launch-test", *options) } private fun createJavaKotlinProject() { @@ -165,6 +166,32 @@ class PluginSpec { launchAndExpectResult(SUCCESS) } + /** + * Locks the absence of the "at execution time" Gradle deprecation warnings + * formerly triggered by the [LaunchSpineCompiler] task. + * + * The task used to assemble its CLI command — including the `mainClass` + * property — in a `doFirst` action, and to query `Task.dependsOn` while + * writing the parameters file. As of Gradle 9.6, both are deprecated: + * the `dependsOn` query fails in Gradle 10, the property mutation + * in Gradle 11. + * + * With `--warning-mode=all` Gradle prints every deprecation warning + * individually, so the assertions below fail if a regression reintroduces + * the execution-time mutation. + */ + @Test + fun `not mutate the launch task state at execution time`() { + createLaunchTestProject("--warning-mode=all") + val result = launch() + + result[launchSpineCompiler] shouldBe SUCCESS + val output = result.output + output shouldNotContain + "Changing property value of task ':${launchSpineCompiler.name()}'" + output shouldNotContain "Invocation of Task.dependsOn at execution time" + } + @Test fun `configure incremental compilation for launch task`() { createLaunchTestProject() diff --git a/gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/LaunchSpineCompiler.kt b/gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/LaunchSpineCompiler.kt index 6ad9c85634..913f4a3f1a 100644 --- a/gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/LaunchSpineCompiler.kt +++ b/gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/LaunchSpineCompiler.kt @@ -47,6 +47,7 @@ import java.io.File.pathSeparator import javax.inject.Inject import org.gradle.api.Project import org.gradle.api.artifacts.Configuration +import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.Directory import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileSystemOperations @@ -65,6 +66,7 @@ import org.gradle.api.tasks.OutputDirectories import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.SourceSet +import org.gradle.process.CommandLineArgumentProvider /** * A task that executes a single Spine Compiler command. @@ -160,6 +162,22 @@ public abstract class LaunchSpineCompiler : JavaExec() { @get:PathSensitive(PathSensitivity.RELATIVE) internal abstract val settingsDirectory: DirectoryProperty + /** + * The directories with the proto source files compiled by + * the [GenerateProtoTask] on which this task depends. + * + * The files found under these directories are listed in the parameters + * file as the compiled proto files. + * + * The property is [Internal] because the content of the compiled proto + * files is already fingerprinted via [requestFile], which the Compiler + * `protoc` plugin derives from them. + * + * @see [consumeProtoFrom] + */ + @get:Internal + internal abstract val protoSourceDirs: ConfigurableFileCollection + @get:InputFiles @get:Classpath internal lateinit var userClasspathConfiguration: Configuration @@ -191,6 +209,9 @@ public abstract class LaunchSpineCompiler : JavaExec() { internal abstract val fileSystemOperations: FileSystemOperations init { + // The main class is a constant, so it is set once at configuration time. + // Doing so at execution time is deprecated and becomes an error in Gradle 11. + mainClass.set(CLI_APP_CLASS) jvmArgs( // Open access for Palantir Java Formatter. "--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", @@ -200,27 +221,6 @@ public abstract class LaunchSpineCompiler : JavaExec() { ) } - /** - * Configures the CLI command for this task. - * - * This method *must* be called after all the configuration is done for the task. - */ - internal fun compileCommandLine() { - val command = sequence { - // Pass the parameters file. - val sourceSet = SourceSetName(sourceSetName.get()) - yield(ParametersFileParam.name) - yield(workingDir.parametersDirectory.file(sourceSet)) - }.asIterable() - logger.info { - "Spine Compiler command for `${path}`: ${command.joinToString(separator = " ")}" - } - classpath(compilerConfiguration) - classpath(userClasspathConfiguration) - mainClass.set(CLI_APP_CLASS) - args(command) - } - /** * Launches the Compiler after cleaning the target directories. * @@ -260,6 +260,15 @@ public abstract class LaunchSpineCompiler : JavaExec() { /** * Applies default settings to the receiver task. * + * Together with the task `init` block and [consumeProtoFrom], this function + * arranges the whole task state — including the CLI command line — at + * configuration time. The values that may change until the end of + * the configuration phase are captured lazily: the classpath via + * [Configuration]s, and the CLI arguments via `argumentProviders`, which + * Gradle queries only when building the actual command line. + * Touching the task state at execution time is deprecated: querying + * `Task.dependsOn` fails in Gradle 10, changing a property in Gradle 11. + * * @param sourceSet The source set for which the task is created. */ internal fun LaunchSpineCompiler.applyDefaults(sourceSet: SourceSet) { @@ -269,20 +278,39 @@ internal fun LaunchSpineCompiler.applyDefaults(sourceSet: SourceSet) { plugins = ext.plugins compilerConfiguration = project.compilerRawArtifact userClasspathConfiguration = project.userClasspath + classpath(compilerConfiguration) + classpath(userClasspathConfiguration) sources = ext.sourceDirs(sourceSet) targets = ext.outputDirs(sourceSet) - requestFile.set(workingDir.requestDirectory.file(SourceSetName(sourceSet.name))) + val ssn = SourceSetName(sourceSet.name) + requestFile.set(workingDir.requestDirectory.file(ssn)) settingsDirectory.set(workingDir.settingsDirectory.path.toFile()) + // The parameters file path is passed via an argument provider rather + // than `args` so that the absolute path does not enter the build cache + // key, keeping the cached outputs relocatable. + val parametersFile = workingDir.parametersDirectory.file(ssn) + argumentProviders.add(CommandLineArgumentProvider { + listOf(ParametersFileParam.name, parametersFile.path) + }) + setDependencies(sourceSet) onlyIf { hasRequestFile(sourceSet) } doFirst { - compileCommandLine() + // Writing the parameters file must stay a `doFirst` action rather + // than move into `exec()`: serializing `PipelineParameters` to JSON + // loads Spine `KnownTypes` via the thread context classloader, and + // Gradle sets that classloader to the plugin classloader only while + // running `doFirst`/`doLast` actions. Inside `exec()` the context + // classloader is a Gradle core one, and the `desc.ref` resource + // lookup fails. Unlike the former command-line assembly, this action + // only writes a file and does not mutate the task state, so it does + // not trip the "at execution time" deprecations. createParametersFile() } } @@ -311,18 +339,33 @@ private fun LaunchSpineCompiler.setDependencies(sourceSet: SourceSet) { project.findKotlinCompileFor(sourceSet)?.dependsOn(launchTask) } +/** + * Makes this task depend on the given [generateProto] task, and captures + * the proto source directories compiled by that task + * into [protoSourceDirs][LaunchSpineCompiler.protoSourceDirs]. + * + * The directories are captured as a live [file collection][ConfigurableFileCollection] + * at configuration time, so that the parameters file can be written without + * querying `Task.dependsOn` at execution time. Such a query is deprecated, + * fails in Gradle 10, and is incompatible with the configuration cache. + */ +internal fun LaunchSpineCompiler.consumeProtoFrom(generateProto: GenerateProtoTask) { + dependsOn(generateProto) + protoSourceDirs.from(generateProto.sourceDirs) +} + /** * Writes the file with parameters for a pipeline. * - * The function obtains the list of compiled proto files by querying an instance - * of [GenerateProtoTask] on which the receiver task depends on (as set by the - * [Plugin.handleLaunchTaskDependency][io.spine.tools.compiler.gradle.plugin.handleLaunchTaskDependency] - * function). + * The function obtains the list of compiled proto files from + * [protoSourceDirs][LaunchSpineCompiler.protoSourceDirs] populated from the + * [GenerateProtoTask] on which the receiver task depends (as arranged by + * [consumeProtoFrom] called from the `handleLaunchTaskDependency` + * extension in `Plugin.kt`). */ private fun LaunchSpineCompiler.createParametersFile() { - val generateProtoTask = dependsOn.first { it is GenerateProtoTask } as GenerateProtoTask val params = pipelineParameters { - val protoFiles = generateProtoTask.sourceDirs.asFileTree.files.toList().sorted() + val protoFiles = protoSourceDirs.asFileTree.files.toList().sorted() .map { it.toAbsoluteFile() } diff --git a/gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/Plugin.kt b/gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/Plugin.kt index 7cbefd5787..e5a07862bb 100644 --- a/gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/Plugin.kt +++ b/gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/Plugin.kt @@ -477,22 +477,32 @@ private fun GenerateProtoTask.declareRequestFileOutputs(requestFile: File) { /** * Makes a [LaunchSpineCompiler], if it exists for the source set of the given [GenerateProtoTask], - * depend on this task. + * depend on the given [generateProto] task and consume the proto source directories it compiles. * * If the [LaunchSpineCompiler] task does not exist (which may be the case for custom source sets * created by other plugins), arranges the task creation on [Project.afterEvaluate]. * In this case the [SpineCompilerCleanTask] is also created with appropriate dependencies. + * + * @see [consumeProtoFrom] */ private fun Project.handleLaunchTaskDependency(generateProto: GenerateProtoTask) { val sourceSet = generateProto.sourceSet - CompilerTask.find(this, sourceSet) - ?.dependsOn(generateProto) - ?: afterEvaluate { - val launchTask = createLaunchTask(sourceSet) - launchTask.configure { - it.dependsOn(generateProto) + val launchTask = CompilerTask.find(this, sourceSet) + check(launchTask is LaunchSpineCompiler?) { + "The task `${launchTask?.path}` is expected to be an instance of" + + " `${LaunchSpineCompiler::class.qualifiedName}`," + + " but was `${launchTask?.javaClass?.name}`." + } + if (launchTask != null) { + launchTask.consumeProtoFrom(generateProto) + } else { + afterEvaluate { + val newTask = createLaunchTask(sourceSet) + newTask.configure { + it.consumeProtoFrom(generateProto) } createCleanTask(sourceSet) arrangeKspTaskDependency(sourceSet) } + } } diff --git a/version.gradle.kts b/version.gradle.kts index ca072a01e4..4969848845 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -30,7 +30,7 @@ * This version is also used by integration test projects. * E.g. see `tests/consumer/build.gradle.kts`. */ -private val compilerVersion = "2.0.0-SNAPSHOT.061" +private val compilerVersion = "2.0.0-SNAPSHOT.062" extra.set("compilerVersion", compilerVersion) /**