Skip to content

Commit 3b94c5d

Browse files
Extended mill init to support an existing Maven project (#3756)
This PR adds support to convert a Maven build to Mill by generating Mill build file(s) from POM file(s). The generator output should be considered scaffolding and will likely require edits to complete conversion. ### 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 ### Limitations The conversion does not support: - build extensions - build profiles - plugins, other than maven-compiler-plugin ### Future work Add support for: - [os-maven-plugin](https://github.com/trustin/os-maven-plugin) - [moditect-maven-plugin](https://github.com/moditect/moditect) - [hawtjni-maven-plugin](https://github.com/fusesource/hawtjni/tree/master/hawtjni-maven-plugin) Resolves #3449. --------- Co-authored-by: Li Haoyi <[email protected]>
1 parent 4d59da3 commit 3b94c5d

File tree

49 files changed

+3733
-5
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3733
-5
lines changed

build.mill

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ object Deps {
184184
val sonatypeCentralClient = ivy"com.lumidion::sonatype-central-client-requests:0.3.0"
185185
val kotlinVersion = "2.0.21"
186186
val kotlinCompiler = ivy"org.jetbrains.kotlin:kotlin-compiler:$kotlinVersion"
187+
val mavenVersion = "3.9.9"
188+
val mavenEmbedder = ivy"org.apache.maven:maven-embedder:$mavenVersion"
189+
val mavenResolverVersion = "1.9.22"
190+
val mavenResolverConnectorBasic = ivy"org.apache.maven.resolver:maven-resolver-connector-basic:$mavenResolverVersion"
191+
val mavenResolverSupplier = ivy"org.apache.maven.resolver:maven-resolver-supplier:$mavenResolverVersion"
192+
val mavenResolverTransportFile = ivy"org.apache.maven.resolver:maven-resolver-transport-file:$mavenResolverVersion"
193+
val mavenResolverTransportHttp = ivy"org.apache.maven.resolver:maven-resolver-transport-http:$mavenResolverVersion"
194+
val mavenResolverTransportWagon = ivy"org.apache.maven.resolver:maven-resolver-transport-wagon:$mavenResolverVersion"
187195

188196
object RuntimeDeps {
189197
val dokkaVersion = "1.9.20"

dist/package.mill

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ object `package` extends RootModule with build.MillPublishJavaModule {
1919

2020
def testTransitiveDeps = build.runner.testTransitiveDeps() ++ Seq(
2121
build.main.graphviz.testDep(),
22+
build.main.maven.testDep(),
2223
build.runner.linenumbers.testDep(),
2324
build.scalalib.backgroundwrapper.testDep(),
2425
build.contrib.bloop.testDep(),

docs/modules/ROOT/nav.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
** xref:cli/flags.adoc[]
4141
** xref:cli/alternate-installation.adoc[]
4242
** xref:cli/builtin-commands.adoc[]
43+
* Migrating to Mill
44+
** xref:migrating/maven.adoc[]
4345
// This section gives a tour of the various user-facing features of Mill:
4446
// library deps, out folder, queries, tasks, etc.. These are things that
4547
// every Mill user will likely encounter, and are touched upon in the various
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
= Migrating From Maven to Mill
2+
:page-aliases: Migrating_A_Maven_Build_to_Mill.adoc
3+
:icons: font
4+
5+
include::partial$gtag-config.adoc[]
6+
7+
The Mill `init` command can be used to convert a Maven build to Mill. This has
8+
xref:#limitations[limitations] and is not intended to reliably migrate 100% of
9+
Maven builds out there in the wild, but is instead meant to provide the basic
10+
scaffolding of a Mill build for you to further refine and update manually.
11+
12+
Each Maven module with a `pom.xml` is converted to a Mill `build.mill`/`package.mill`
13+
file containing a top-level `MavenModule`. A nested `test` module is defined if both:
14+
15+
* `src/test` exists
16+
* a supported xref:javalib/testing.adoc[test framework] is detected (for a _tests only_
17+
module with test sources in `src/main/java`)
18+
19+
20+
Again, note that `mill init` importing Maven builds is best effort.
21+
This means that while small projects can be expected to complete without issue:
22+
23+
include::partial$example/javalib/migrating/1-maven-complete.adoc[]
24+
25+
More larger projects often require some manual tweaking in order to work:
26+
27+
include::partial$example/javalib/migrating/2-maven-incomplete.adoc[]
28+
29+
Nevertheless, even for larger builds `mill init` automates most of the tedious
30+
busy-work of writing `build.mill`/`package.mill` files, and makes it much quicker
31+
to get a working Mill build for any existing Maven project.
32+
33+
34+
== Capabilities
35+
36+
The conversion
37+
38+
* handles deeply nested modules
39+
* captures project metadata
40+
* configures dependencies for scopes:
41+
** compile
42+
** provided
43+
** runtime
44+
** test
45+
* configures testing frameworks:
46+
** JUnit 4
47+
** JUnit 5
48+
** TestNG
49+
* configures multiple, compile and test, resource directories
50+
51+
=== Command line arguments
52+
.name of generated base module trait defining project metadata settings
53+
[source,sh]
54+
----
55+
./mill init --base-module MyModule
56+
----
57+
.name of generated nested test module (defaults to `test`)
58+
[source,sh]
59+
----
60+
./mill init --test-module test
61+
----
62+
.name of generated companion object defining constants for dependencies
63+
[source,sh]
64+
----
65+
./mill init --deps-object Deps
66+
----
67+
.capture properties defined in `pom.xml` for publishing
68+
[source,sh]
69+
----
70+
./mill init --publish-properties
71+
----
72+
.merge build files generated for a multi-module build
73+
[source,sh]
74+
----
75+
./mill init --merge
76+
----
77+
78+
.use cache for Maven repository system
79+
[source,sh]
80+
----
81+
./mill init --cache-repository
82+
----
83+
.process Maven plugin executions and configurations
84+
[source,sh]
85+
----
86+
./mill init --process-plugins
87+
----
88+
89+
=== Verified projects
90+
91+
The conversion has been tested with the following projects:
92+
93+
* https://github.com/fusesource/jansi/archive/refs/tags/jansi-2.4.1.zip[jansi]
94+
[source,sh]
95+
----
96+
./mill init --base-module JansiModule --deps-object Deps --cache-repository --process-plugins
97+
----
98+
99+
* https://github.com/davidmoten/geo/archive/refs/tags/0.8.1.zip[geo] (multi-module build)
100+
[source,sh]
101+
----
102+
./mill init --base-module GeoModule --deps-object Deps --merge --cache-repository --process-plugins
103+
----
104+
105+
Post `init`, the following tasks were executed successfully:
106+
107+
* `compile`
108+
* `test`
109+
* `publishLocal`
110+
111+
[#limitations]
112+
== Limitations
113+
114+
The conversion does not support
115+
116+
* build extensions
117+
* build profiles
118+
* non-Java (native) sources
119+
120+
Maven plugin support is limited to
121+
122+
* https://maven.apache.org/plugins/maven-compiler-plugin/[maven-compiler-plugin]
123+
124+
[TIP]
125+
====
126+
These limitations can be overcome by:
127+
128+
* configuring equivalent Mill xref:extending/contrib-plugins.adoc[contrib]
129+
or xref:extending/thirdparty-plugins.adoc[third party] plugins
130+
* defining custom xref:extending/writing-plugins.adoc[plugins]
131+
* defining custom xref:fundamentals/tasks.adoc[tasks]
132+
* defining custom xref:fundamentals/cross-builds.adoc[cross modules]
133+
====
134+
135+
== FAQ
136+
137+
.How to fix compilation errors in generated build files?
138+
139+
This could happen if a module and task name collision occurs. Either rename the module or enclose the name in backticks.
140+
141+
142+
.How to fix JPMS `module not found` compilation errors?
143+
144+
Set https://github.com/tfesenko/Java-Modules-JPMS-CheatSheet#how-to-export-or-open-a-package[additional command line options]
145+
for dependencies.
146+
147+
148+
.How to fix test compilation errors?
149+
150+
* The test framework configured may be for an unsupported version; try upgrading the
151+
corresponding dependencies.
152+
* Mill does not add `provided` dependencies to the transitive dependencies of the nested
153+
test module; specify the dependencies again, in one of `ivyDeps`, `compileIvyDeps`, `runIvyDeps`, in the test module.
154+
155+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/** Usage
2+
3+
> rm build.mill # remove any existing build file
4+
5+
> git init .
6+
> git remote add -f origin https://github.com/davidmoten/geo.git
7+
> git checkout 0.8.1 # example multi-module Java project using JUnit4
8+
9+
> ./mill init
10+
converting Maven build
11+
writing Mill build file to geo/package.mill
12+
writing Mill build file to geo-mem/package.mill
13+
writing Mill build file to build.mill
14+
init completed, run "mill resolve _" to list available tasks
15+
16+
> ./mill __.compile
17+
compiling 9 Java sources to .../out/geo/compile.dest/classes ...
18+
compiling 2 Java sources to .../out/geo-mem/compile.dest/classes ...
19+
compiling 10 Java sources to .../out/geo/test/compile.dest/classes ...
20+
done compiling
21+
compiling 1 Java source to .../out/geo-mem/test/compile.dest/classes ...
22+
done compiling
23+
24+
> ./mill __.test # all tests pass immediately
25+
Test run com.github.davidmoten.geo.GeoHashTest finished: 0 failed, 0 ignored, 66 total, ...
26+
Test run com.github.davidmoten.geo.DirectionTest finished: 0 failed, 0 ignored, 1 total, ...
27+
...
28+
29+
*/
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/** Usage
2+
3+
> rm build.mill # remove any existing build file
4+
5+
> git init .
6+
> git remote add -f origin https://github.com/dhatim/fastexcel.git
7+
> git checkout 0.18.4
8+
> # pom.xml has custom profiles for JPMS that mill init does not support
9+
> # https://github.com/dhatim/fastexcel/blob/de56e786a1fe29351e2f8dc1d81b7cdd9196de4a/pom.xml#L251
10+
11+
> ./mill init
12+
converting Maven build
13+
writing Mill build file to fastexcel-writer/package.mill
14+
writing Mill build file to fastexcel-reader/package.mill
15+
writing Mill build file to e2e/package.mill
16+
writing Mill build file to build.mill
17+
init completed, run "mill resolve _" to list available tasks
18+
19+
> ./mill -k __.compile # Compilation needs manual tweaking to pass
20+
error: ...fastexcel-reader/src/main/java/module-info.java:3:32: module not found: org.apache.commons.compress
21+
error: ...fastexcel-reader/src/main/java/module-info.java:4:27: module not found: com.fasterxml.aalto
22+
error: ...fastexcel-writer/src/main/java/module-info.java:2:14: module not found: opczip
23+
24+
*/

example/package.mill

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ object `package` extends RootModule with Module {
3434
object dependencies extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "dependencies"))
3535
object testing extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "testing"))
3636
object linting extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "linting"))
37+
object migrating extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "migrating"))
3738
object publishing extends Cross[ExampleCrossModuleJava](build.listIn(millSourcePath / "publishing"))
3839
object web extends Cross[ExampleCrossModule](build.listIn(millSourcePath / "web"))
3940
}

0 commit comments

Comments
 (0)