Migrating From Maven to Mill

The Mill init command can be used to convert a Maven build to Mill. This has limitations and is not intended to reliably migrate 100% of Maven builds out there in the wild, but is instead meant to provide the basic scaffolding of a Mill build for you to further refine and update manually.

Each Maven module with a pom.xml is converted to a Mill build.mill/package.mill file containing a top-level MavenModule. A nested test module is defined if both:

  • src/test exists

  • a supported test framework is detected (for a tests only module with test sources in src/main/java)

Again, note that mill init importing Maven builds is best effort. This means that while small projects can be expected to complete without issue:

> rm build.mill # remove any existing build file

> git init .
> git remote add -f origin https://github.com/davidmoten/geo.git
> git checkout 0.8.1 # example multi-module Java project using JUnit4

> ./mill init
converting Maven build
writing Mill build file to geo/package.mill
writing Mill build file to geo-mem/package.mill
writing Mill build file to build.mill
init completed, run "mill resolve _" to list available tasks

> ./mill __.compile
compiling 9 Java sources to .../out/geo/compile.dest/classes ...
compiling 2 Java sources to .../out/geo-mem/compile.dest/classes ...
compiling 10 Java sources to .../out/geo/test/compile.dest/classes ...
done compiling
compiling 1 Java source to .../out/geo-mem/test/compile.dest/classes ...
done compiling

> ./mill __.test # all tests pass immediately
Test run com.github.davidmoten.geo.GeoHashTest finished: 0 failed, 0 ignored, 66 total, ...
Test run com.github.davidmoten.geo.DirectionTest finished: 0 failed, 0 ignored, 1 total, ...
...

More larger projects often require some manual tweaking in order to work:

> rm build.mill # remove any existing build file

> git init .
> git remote add -f origin https://github.com/dhatim/fastexcel.git
> git checkout 0.18.4
> # pom.xml has custom profiles for JPMS that mill init does not support
> # https://github.com/dhatim/fastexcel/blob/de56e786a1fe29351e2f8dc1d81b7cdd9196de4a/pom.xml#L251

> ./mill init
converting Maven build
writing Mill build file to fastexcel-writer/package.mill
writing Mill build file to fastexcel-reader/package.mill
writing Mill build file to e2e/package.mill
writing Mill build file to build.mill
init completed, run "mill resolve _" to list available tasks

> ./mill -k __.compile # Compilation needs manual tweaking to pass
error: ...fastexcel-reader/src/main/java/module-info.java:3:32: module not found: org.apache.commons.compress
error: ...fastexcel-reader/src/main/java/module-info.java:4:27: module not found: com.fasterxml.aalto
error: ...fastexcel-writer/src/main/java/module-info.java:2:14: module not found: opczip

Nevertheless, even for larger builds mill init automates most of the tedious busy-work of writing build.mill/package.mill files, and makes it much quicker to get a working Mill build for any existing Maven project.

Capabilities

The conversion

  • handles deeply nested modules

  • captures project metadata

  • configures dependencies for scopes:

    • compile

    • provided

    • runtime

    • test

  • configures testing frameworks:

    • JUnit 4

    • JUnit 5

    • TestNG

  • configures multiple, compile and test, resource directories

Command line arguments

name of generated base module trait defining project metadata settings
./mill init --base-module MyModule
name of generated nested test module (defaults to test)
./mill init --test-module test
name of generated companion object defining constants for dependencies
./mill init --deps-object Deps
capture properties defined in pom.xml for publishing
./mill init --publish-properties
merge build files generated for a multi-module build
./mill init --merge
use cache for Maven repository system
./mill init --cache-repository
process Maven plugin executions and configurations
./mill init --process-plugins

Verified projects

The conversion has been tested with the following projects:

./mill init --base-module JansiModule --deps-object Deps --cache-repository --process-plugins
  • geo (multi-module build)

./mill init --base-module GeoModule --deps-object Deps --merge --cache-repository --process-plugins

Post init, the following tasks were executed successfully:

  • compile

  • test

  • publishLocal

Limitations

The conversion does not support

  • build extensions

  • build profiles

  • non-Java (native) sources

Maven plugin support is limited to

These limitations can be overcome by:

FAQ

How to fix compilation errors in generated build files?

This could happen if a module and task name collision occurs. Either rename the module or enclose the name in backticks.

How to fix JPMS module not found compilation errors?

Set additional command line options for dependencies.

How to fix test compilation errors?
  • The test framework configured may be for an unsupported version; try upgrading the corresponding dependencies.

  • Mill does not add provided dependencies to the transitive dependencies of the nested test module; specify the dependencies again, in one of ivyDeps, compileIvyDeps, runIvyDeps, in the test module.