codeconsole opened a new pull request, #16114:
URL: https://github.com/apache/grails-core/pull/16114

   ## Problem
   
   `GrailsGradlePlugin.configureGroovyCompiler` assigns 
`groovyOptions.configurationScript` from a `doFirst` on each `GroovyCompile` 
task. Gradle finalizes task properties before any task action runs, so from 
**Gradle 9.7** — where `GroovyCompileOptions` [became a lazy 
property](https://docs.gradle.org/9.7.0/release-notes.html) — every Groovy 
compilation in every Grails project fails:
   
   ```
   * What went wrong:
   Execution failed for task ':compileGroovy' (registered by plugin class 
'org.gradle.api.plugins.GroovyBasePlugin').
   > The value for task ':compileGroovy' property 
'groovyOptions.configurationScriptFile' is final and cannot be changed any 
further.
   ```
   
   ```
   at 
org.gradle.api.tasks.compile.GroovyCompileOptions.setConfigurationScript(GroovyCompileOptions.java:216)
   at 
org.grails.gradle.plugin.core.GrailsGradlePlugin$_configureGroovyCompiler_closure4$_closure37.doCall(GrailsGradlePlugin.groovy:233)
   ```
   
   This blocks Grails 8 on Gradle 9.7 entirely — there is no user-side 
workaround, and no Gradle opt-out flag.
   
   ## Fix
   
   The combined compiler configuration script is now produced by a dedicated 
task that the compile task depends on.
   
   Assigning the property during configuration is necessary but not sufficient: 
Gradle then treats the script as an input file that must exist *before* the 
compile task runs, which fails on a clean build because `doFirst` runs after 
input validation. A producing task is what makes the file exist at the right 
moment.
   
   The generator task is marked `doNotTrackState`, which preserves the property 
the original `doFirst` was protecting — the existing comment noted that 
generating the script needs the resolved compile classpath, and declaring that 
as an input would pull the `runtimeClasspath` into the task's up-to-date check. 
The script is cheap to build, so it is regenerated on every build instead.
   
   Wiring moves into `afterEvaluate` so a `configurationScript` set by the 
build script is already in place and gets folded into the combined script 
rather than clobbered — preserving the merge the old execution-time read 
performed. Task names are read via `TaskCollection.names`, which does not 
realize the tasks.
   
   ## Testing
   
   - `:grails-gradle-plugins:test` passes.
   - Verified against a multi-project Grails 8 application (~20 subprojects, 
Groovy + GSP + plugins) on **both Gradle 9.6.1 and 9.7.0**:
     - full `bootJar` succeeds on both;
     - `clean` plus compilation in a single invocation succeeds (the case a 
`doFirst` cannot satisfy);
     - the generated `grailsGroovyCompilerConfig-<task>.groovy` still carries 
the expected `withConfig(configuration) { inline(phase: 'CONVERSION') ... }` 
metadata (`projectVersion`, `projectName`, `isPlugin`).
   
   Without this change, that same application fails on Gradle 9.7.0 at the 
first `compileGroovy`.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to