Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d57983b
Added standalone tests for SBT import
ajaychandran Jul 20, 2025
55eb124
Rebase
ajaychandran Jul 29, 2025
5410f43
Merged code from new modules in to existing ones
ajaychandran Jul 31, 2025
2e82d15
Restored log statement required by examples
ajaychandran Jul 31, 2025
a2b17d2
Updated failing example
ajaychandran Jul 31, 2025
0c135ff
Cleanup
ajaychandran Aug 1, 2025
18b0e78
Refined core design and extended cross development support.
ajaychandran Aug 7, 2025
ff61532
Cleanup
ajaychandran Aug 7, 2025
6e10b2d
Removed build transformation options.
ajaychandran Aug 7, 2025
2113a73
Cleanup
ajaychandran Aug 7, 2025
50ec630
Updated incomplete example
ajaychandran Aug 7, 2025
d90a39a
Cleanup
ajaychandran Aug 7, 2025
997ee71
Added base trait and merge features, fixed issue with missing modules…
ajaychandran Aug 9, 2025
f3802b8
Cleanup
ajaychandran Aug 11, 2025
3948dbb
Render output using concatenation
ajaychandran Aug 14, 2025
335bca9
Updated Gradle implementation
ajaychandran Aug 20, 2025
aa3c626
Cleanup
ajaychandran Aug 21, 2025
fcf163b
Set .mill-jvm-version for Mockito tests
ajaychandran Aug 21, 2025
63731fb
Set .mill-jvm-version for Fluency example
ajaychandran Aug 21, 2025
59055b7
Updated Maven conversion
ajaychandran Aug 29, 2025
cce84a5
Cleanup
ajaychandran Aug 29, 2025
5a889fc
Fix mima
ajaychandran Aug 31, 2025
199b26e
Revert name change
ajaychandran Sep 1, 2025
d8c8089
Updated Scaladocs
ajaychandran Sep 2, 2025
9f49707
Eliminated MiMa filters
ajaychandran Sep 2, 2025
6bfd04c
Cleanup
ajaychandran Sep 2, 2025
66f7bf9
Reinstated mill-jvm-version in build header and added lower bound for…
ajaychandran Sep 2, 2025
aeb3fbb
Merge remote-tracking branch 'upstream/main' into importer
ajaychandran Sep 2, 2025
fa2a015
Added fixes for binary compatibility
ajaychandran Sep 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion example/migrating/javalib/3-maven-complete-large/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
> git remote add -f origin https://github.com/iluwatar/java-design-patterns
> git checkout ede37bd05568b1b8b814d8e9a1d2bbd71d9d615d

> ./mill init --jvm-id 21 # Repo needs Java >=21 to build and test
> echo 21 > .mill-jvm-version # Repo needs Java >=21 to build and test

> ./mill init
Comment on lines +9 to +11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we no longer support --jvm-id?

Copy link
Contributor Author

@ajaychandran ajaychandran Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conversion now auto-configures JavaHomeModule.jvmId for Gradle and Maven projects.
Based on the projects tested, JDK version enforcement is quite rare. It is much more common to ensure compatibility with javacOptions like -target.
The Netty project is an example where the version, 1.8, is enforced. But we cannot support this value due to #5782.

The option was also being used to configure the JVM version in the build header. We could rename it to --mill-jvm-version and use it for this purpose.
I am not convinced that the conversion should configure this property since, in the typical case, the preferred JDK is the one already installed.
Consider the Mockito example in 5-gradle-incomplete.

> git checkout v5.19.0 # multi-module Java project that requires Java 11

> echo "17" > .mill-jvm-version # Gradle version in use requires Java 17

