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

   Alternative to #16170. Same problem, opposite conclusion: instead of 
publishing every artifact twice, publish each one once — always as 
`invokedynamic`.
   
   ### Why
   
   Call-site caching links call sites at runtime, which ahead-of-time native 
compilation cannot do. A native image needs every class on the classpath to be 
the `invokedynamic` flavour, so **one dependency compiled the other way rules 
out a native image for every application that depends on it**.
   
   That makes the flavour of a *published* artifact not really its own build's 
decision. Today a plugin author can set `grails { indy = false }` and silently 
strip native compatibility from every application using that plugin.
   
   ### What changes
   
   A project applying `org.apache.grails.gradle.grails-plugin` always compiles 
its published classes with `invokedynamic` and ignores `grails.indy`. Plugin 
authors need to change nothing; a plugin build that sets `indy` can drop it.
   
   `grails.indy` still applies to applications, which sit at the end of the 
classpath and may choose for their own sources. It now defaults to `true`, 
following Groovy's own default, rather than `false`. An application setting it 
to `false` opts itself out of native compilation but still runs correctly 
against the `invokedynamic` artifacts of the framework and its plugins — the 
two flavours interoperate on the same classpath.
   
   This also resolves an existing incoherence: the framework currently ships 
mixed bytecode (`grails-controllers` indy-on, `grails-gsp` indy-off) purely 
from which modules happened to adopt `grails-plugin`. Every published artifact 
is now `invokedynamic`.
   
   ### Compared to #16170
   
   |  | #16170 (dual artifacts) | this PR |
   |---|---|---|
   | Published artifacts | 2 per module | 1 per module |
   | Diff | 2 new plugin classes + test projects | 73 insertions, 10 deletions, 
6 files |
   | Groovy compilation | ~doubles | unchanged |
   | Release surface | doubles (signing, SBOM, scanning) | unchanged |
   | Native compilation | possible unless the app opts out | possible unless 
the app opts out |
   | App can use call-site caching | yes, for its own code and its dependencies 
| yes, for its own code |
   
   The `noindy` artifacts that #16170 publishes can never be used in a native 
build, so they double the release surface to serve only the non-native case — 
which this PR still supports for an application's own code at no artifact cost.
   
   ### Verification
   
   4 functional tests in `GrailsIndyAppOnlySpec`: a plugin that explicitly sets 
`indy = false` still emits `PLUGIN_BYTECODE=indy=true,callsite=false`; no 
second-flavour tasks exist; an application can still choose call-site caching 
for itself; an application configuring nothing follows Groovy's default.
   
   On a real module: `grails-cache` applies `grails-plugin` and compiled with 
zero `invokedynamic` instructions on `8.0.x`. On this branch, 17 of its 37 
classes carry them.
   
   Suite: 96/99 passing. The 3 `GroovyPageToolchainSpec` failures are 
environmental — they need a JDK 21 toolchain that is not installed on the 
machine I ran them on, and they fail identically on unmodified `8.0.x`. 
`codeStyle` clean.
   
   ### Reviewer notes
   
   - Full `./gradlew build` has not been run; one framework module was built 
and inspected locally.
   - The 29 modules here that apply `grails-plugin` change from indy-off to 
indy-on, which is the intended unification but is the change most likely to 
show in a performance comparison against 7.x.


-- 
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