Hi all, I'm trying to get Gretty work on Gradle 9....
# plugin-development
b
Hi all, I'm trying to get Gretty work on Gradle 9. I believe I've fixed the deprecation warnings but I get a very strange error when running with Gradle 9 (the reason is most likely Groovy 4):
Copy code
> No signature of method: org.akhikhl.gretty.LauncherBase.beforeLaunch() is applicable for argument types: () values: []
  Possible solutions: beforeLaunch(), afterLaunch()
You can see in the code that there very much is such a method on that class. Even the
Possible solutions
below the error mention it. The error happens on the
super.beforeLaunch()
call in DefaultLauncher. The details are not important that much - it's just that every call to
super.XXX()
(not just here - also in other places) in Gradle 9/Groovy 4 fails with
No signature of method ... is applicable for argument types
. Something which doesn't happen in Gradle 8/Groovy 3. Does anyone have any idea why that might be? P.S. Something of note - the plugin is compiled with Gradle 6 (so I think Groovy 2) (for backwards-compatibility). Not sure if it matters. I see the compiled code in the JAR:
Copy code
CallSite[] arrayOfCallSite = $getCallSiteArray();
Object object = arrayOfCallSite[6].callStatic(DefaultLauncher.class, this.project);
this.runnerClasspath = (Collection<URL>)ScriptBytecodeAdapter.castToType(object, Collection.class);
ScriptBytecodeAdapter.invokeMethodOnSuper0(LauncherBase.class, (GroovyObject)this, "beforeLaunch");
Not sure if this somehow "broke" in Gradle 9/Groovy 4?
b
You've given the same link twice. Why do you think it's a similar issue?
v
Indeed, sorry, fixed
It's also about methods that are not found though they are there
The 280 says
Browser.drive
is not found while it is there. The 284 says trying to set a read-only property, but the setter method is there.
b
So do you think this is a Groovy issue or something else?
b
Ouch... so what can I do about that?
v
Ah, thanks
o
Unfortunately it seems the only reliable solution is to build against Groovy 4, which likely means using Gradle 9.x
😟 1
If you want to retain compatibility across more versions, my best recommendation would be to write it in Java which has much stronger backwards compatibility
v
It's imho always better to write public plugins in Java at least for best compatibility 🙂 But that is really a quite breaking change. That would also mean you have to drop Groovy 3 support, doesn't it? And thus Gradle <9 support. Since when is Groovy that breaking between versions that you are unable to run code compiled using Groovy 3 on Groovy 4 😕
Sounds more like a Groovy bug to me
b
Yes, it's very strange... calling super methods is ubiquitous so... that's like Python 2 vs 3.
v
If you want to continue writing the plugin in Groovy but keep supporting older Gradle versions, you can of course release two variants of the plugin, one compiled with Groovy 3 for older Gradle versions, one compiled with Groovy 4 for 9+ if that is really an intended breaking change in Groovy. Gradle will automatically pick the correct variant for the consumer's Gradle version if you model the variants of the plugin properly.
o
The specific issue is https://issues.apache.org/jira/browse/GROOVY-11568, which is only fixed in Groovy 5. I asked about backporting to 4.x but they declined to do so. Upon further digging, I believe that using @CompileStatic for the relevant broken classes may allow it to keep working, as that avoids the changes made to the dynamic call infrastructure. So that is another option as well.
b
The classes I've mentioned do have CompileStatic. Albeit with
TypeCheckingMode.SKIP
. Could that be the problem?
o
I don't think that would affect the generated bytecode, but it would be worth verifying
b
I'll try that but my thoughts were the same - that the generated bytecode should be the same.
As for building multiple variants - Gretty is very old, I'm not the one who initially wrote it so I'm not too familiar with most of it... it's being built with Gradle 6, boosting that to 7 leads to some deprecation warnings. So I guess trying to build it with 9 will be a difficult thing... and I'm really trying to do the minimum here. 😄
v
The specific issue is https://issues.apache.org/jira/browse/GROOVY-11568
But isn't that about calling private methods in superclasses?
beforeLaunch
is public, isn't it?
b
Yes, it's a method from an interface.
This issue is the same as mine I believe.
This is the correct Groovy issue.
Resolution: Won't Fix
🧐 1
😄
People are saying that CompileStatic is a workaround. I'll try to fix the type errors and remove
TypeCheckingMode.SKIP
. Let's hope that resolves it...
Oh wow, that worked! Didn't expect that.
Thank you both for the time! So I'll spend some time fixing type errors and hopefully that will resolve this issue.
v
Oh wow, that worked! Didn't expect that.
Why not?
@CompileStatic(SKIP)
is like not having
@CompileStatic
at all. Except if you for example have a
@CompileStatic
class with a
@CompileStatic(SKIP)
method where all is compiled static except for that method.
You cannot do static compilation without type checking. You can do type checking without static compilation.
b
So what does
@CompileStatic(TypeCheckingMode.SKIP)
do then?
v
I just told you
Copy code
@CompileStatic
class Foo {
    def foo() {}
    @CompileStatic(SKIP)
    def bar() {}
}
foo
will be statically compiled,
bar
will be dynamically compiled as you switched static compilation off for that method even though it was switched on for the class.
Or if you configure static compilation for everything by configuring the Groovy compiler to do so with a config script for example but then want single classes or methods still be dynamically compiled
At least as far as I remember. There is also
@CompileDynamic
, but I guess it is just an alias. 🤷‍♂️
b
I see. Yes, that's what I have been using - "overriding" with CompileDynamic. Perhaps you're right that the other thing does the same.