Since init runs the Gradle daemon, we need at least version 17. Post conversion, JDK 11 would suffice (this won't be configured at the module level since it is not enforced in the build).
But why not use the latest version? The Mill project itself uses zulu:21.
The reason the version needs to be specified here is that we do not know the JDK version in the CI environment. We could move the value to .mill-jvm-version file to "hide" this from the user.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we look at versions below 11 like 1.8 and generate mill-jvm-version: 11? That won't work for all projects, but it should hopefully work for many of them which aren't too picky about the version they are using. Then the user won't have to create the .mill-jvm-version file manually.

I think trying to specify a version as close as possible to that configured within their build via javacOptions sounds best. Not all projects work with newer versions, e.g. Scala, Kotlin, Spring, etc. all can potentially have problems if we pick a too-new version of the JVM to run them on

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the user won't have to create the .mill-jvm-version file manually.

I think trying to specify a version as close as possible to that configured within their build via javacOptions sounds best.

But why should the conversion explicitly specify the .mill-jvm-version at all? Isn't the default Mill behavior of using the installed JDK sufficient for real world usage?

The conversion should be concerned with configuring the JVM only at the module level and only if it is strictly enforced in the Gradle / Maven build.
I don't think javacOptions should be used to determine a version since a low value is targeted in many cases. Downgrading the JDK will likely adversely affect build times and require a fix in the build file (assuming the cause for the slowdown is identified).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Mill main branch, we need to opt-into using the installed JDK via mill-jvm-version: system. But in general that is discouraged (hence making it no longer the default) and so we shouldn't generate it on-import if possible.

Pulling a low Java version is fine as long as it works. People can tweak and adjust it later, but our goal for the import "a version that is most likely to work while avoiding mill-jvm-version: system". So if there is a -target or -release flag we should use as close to a version as possible, and if there is no flag we maybe just leave it unspecified and Mill will default to Java 21

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reinstated mill-jvm-version in build header and added lower bound for Mill/module JVM version.


> rm twin/src/test/java/com/iluwatar/twin/BallThreadTest.java # skip flaky test
> rm actor-model/src/test/java/com/iluwatar/actor/ActorModelTest.java # skip flaky test
Expand Down
4 changes: 3 additions & 1 deletion example/migrating/javalib/4-gradle-complete/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
> git remote add -f origin https://github.com/komamitsu/fluency.git
> git checkout 2.7.3 # multi-module Java project that requires Java 16+

> ./mill init --base-module FluencyModule --jvm-id 16
> echo "16" > .mill-jvm-version

> ./mill init
converting Gradle build
...
init completed, run "mill resolve _" to list available tasks
Expand Down
11 changes: 6 additions & 5 deletions example/migrating/javalib/5-gradle-incomplete/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

> git init .
> git remote add -f origin https://github.com/mockito/mockito.git
> git checkout v5.15.2 # multi-module Java project that requires Java 17+
> git checkout v5.19.0 # multi-module Java project that requires Java 11

> ./mill init --base-module MockitoModule --jvm-id 17 # init ignores custom dependency configurations
> echo "17" > .mill-jvm-version # Gradle version in use requires Java 17

> ./mill init # imported modules are not fully functional
converting Gradle build
ignoring errorprone dependency (com.google.errorprone,error_prone_core,2.23.0)
init completed, run "mill resolve _" to list available tasks

> ./mill __.compile # compilation error can be by fixed by using the Mill plugin for ErrorProne
error: plug-in not found: ErrorProne
> ./mill mockito-core.compile # requires manual tweaking to support Java modules
error: ...module not found: net.bytebuddy
*/
12 changes: 5 additions & 7 deletions example/migrating/scalalib/2-sbt-incomplete/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
> rm build.mill # remove any existing build file

> git init .
> git remote add -f origin https://github.com/tototoshi/scala-csv.git
> git checkout 2.0.0
> git remote add -f origin https://github.com/fthomas/refined.git
> git checkout v0.11.3

> ./mill init
converting sbt build
...
init completed, run "mill resolve _" to list available tasks

> ./mill compile # You will have to further configure the `CrossScalaModule` for different Scala versions
compiling 7 Scala sources and 3 Java sources to ...
error: class CSVReader protected (private val lineReader: LineReader)(implicit format: CSVFormat) extends Closeable with CSVReaderCompat {
error: ^
error: one error found
> ./mill modules.core.jvm[2.12.20].compile # custom version range source roots 3.0+/3.0- not supported
compiling 22 Scala sources to ...
error: ...object boolean is not a member of package eu.timepit.refined
*/
34 changes: 34 additions & 0 deletions integration/manual/migrating/src/MillInitGradleAsmTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitGradleAsmTests extends GitRepoIntegrationTestSuite {

// gradle 8.3
def gitRepoUrl = "https://gitlab.ow2.org/asm/asm.git"
def gitRepoBranch = "ASM_9_8"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

os.write(workspacePath / ".mill-jvm-version", "11")

eval("init", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("asm.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("asm.publishLocal", stdout = os.Inherit, stderr = os.Inherit)

// modules are tested with asm-test module?
eval("asm.test", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false

// custom sourceSets not supported
eval(
"tools.retrofitter.compile",
stdout = os.Inherit,
stderr = os.Inherit
).isSuccess ==> false
}
}
}
35 changes: 35 additions & 0 deletions integration/manual/migrating/src/MillInitGradleEhcache3Tests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitGradleEhcache3Tests extends GitRepoIntegrationTestSuite {

// gradle 7.2
// custom dependency configurations
// dependencies with version constraints
// custom layout
// custom repository
// bom dependencies
// modules with pom packaging
// Junit4
def gitRepoUrl = "https://github.com/ehcache/ehcache3.git"
def gitRepoBranch = "v3.10.8"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

// https://docs.gradle.org/current/userguide/compatibility.html#java_runtime
os.write(workspacePath / ".mill-jvm-version", "11")

eval("init", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("ehcache-api.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("ehcache-api.test", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true

// custom dependency configurations not supported
eval("ehcache-xml.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false
}
}
}
33 changes: 33 additions & 0 deletions integration/manual/migrating/src/MillInitGradleFastCsvTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitGradleFastCsvTests extends GitRepoIntegrationTestSuite {

// gradle 9.0.0-rc-1
// Junit5
// uses ErrorProne
def gitRepoUrl = "https://github.com/osiegmar/FastCSV.git"
def gitRepoBranch = "v4.0.0"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

os.write(workspacePath / ".mill-jvm-version", "17")

eval("init", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("lib.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("lib.publishLocal", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true

// requires support for Java modules
eval("example.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false

// junit-platform-launcher version is set implicitly (tasks.test.useJunitPlatform())
// https://docs.gradle.org/8.14.3/userguide/upgrading_version_8.html#test_framework_implementation_dependencies
eval("lib.test.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitGradleJCommanderTests extends GitRepoIntegrationTestSuite {

// gradle 8.9
// single module
// testng 7.0.0
def gitRepoUrl = "https://github.com/cbeust/jcommander.git"
def gitRepoBranch = "2.0"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

os.write(workspacePath / ".mill-jvm-version", "11")

eval("init", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("publishLocal", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true

// annotations defined in main-module cannot be used in test-module?
eval("test.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitGradleMicroconfigTests extends GitRepoIntegrationTestSuite {

// gradle 8.10.1
// uses spring-boot-dependencies BOM
// Junit5
def gitRepoUrl = "https://github.com/microconfig/microconfig.git"
def gitRepoBranch = "v4.9.5"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

eval(("init", "-u"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("__.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("__.publishLocal", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval("__.test", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
}
}
}
27 changes: 27 additions & 0 deletions integration/manual/migrating/src/MillInitGradleMockitoTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitGradleMockitoTests extends GitRepoIntegrationTestSuite {

// gradle 8.14.2
// contains BOM module
def gitRepoUrl = "https://github.com/mockito/mockito.git"
def gitRepoBranch = "v5.19.0"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

// project requires Java 11 but Gradle version in use requires Java 17
os.write(workspacePath / ".mill-jvm-version", "17")

eval("init", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true

// requires javacOptions for Java modules
eval("mockito-core.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitGradlePCollectionsTests extends GitRepoIntegrationTestSuite {

// gradle 8.14.3
// single module
// Junit5
def gitRepoUrl = "https://github.com/hrldcpr/pcollections.git"
def gitRepoBranch = "v5.0.0"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

eval("init", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true

// https://github.com/com-lihaoyi/mill/issues/5782
eval("compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false
}
}
}
37 changes: 37 additions & 0 deletions integration/manual/migrating/src/MillInitGradleSpotbugsTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitGradleSpotbugsTests extends GitRepoIntegrationTestSuite {

// gradle 9.0.0
// custom dependency configurations
// dependencies with version constraints
// custom layout
// Junit5
def gitRepoUrl = "https://github.com/spotbugs/spotbugs.git"
def gitRepoBranch = "4.9.4"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

eval("init", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(
"spotbugs-annotations.compile",
stdout = os.Inherit,
stderr = os.Inherit
).isSuccess ==> true
eval(
"spotbugs-annotations.publishLocal",
stdout = os.Inherit,
stderr = os.Inherit
).isSuccess ==> true

// missing sources from custom layout
eval("spotbugs-tests.test", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitGradleSpringFrameworkTests extends GitRepoIntegrationTestSuite {

// gradle 8.14.3
// custom repository
// dependencies with version constraints
// BOM modules
// uses errorprone
def gitRepoUrl = "https://github.com/spring-projects/spring-framework.git"
def gitRepoBranch = "v6.2.10"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

os.write(workspacePath / ".mill-jvm-version", "17")

eval("init", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true

// requires support for dependency version constraints
eval("spring-jcl.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false
}
}
}
22 changes: 22 additions & 0 deletions integration/manual/migrating/src/MillInitMavenAntlr4Tests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package mill.integration

import mill.testkit.GitRepoIntegrationTestSuite
import utest.*

object MillInitMavenAntlr4Tests extends GitRepoIntegrationTestSuite {

def gitRepoUrl = "https://github.com/antlr/antlr4.git"
def gitRepoBranch = "v4.11.1"

def tests = Tests {
test - integrationTest { tester =>
import tester.*

eval("init", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true
eval(("resolve", "_"), stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> true

// custom layout not supported
eval("__.compile", stdout = os.Inherit, stderr = os.Inherit).isSuccess ==> false
}
}
}
Loading
Loading