Building Groovy with Mill
| Mill Groovy support is currently still under active development. It is expected to continue evolving over time. |
Declarative Module Config
This is a basic Mill build for a single GroovyModule, with one
third-party dependency and a test suite using the JUnit framework.
This example project uses two third-party dependencies - Groovy-Cli-Commons for CLI argument parsing - Groovy-Xml for HTML templating and escaping and uses them to wrap a given input string in HTML templates with proper escaping.
extends: mill.groovylib.GroovyModule
groovyVersion: 5.0.3
mvnDeps:
- org.apache.groovy:groovy-cli-commons
- org.apache.groovy:groovy-xml
mainClass: foo.Foo
groovyCompileTargetBytecode: 11
extends: [build.GroovyTests, TestModule.Junit5]
jupiterVersion: 5.13.4
mvnDeps:
- org.apache.groovy:groovy-test
> ./mill resolve _ # List what tasks are available to run
assembly
...
compile
...
run
...
test
> ./mill run --text hello
<h1>hello</h1>
> ./mill test
Running Test Class foo.FooTest
Test foo.FooTest#generate html created properly() finished...
Test foo.FooTest#generated html is properly escaped() finished...
Test foo.FooTest finished...
> ./mill assembly # bundle classfiles and libraries into a jar for deployment
> ./mill show assembly # show the output of the assembly task
".../out/assembly.dest/out.jar"
> java -jar ./out/assembly.dest/out.jar --text hello
<h1>hello</h1>
Config-Based Modules
This example project uses two third-party dependencies - groovy-cli-commons for CLI
argument parsing, and groovy-xml - uses them to wrap a
given input string in HTML templates with proper escaping.
The test/ submodule contains its own mvnDeps
for dependencies that are only used in the test suite.
build.mill.yaml
src/
foo/Foo.groovy
resources/
...
test/
package.mill.yaml
src/
foo/FooTest.groovy
out/
compile.json
compile.dest/
...
test/
compile.json
compile.dest/
...
The default Mill source folder layout src/ differs from that of Maven/Gradle’s
src/main/java/.
If you wish to use the Maven source folder layout, e.g. for migrating
an existing codebase, you should use
Maven-Compatible Modules
|
> ./mill inspect compile # Show documentation and inputs of a task
compile(GroovyModule.scala:...)
Compiles the current module to generate compiled classfiles/bytecode.
...
Inputs:
upstreamCompileOutput
allSources
compileClasspath
> ./mill compile # compile sources into classfiles
...
Compiling 1 Groovy sources to...
> ./mill test
Test foo.FooTest#generate html created properly() finished, ...
Test foo.FooTest#generated html is properly escaped() finished, ...
Test foo.FooTest finished, ...
Multi-Module Projects
package build
import mill.*, groovylib.*
object foo extends GroovyModule {
def groovyVersion = "5.0.3"
def moduleDeps = Seq(build.bar)
def mvnDeps = Seq(
mvn"org.apache.groovy:groovy-cli-commons"
)
}
object bar extends GroovyModule {
def groovyVersion = "5.0.3"
def mvnDeps = Seq(
mvn"org.apache.groovy:groovy-xml"
)
object test extends GroovyTests with TestModule.Junit5 {}
}
build.mill
foo/
src/
foo/Foo.groovy
bar/
src/
bar/Bar.groovy
test/
src/
bar/BarTests.groovy
out/
foo/
compile.json
compile.dest/
...
bar/
compile.json
compile.dest/
...
test/
compile.json
compile.dest/
...
Maven Compatible Modules
Mill’s default folder layout of foo/src/ and foo/test/src differs from that
of Maven or Gradle’s foo/src/main/groovy/ and foo/src/test/groovy/. If you are
migrating an existing codebase, you can use Mill’s GroovyMavenModule and
GroovyMavenTests as shown below to preserve filesystem compatibility with an existing
Maven or Gradle build:
package build
import mill.*, groovylib.*
object foo extends GroovyMavenModule {
def groovyVersion = "5.0.3"
object test extends GroovyMavenTests with TestModule.Junit5 {}
object integration extends GroovyMavenTests with TestModule.Junit5 {}
}
GroovyMavenModule is a variant of GroovyModule
that uses the more verbose folder layout of Maven, sbt, and other tools:
-
foo/src/main/java -
foo/src/main/groovy -
foo/src/test/java -
foo/src/test/groovy -
foo/src/integration/java -
foo/src/integration/groovy
Rather than Mill’s
-
foo/src -
foo/test/src
This is especially useful if you are migrating from Maven to Mill (or vice versa), during which a particular module may be built using both Maven and Mill at the same time
For more details on migrating from other build tools, see Migrating to Mill
Single-File Scripts
class Foo {
static void main(String[] args) {
if(args == null || args.length != 1){
println "Specify exactly one parameter for greeting"
System.exit(1)
}
println "Hello ${args[0]}"
}
}
> ./mill Foo.groovy bar
Compiling 1 Groovy sources to...
Hello bar
> ./mill Foo.groovy:run bar
Hello bar
> ./mill resolve Foo.groovy:_
Foo.groovy:run
Foo.groovy:runMain
Foo.groovy:compile
Foo.groovy:assembly
...
Programmable Module Config
package build
import mill.*, groovylib.*
object foo extends GroovyModule {
def groovyVersion = "5.0.3"
// Groovy dependency version have been loaded via BOM from the Module already
def mvnDeps = Seq(
mvn"org.apache.groovy:groovy-cli-commons",
mvn"org.apache.groovy:groovy-xml"
)
object test extends GroovyTests, TestModule.Junit5 {
def mvnDeps = Seq(
mvn"org.apache.groovy:groovy-test"
)
}
}
Defining Unit Test Suites
package build
import mill.*, groovylib.*
object foo extends GroovyModule {
def groovyVersion = "5.0.3"
object test extends GroovyTests with TestModule.Junit5 {
def jupiterVersion = "5.13.4"
def mvnDeps = Seq(
mvn"org.apache.groovy:groovy-test"
)
}
}
object bar extends GroovyModule {
def mainClass = Some("bar.Bar")
def groovyVersion = "5.0.3"
object test extends GroovyTests, TestModule.Junit5 {
def jupiterVersion = "5.13.4"
def mvnDeps = Seq(
mvn"org.apache.groovy:groovy-test"
)
}
}
Defining Integration Test Suites
package build
import mill.*, groovylib.*
object qux extends GroovyModule {
def groovyVersion = "5.0.3"
object test extends GroovyTests with TestModule.Junit5 {
def mvnDeps = super.mvnDeps() ++ Seq(
mvn"org.apache.groovy:groovy-test"
)
}
object integration extends GroovyTests with TestModule.Junit5 {
def mvnDeps = super.mvnDeps() ++ Seq(
mvn"org.apache.groovy:groovy-test"
)
}
}
The integration suite is just another regular test module within the parent GroovyModule
Using Spock in Java projects with Maven layout
package build
import mill.*, groovylib.*
object `package` extends JavaMavenModuleWithGroovyTests {
object test extends GroovyMavenTests with TestModule.Spock {
def spockVersion = "2.4-groovy-5.0"
def groovyVersion = "5.0.3"
def jupiterVersion = "5.13.4"
}
}
JavaMavenModuleWithGroovyTests is a variant of JavaModule which also
includes MavenModule and has a special test trait for Groovy tests:
-
foo/src/main/java -
foo/src/test/groovy
This is usefull for Java projects which use Groovy only for testing.
For non Maven-layout projects, this convenience trait is not necessary
because you can just use GroovyModule for your test object instead.