-
-
Notifications
You must be signed in to change notification settings - Fork 418
Initial Groovy setup #5747
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Initial Groovy setup #5747
Conversation
fe154eb
to
a7455f8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for opening this PR and welcome to Mill.
I had a quick scan and left some comments where I spotted something. Overall, this looks reasonable, but there might be some more places copied from the Kotlin implementation which aren't adequate for Groovy.
libs/groovylib/api/src/mill/groovylib/worker/api/GroovyWorker.scala
Outdated
Show resolved
Hide resolved
override def prepareOffline(all: Flag): Command[Seq[PathRef]] = Task.Command { | ||
( | ||
super.prepareOffline(all)() ++ | ||
groovyCompilerClasspath() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this include potential compiler plugin dependencies?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there is no real Groovy compiler in the sense of Javac, Scala or Kotlin (there is Groovyc, which is just a CLI wrapper) I guess there is no need for this. The core Groovy dependency is able to compile and you can just extends the normal classpath. Guess this is due to Groovy being a dynamic language where everything is resolved at runtime anyways. The only difference could be when you use @CompileStatic
(doc). I will add this to the tasks to be evaluated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand, that you copied another language module to start this implementation, but it would be helpful, if you could revise it and delete all tasks that aren't needed, like groovycOptions
.
21334e0
to
69cb09a
Compare
@lefou I've resolved most of the issues and fixed the Spock bug. I've also extended the use-cases and backed them by tests to support static compilation as well as a 3-stage compilation for setups where Java depends on Groovy and vice-versa. In the next weeks I will probably find some more time to see about what configuration options are needed and how to support them. |
@lostiniceland Can you resolve the merge conflicts? |
69cb09a
to
f7cd2cf
Compare
@lefou I would like to pull |
You can try, but I think it will break bin-compat. |
I gave it a try and no additional test broke. From SemVer perspective it also shouldn't break anything as long as the trait provides a default implementation. So I will keep this for now. |
bfbe1fe
to
c82f9a2
Compare
@lefou Have a look at the latest commit I managed to manage (pun intended) the JUnit5/Spock dependencies. Since the BOMs are only available at certain versions this will be checked.
What do you think? Do you want to keep this, or should I remove it? |
…pile which also fixed spock not being executed
Starting with JUnit 5.12 and Spock 2.3 a BOM is available on Maven Central. If the version matches the BOMs will be automatically added. For JUnit, this has the effect that the platform-launcher is also managed in the BOM so it is actually not necessary to specify a platform-launcher-version. Hence the launcher is also added when the version is not set and the minimum version is met.
32f8111
to
bda67ee
Compare
Looks like I was wrong about binary compatibility though I am not quite sure what to make of this: Lets say Groovylib is released with Mill 1.0.10 then I cannot use this with Mill 1.0.9. Fine. And plugins targeting 1.0.10 will also still be compatible since the new method has a default implementation. |
9bb4038
to
39cdc7e
Compare
Do I have to change the package from |
Since we also have experimental We already have the example tooling in place for |
Sounds good to me! |
/** | ||
* In a mixed setup this will compile the Groovy sources to Java stubs. | ||
*/ | ||
def compileGroovyStubs( | ||
sourceFiles: Seq[os.Path], | ||
classpath: Seq[os.Path], | ||
outputDir: os.Path | ||
)(implicit | ||
ctx: TaskCtx | ||
) | ||
: Result[CompilationResult] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the output of this? .class
files or .java
files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.java
though they are cleaned up after the last groovy compilation stage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using CompilationResult
in the return isn't appropriate here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this stub-handling somewhere documented? Or can you outline the process and what you mean with "cleaned up after the last compilation stage"?
It looks to me, this groovy stubs should reside in it's own cacheable task, since it should not need to be regenerated when just Java files changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will document it.
In order for Java to compile with dependencies to Groovy, It only needs the method signatures (headers). This is what the Groovy Stubs are. When you have dependencies Groovy -> Java AND Java -> Groovy you need a 3 stage compile
- Groovy compiles to Java stubs (*.java files in the output)
- Java compiles with the Stubs available
2.1 Cleanup stubs after Java compile (I was wrong before, it happens here) - Compile Groovy (now all Java dependencies are also available on the compilepath).
It should actually be very similar in the other toolchains (scala, kotlin) but maybe the external compiler handles this already internally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point about Mill caching. I was using GMavenPlus (Groovy Maven Plugin) as a reference, and maybe there are some things that we could do differently. For instance, I could test if the Groovy compiler can read Java files so we might be able to ditch the stubs.
Edit: The Groovy compiler is actually able to receive Groovy and Java sources and compile but it will not consider anything passed in javacOptions
. Thats why I choose to split the stages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, we could model the three steps as independent cacheable tasks, as in the following pseude-code:
def groovyCompileJavaStubs: Task[PathRef]
def groovyCompileJava: Task[PathRef] // depends on groovyCompileJavaStubs
def groovyComileGroovy: Task[PathRef] // depends on groovyCompileJava
Unfortunately, this produces more than one out directory with final classfiles with is not what (current) Mill expects, so we need to merge-copy the final classes-directories together.
def compile: Task[CompilationResult] {
Seq(groovyCompileGroovy(), groovyCompileJava())
.map(pr = os.copy(pr.path, Task.dest, mergeFolders = true))
CompileResult(..., PathRef(Task.dest))
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lefou Thanks for fixing the mima setup.
EDIT: I've rebased and updated the compilation to use a dedicated (cached) folder for the stubs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I missed your post and tried another solution. What's your take on the latest commit?
I am not sure if we split the compile into 3 public tasks: since they are implicitly dependent on another, it can easily break if the user overwrites only one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't a look at your latest changes, yet. About my suggestions: You always could hide implementation details by making task private, without loosing all the benefits. Besides, I think there is only a minimal risk of breaking anything by overriding, since each task has exactly one purpose and clear in- and outputs. Also, overriding selected task is exactly the way to customize the integration further. There is also the benefit of inspect-ability from the CLI.
Pull request: com-lihaoyi#5913
Inconsistent application of this environment variable seems to be the cause of com-lihaoyi#5910. Before applying it everywhere, first let's try removing it to see if it's still needed at all
2ed36ba
to
89c5eda
Compare
Your latest |
# Conflicts: # mill-build/src/millbuild/Deps.scala # mill-build/src/millbuild/Settings.scala
I did a rebase since your guidelines mention that the PR commits get squashed and afaik you cannot squash properly with merges. |
I have been working on Groovy support since I would like to use Mill for projects where tests are written in Spock/Groovy.
It is basically a modified version of the Kotlin support.
Whats currently working:
If anyone would like to provide feedback I would appreciate it.