├── .mill-version ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ └── build.yml ├── .gitignore ├── .git-blame-ignore-revs ├── itest └── src │ ├── hello-world-kotlin-1.0 │ ├── main │ │ ├── src │ │ │ └── Hello.kt │ │ └── test │ │ │ └── src │ │ │ └── HelloTest.kt │ └── build.sc │ ├── hello-world-kotlin-1.1 │ ├── main │ │ ├── src │ │ │ └── Hello.kt │ │ └── test │ │ │ └── src │ │ │ └── HelloTest.kt │ └── build.sc │ ├── hello-world-kotlin-1.2 │ ├── main │ │ ├── src │ │ │ └── Hello.kt │ │ └── test │ │ │ └── src │ │ │ └── HelloTest.kt │ └── build.sc │ ├── hello-world-kotlin-1.3 │ ├── main │ │ ├── src │ │ │ └── Hello.kt │ │ └── test │ │ │ └── src │ │ │ └── HelloTest.kt │ └── build.sc │ ├── hello-world-kotlin-1.4 │ ├── main │ │ ├── src │ │ │ └── Hello.kt │ │ └── test │ │ │ └── src │ │ │ └── HelloTest.kt │ └── build.sc │ ├── mixed-code-hello-world-kotlin-1.2 │ ├── main │ │ ├── src │ │ │ └── hello │ │ │ │ ├── KotlinHello.kt │ │ │ │ └── JavaHello.java │ │ └── test │ │ │ └── src │ │ │ └── hello │ │ │ └── tests │ │ │ └── HelloTest.java │ └── build.sc │ └── mixed-code-hello-world-kotlin-1.4 │ ├── main │ ├── src │ │ └── hello │ │ │ ├── KotlinHello.kt │ │ │ └── JavaHello.java │ └── test │ │ └── src │ │ └── hello │ │ └── tests │ │ └── HelloTest.java │ └── build.sc ├── main ├── src │ └── de │ │ └── tobiasroeser │ │ └── mill │ │ └── kotlin │ │ ├── KotlinWorkerManager.scala │ │ ├── KotlinTestModule.scala │ │ ├── KotlinWorkerModule.scala │ │ ├── KotlinWorkerManagerImpl.scala │ │ └── KotlinModule.scala ├── worker │ ├── src │ │ └── de │ │ │ └── tobiasroeser │ │ │ └── mill │ │ │ └── kotlin │ │ │ └── KotlinWorker.scala │ └── impl │ │ └── src │ │ └── de │ │ └── tobiasroeser │ │ └── mill │ │ └── kotlin │ │ └── impl │ │ └── KotlinWorkerImpl.scala ├── src-0.10 │ └── de │ │ └── tobiasroeser │ │ └── mill │ │ └── kotlin │ │ └── KotlinModulePlatform.scala ├── src-0.11 │ └── de │ │ └── tobiasroeser │ │ └── mill │ │ └── kotlin │ │ └── KotlinModulePlatform.scala └── src-0.9- │ └── de │ └── tobiasroeser │ └── mill │ └── kotlin │ └── KotlinModulePlatform.scala ├── .editorconfig ├── .scalafmt.conf ├── millw ├── LICENSE └── README.adoc /.mill-version: -------------------------------------------------------------------------------- 1 | 0.11.12 2 | 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: lefou 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /out/ 2 | /.idea/ 3 | /.idea_modules/ 4 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Scala Steward: Reformat with scalafmt 3.0.8 2 | 8d58705806bcf399976168d377c9fc79023043b6 3 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.0/main/src/Hello.kt: -------------------------------------------------------------------------------- 1 | package hello 2 | 3 | fun getHelloString() : String { 4 | return "Hello, world!" 5 | } 6 | 7 | fun main(args : Array) { 8 | println(getHelloString()) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.1/main/src/Hello.kt: -------------------------------------------------------------------------------- 1 | package hello 2 | 3 | fun getHelloString() : String { 4 | return "Hello, world!" 5 | } 6 | 7 | fun main(args : Array) { 8 | println(getHelloString()) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.2/main/src/Hello.kt: -------------------------------------------------------------------------------- 1 | package hello 2 | 3 | fun getHelloString() : String { 4 | return "Hello, world!" 5 | } 6 | 7 | fun main(args : Array) { 8 | println(getHelloString()) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.3/main/src/Hello.kt: -------------------------------------------------------------------------------- 1 | package hello 2 | 3 | fun getHelloString() : String { 4 | return "Hello, world!" 5 | } 6 | 7 | fun main(args : Array) { 8 | println(getHelloString()) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.4/main/src/Hello.kt: -------------------------------------------------------------------------------- 1 | package hello 2 | 3 | fun getHelloString() : String { 4 | return "Hello, world!" 5 | } 6 | 7 | fun main(args : Array) { 8 | println(getHelloString()) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /itest/src/mixed-code-hello-world-kotlin-1.2/main/src/hello/KotlinHello.kt: -------------------------------------------------------------------------------- 1 | package hello 2 | 3 | val KotlinHelloString : String = "Hello from Kotlin!" 4 | 5 | fun getHelloStringFromJava() : String { 6 | return JavaHello.JavaHelloString!!; 7 | } -------------------------------------------------------------------------------- /itest/src/mixed-code-hello-world-kotlin-1.4/main/src/hello/KotlinHello.kt: -------------------------------------------------------------------------------- 1 | package hello 2 | 3 | val KotlinHelloString : String = "Hello from Kotlin!" 4 | 5 | fun getHelloStringFromJava() : String { 6 | return JavaHello.JavaHelloString!!; 7 | } -------------------------------------------------------------------------------- /main/src/de/tobiasroeser/mill/kotlin/KotlinWorkerManager.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin 2 | 3 | import mill.api.{Ctx, PathRef} 4 | 5 | trait KotlinWorkerManager { 6 | def get(toolsClasspath: Seq[PathRef])(implicit ctx: Ctx): KotlinWorker 7 | } 8 | -------------------------------------------------------------------------------- /main/worker/src/de/tobiasroeser/mill/kotlin/KotlinWorker.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin 2 | 3 | import mill.api.{Ctx, Result} 4 | 5 | trait KotlinWorker { 6 | 7 | def compile(args: String*)(implicit ctx: Ctx): Result[Unit] 8 | 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.java] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | indent_style = tab 8 | indent_size = 4 9 | 10 | [*.scala] 11 | end_of_line = lf 12 | insert_final_newline = true 13 | charset = utf-8 14 | indent_style = space 15 | indent_size = 2 16 | 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Documentation for all configuration options: 2 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 3 | 4 | version: 2 5 | updates: 6 | - package-ecosystem: "github-actions" 7 | directory: "/" 8 | schedule: 9 | interval: "weekly" 10 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.0/main/test/src/HelloTest.kt: -------------------------------------------------------------------------------- 1 | package hello.tests 2 | 3 | import hello.getHelloString 4 | import kotlin.test.assertEquals 5 | import org.junit.Test 6 | 7 | class HelloTest { 8 | @Test fun testAssert() : Unit { 9 | assertEquals("Hello, world!", getHelloString()) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.1/main/test/src/HelloTest.kt: -------------------------------------------------------------------------------- 1 | package hello.tests 2 | 3 | import hello.getHelloString 4 | import kotlin.test.assertEquals 5 | import org.junit.Test 6 | 7 | class HelloTest { 8 | @Test fun testAssert() : Unit { 9 | assertEquals("Hello, world!", getHelloString()) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.2/main/test/src/HelloTest.kt: -------------------------------------------------------------------------------- 1 | package hello.tests 2 | 3 | import hello.getHelloString 4 | import kotlin.test.assertEquals 5 | import org.junit.Test 6 | 7 | class HelloTest { 8 | @Test fun testAssert() : Unit { 9 | assertEquals("Hello, world!", getHelloString()) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.3/main/test/src/HelloTest.kt: -------------------------------------------------------------------------------- 1 | package hello.tests 2 | 3 | import hello.getHelloString 4 | import kotlin.test.assertEquals 5 | import org.junit.Test 6 | 7 | class HelloTest { 8 | @Test fun testAssert() : Unit { 9 | assertEquals("Hello, world!", getHelloString()) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.4/main/test/src/HelloTest.kt: -------------------------------------------------------------------------------- 1 | package hello.tests 2 | 3 | import hello.getHelloString 4 | import kotlin.test.assertEquals 5 | import org.junit.Test 6 | 7 | class HelloTest { 8 | @Test fun testAssert() : Unit { 9 | assertEquals("Hello, world!", getHelloString()) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /main/src/de/tobiasroeser/mill/kotlin/KotlinTestModule.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin 2 | 3 | import mill.scalalib.TestModule 4 | 5 | /** 6 | * A [[TestModule]] with support for the Kotlin compiler. 7 | * 8 | * @see [[KotlinModule]] for details. 9 | */ 10 | trait KotlinTestModule extends TestModule with KotlinModule { 11 | override def defaultCommandName(): String = super.defaultCommandName() 12 | } 13 | -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = "3.7.14" 2 | 3 | align.preset = none 4 | align.openParenCallSite = false 5 | align.stripMargin = true 6 | 7 | assumeStandardLibraryStripMargin = true 8 | 9 | continuationIndent.callSite = 2 10 | continuationIndent.defnSite = 4 11 | 12 | docstrings.style = Asterisk 13 | docstrings.oneline = keep 14 | docstrings.wrap = no 15 | 16 | maxColumn = 120 17 | 18 | newlines.source = keep 19 | 20 | runner.dialect = scala213 21 | 22 | -------------------------------------------------------------------------------- /itest/src/mixed-code-hello-world-kotlin-1.2/main/src/hello/JavaHello.java: -------------------------------------------------------------------------------- 1 | package hello; 2 | 3 | public class JavaHello { 4 | public static String JavaHelloString = "Hello from Java!"; 5 | 6 | public static String getHelloStringFromKotlin() { 7 | return KotlinHelloKt.getKotlinHelloString(); 8 | } 9 | 10 | public static void main(String[] args) { 11 | System.out.println(getHelloStringFromKotlin()); 12 | System.out.println(KotlinHelloKt.getHelloStringFromJava()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /itest/src/mixed-code-hello-world-kotlin-1.4/main/src/hello/JavaHello.java: -------------------------------------------------------------------------------- 1 | package hello; 2 | 3 | public class JavaHello { 4 | public static String JavaHelloString = "Hello from Java!"; 5 | 6 | public static String getHelloStringFromKotlin() { 7 | return KotlinHelloKt.getKotlinHelloString(); 8 | } 9 | 10 | public static void main(String[] args) { 11 | System.out.println(getHelloStringFromKotlin()); 12 | System.out.println(KotlinHelloKt.getHelloStringFromJava()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /itest/src/mixed-code-hello-world-kotlin-1.2/main/test/src/hello/tests/HelloTest.java: -------------------------------------------------------------------------------- 1 | package hello.tests; 2 | 3 | import hello.JavaHello; 4 | import junit.framework.TestCase; 5 | 6 | public class HelloTest extends TestCase { 7 | public void testAssert() { 8 | assertEquals("Hello from Kotlin!", JavaHello.getHelloStringFromKotlin()); 9 | assertEquals("Hello from Java!", hello.KotlinHelloKt.getHelloStringFromJava()); 10 | 11 | System.out.println(hello.KotlinHelloKt.getHelloStringFromJava()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /itest/src/mixed-code-hello-world-kotlin-1.4/main/test/src/hello/tests/HelloTest.java: -------------------------------------------------------------------------------- 1 | package hello.tests; 2 | 3 | import hello.JavaHello; 4 | import junit.framework.TestCase; 5 | 6 | public class HelloTest extends TestCase { 7 | public void testAssert() { 8 | assertEquals("Hello from Kotlin!", JavaHello.getHelloStringFromKotlin()); 9 | assertEquals("Hello from Java!", hello.KotlinHelloKt.getHelloStringFromJava()); 10 | 11 | System.out.println(hello.KotlinHelloKt.getHelloStringFromJava()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /main/src/de/tobiasroeser/mill/kotlin/KotlinWorkerModule.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin 2 | 3 | import mill.T 4 | import mill.define.{Discover, ExternalModule, Module, Worker} 5 | 6 | trait KotlinWorkerModule extends Module { 7 | def kotlinWorkerManager: Worker[KotlinWorkerManager] = T.worker { 8 | new KotlinWorkerManagerImpl(T.ctx()) 9 | } 10 | } 11 | 12 | object KotlinWorkerModule extends ExternalModule with KotlinWorkerModule { 13 | override def millDiscover: Discover[this.type] = Discover[this.type] 14 | } 15 | -------------------------------------------------------------------------------- /main/worker/impl/src/de/tobiasroeser/mill/kotlin/impl/KotlinWorkerImpl.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin.impl 2 | 3 | import de.tobiasroeser.mill.kotlin.KotlinWorker 4 | import mill.api.{Ctx, Result} 5 | import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler 6 | 7 | class KotlinWorkerImpl extends KotlinWorker { 8 | 9 | def compile(args: String*)(implicit ctx: Ctx): Result[Unit] = { 10 | ctx.log.debug("Using kotlin compiler arguments: " + args.map(v => s"'${v}'").mkString(" ")) 11 | 12 | val compiler = new K2JVMCompiler() 13 | val exitCode = compiler.exec(ctx.log.errorStream, args: _*) 14 | if (exitCode.getCode() != 0) { 15 | Result.Failure(s"Kotlin compiler failed with exit code ${exitCode.getCode()} (${exitCode})") 16 | } else { 17 | Result.Success(()) 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.1/build.sc: -------------------------------------------------------------------------------- 1 | import $file.plugins 2 | import $file.shared 3 | 4 | import mill._ 5 | import mill.scalalib._ 6 | import de.tobiasroeser.mill.kotlin._ 7 | import org.scalatest.Assertions 8 | 9 | // Adapted from source: https://github.com/Kotlin/kotlin-examples/tree/master/maven/hello-world 10 | object main extends KotlinModule { 11 | 12 | def kotlinVersion = "1.1.0" 13 | 14 | def mainClass = Some("hello.HelloKt") 15 | 16 | object test extends KotlinModuleTests { 17 | def testFrameworks = Seq("com.novocode.junit.JUnitFramework") 18 | def ivyDeps = Agg( 19 | ivy"com.novocode:junit-interface:0.11", 20 | ivy"junit:junit:4.12", 21 | ivy"org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion()}" 22 | ) 23 | } 24 | 25 | } 26 | 27 | def verify() = T.command { 28 | val A = new Assertions {} 29 | import A._ 30 | 31 | val cr = main.compile() 32 | val classFiles = os.walk(cr.classes.path).filter(os.isFile) 33 | assert(classFiles.isEmpty === false) 34 | 35 | main.run()() 36 | 37 | val tcr = main.test.compile() 38 | val testClassFiles = os.walk(tcr.classes.path).filter(os.isFile) 39 | assert(testClassFiles.isEmpty === false) 40 | 41 | val (_, tr) = main.test.test()() 42 | assert(tr.size === 1) 43 | assert(tr.head.status === "Success") 44 | () 45 | } 46 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.2/build.sc: -------------------------------------------------------------------------------- 1 | import $file.plugins 2 | import $file.shared 3 | 4 | import mill._ 5 | import mill.scalalib._ 6 | import de.tobiasroeser.mill.kotlin._ 7 | import org.scalatest.Assertions 8 | 9 | // Adapted from source: https://github.com/Kotlin/kotlin-examples/tree/master/maven/hello-world 10 | object main extends KotlinModule { 11 | 12 | def kotlinVersion = "1.2.0" 13 | 14 | def mainClass = Some("hello.HelloKt") 15 | 16 | object test extends KotlinModuleTests { 17 | def testFrameworks = Seq("com.novocode.junit.JUnitFramework") 18 | def ivyDeps = Agg( 19 | ivy"com.novocode:junit-interface:0.11", 20 | ivy"junit:junit:4.12", 21 | ivy"org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion()}" 22 | ) 23 | } 24 | 25 | } 26 | 27 | def verify() = T.command { 28 | val A = new Assertions {} 29 | import A._ 30 | 31 | val cr = main.compile() 32 | val classFiles = os.walk(cr.classes.path).filter(os.isFile) 33 | assert(classFiles.isEmpty === false) 34 | 35 | main.run()() 36 | 37 | val tcr = main.test.compile() 38 | val testClassFiles = os.walk(tcr.classes.path).filter(os.isFile) 39 | assert(testClassFiles.isEmpty === false) 40 | 41 | val (_, tr) = main.test.test()() 42 | assert(tr.size === 1) 43 | assert(tr.head.status === "Success") 44 | () 45 | } 46 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.0/build.sc: -------------------------------------------------------------------------------- 1 | import $file.plugins 2 | import $file.shared 3 | 4 | import mill._ 5 | import mill.scalalib._ 6 | import mill.define._ 7 | import de.tobiasroeser.mill.kotlin._ 8 | import org.scalatest.Assertions 9 | 10 | // Adapted from source: https://github.com/Kotlin/kotlin-examples/tree/master/maven/hello-world 11 | object main extends KotlinModule { 12 | 13 | def kotlinVersion = "1.0.3" 14 | 15 | def mainClass = Some("hello.HelloKt") 16 | 17 | object test extends Tests { 18 | def testFrameworks = Seq("com.novocode.junit.JUnitFramework") 19 | def ivyDeps = Agg( 20 | ivy"com.novocode:junit-interface:0.11", 21 | ivy"junit:junit:4.12", 22 | ivy"org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion()}" 23 | ) 24 | } 25 | 26 | } 27 | 28 | def verify(): Command[Unit] = T.command { 29 | val A = new Assertions {} 30 | import A._ 31 | 32 | val cr = main.compile() 33 | val classFiles = os.walk(cr.classes.path).filter(os.isFile) 34 | assert(classFiles.isEmpty === false) 35 | 36 | main.run()() 37 | 38 | val tcr = main.test.compile() 39 | val testClassFiles = os.walk(tcr.classes.path).filter(os.isFile) 40 | assert(testClassFiles.isEmpty === false) 41 | 42 | val (_, tr) = main.test.test()() 43 | assert(tr.size === 1) 44 | assert(tr.head.status === "Success") 45 | () 46 | } 47 | -------------------------------------------------------------------------------- /itest/src/mixed-code-hello-world-kotlin-1.2/build.sc: -------------------------------------------------------------------------------- 1 | import $file.plugins 2 | import $file.shared 3 | 4 | import mill._ 5 | import mill.scalalib._ 6 | import de.tobiasroeser.mill.kotlin._ 7 | import org.scalatest.Assertions 8 | 9 | // Adapted from source: https://github.com/Kotlin/kotlin-examples/tree/master/maven/mixed-code-hello-world 10 | object main extends KotlinModule { 11 | 12 | def kotlinVersion = "1.2.0" 13 | 14 | def mainClass = Some("hello.JavaHello") 15 | 16 | object test extends Tests { 17 | def testFrameworks = Seq("com.novocode.junit.JUnitFramework") 18 | def ivyDeps = Agg( 19 | ivy"com.novocode:junit-interface:0.11", 20 | ivy"junit:junit:4.12", 21 | ivy"org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion()}" 22 | ) 23 | } 24 | 25 | def kotlincOptions = Seq("-verbose") 26 | 27 | } 28 | 29 | def verify(): Command[Unit] = T.command { 30 | val A = new Assertions {} 31 | import A._ 32 | 33 | val cr = main.compile() 34 | val classFiles = os.walk(cr.classes.path).filter(os.isFile) 35 | assert(classFiles.isEmpty === false) 36 | 37 | main.run()() 38 | 39 | val tcr = main.test.compile() 40 | val testClassFiles = os.walk(tcr.classes.path).filter(os.isFile) 41 | assert(testClassFiles.isEmpty === false) 42 | 43 | val (_, tr) = main.test.test()() 44 | assert(tr.size === 1) 45 | assert(tr.head.status === "Success") 46 | () 47 | } 48 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.3/build.sc: -------------------------------------------------------------------------------- 1 | import $file.plugins 2 | import $file.shared 3 | 4 | import mill._ 5 | import mill.scalalib._ 6 | import de.tobiasroeser.mill.kotlin._ 7 | import org.scalatest.Assertions 8 | 9 | // Adapted from source: https://github.com/Kotlin/kotlin-examples/tree/master/maven/hello-world 10 | object main extends KotlinModule { 11 | 12 | def kotlinVersion = "1.3.0" 13 | 14 | def mainClass = Some("hello.HelloKt") 15 | 16 | object test extends KotlinModuleTests { 17 | // compatibility with older Mill versions 18 | def testFrameworks: T[Seq[String]] = T(Seq(testFramework())) 19 | def testFramework: T[String] = "com.novocode.junit.JUnitFramework" 20 | def ivyDeps = Agg( 21 | ivy"com.novocode:junit-interface:0.11", 22 | ivy"junit:junit:4.12", 23 | ivy"org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion()}" 24 | ) 25 | } 26 | 27 | } 28 | 29 | def verify() = T.command { 30 | val A = new Assertions {} 31 | import A._ 32 | 33 | val cr = main.compile() 34 | val classFiles = os.walk(cr.classes.path).filter(os.isFile) 35 | assert(classFiles.isEmpty === false) 36 | 37 | main.run()() 38 | 39 | val tcr = main.test.compile() 40 | val testClassFiles = os.walk(tcr.classes.path).filter(os.isFile) 41 | assert(testClassFiles.isEmpty === false) 42 | 43 | val (_, tr) = main.test.test()() 44 | assert(tr.size === 1) 45 | assert(tr.head.status === "Success") 46 | () 47 | } 48 | -------------------------------------------------------------------------------- /itest/src/hello-world-kotlin-1.4/build.sc: -------------------------------------------------------------------------------- 1 | import $file.plugins 2 | import $file.shared 3 | 4 | import mill._ 5 | import mill.scalalib._ 6 | import de.tobiasroeser.mill.kotlin._ 7 | import org.scalatest.Assertions 8 | 9 | // Adapted from source: https://github.com/Kotlin/kotlin-examples/tree/master/maven/hello-world 10 | object main extends KotlinModule { 11 | 12 | def kotlinVersion = "1.4.0" 13 | 14 | def mainClass = Some("hello.HelloKt") 15 | 16 | object test extends KotlinModuleTests { 17 | // compatibility with older Mill versions 18 | def testFrameworks: T[Seq[String]] = T(Seq(testFramework())) 19 | def testFramework: T[String] = "com.novocode.junit.JUnitFramework" 20 | def ivyDeps = Agg( 21 | ivy"com.novocode:junit-interface:0.11", 22 | ivy"junit:junit:4.12", 23 | ivy"org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion()}" 24 | ) 25 | } 26 | 27 | } 28 | 29 | def verify() = T.command { 30 | val A = new Assertions {} 31 | import A._ 32 | 33 | val cr = main.compile() 34 | val classFiles = os.walk(cr.classes.path).filter(os.isFile) 35 | assert(classFiles.isEmpty === false) 36 | 37 | main.run()() 38 | 39 | val tcr = main.test.compile() 40 | val testClassFiles = os.walk(tcr.classes.path).filter(os.isFile) 41 | assert(testClassFiles.isEmpty === false) 42 | 43 | val (_, tr) = main.test.test()() 44 | assert(tr.size === 1) 45 | assert(tr.head.status === "Success") 46 | () 47 | } 48 | -------------------------------------------------------------------------------- /itest/src/mixed-code-hello-world-kotlin-1.4/build.sc: -------------------------------------------------------------------------------- 1 | import $file.plugins 2 | import $file.shared 3 | 4 | import mill._ 5 | import mill.scalalib._ 6 | import de.tobiasroeser.mill.kotlin._ 7 | import org.scalatest.Assertions 8 | 9 | // Adapted from source: https://github.com/Kotlin/kotlin-examples/tree/master/maven/mixed-code-hello-world 10 | object main extends KotlinModule { 11 | 12 | def kotlinVersion = "1.4.0" 13 | 14 | override def kotlincOptions = super.kotlincOptions() ++ Seq("-jvm-target", "1.8") 15 | override def javacOptions = super.javacOptions() ++ Seq("-source", "8", "-target", "8") 16 | 17 | def mainClass = Some("hello.JavaHello") 18 | 19 | object test extends Tests { 20 | // compatibility with older Mill versions 21 | def testFrameworks: T[Seq[String]] = T(Seq(testFramework())) 22 | def testFramework: T[String] = "com.novocode.junit.JUnitFramework" 23 | def ivyDeps = Agg( 24 | ivy"com.novocode:junit-interface:0.11", 25 | ivy"junit:junit:4.12", 26 | ivy"org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion()}" 27 | ) 28 | } 29 | 30 | } 31 | 32 | def verify() = T.command { 33 | val A = new Assertions {} 34 | import A._ 35 | 36 | val cr = main.compile() 37 | val classFiles = os.walk(cr.classes.path).filter(os.isFile) 38 | assert(classFiles.isEmpty === false) 39 | 40 | main.run()() 41 | 42 | val tcr = main.test.compile() 43 | val testClassFiles = os.walk(tcr.classes.path).filter(os.isFile) 44 | assert(testClassFiles.isEmpty === false) 45 | 46 | val (_, tr) = main.test.test()() 47 | assert(tr.size === 1) 48 | assert(tr.head.status === "Success") 49 | () 50 | } 51 | -------------------------------------------------------------------------------- /main/src-0.10/de/tobiasroeser/mill/kotlin/KotlinModulePlatform.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin 2 | 3 | import mill.{Agg, T} 4 | import mill.api.{PathRef, Result} 5 | import mill.define.Task 6 | import mill.scalalib.{Dep, JavaModule, ZincWorkerModule} 7 | import mill.scalalib.api.{CompilationResult, ZincWorkerApi} 8 | 9 | trait KotlinModulePlatform extends JavaModule { 10 | 11 | type CompileProblemReporter = mill.api.CompileProblemReporter 12 | 13 | // compatibility with Mill 0.11 14 | protected type ModuleRef[T] = Function0[T] 15 | protected def zincWorkerRef: ModuleRef[ZincWorkerModule] = () => zincWorker 16 | 17 | protected def kotlinWorkerRef: ModuleRef[KotlinWorkerModule] = () => KotlinWorkerModule 18 | 19 | def kotlinCompilerIvyDeps: T[Agg[Dep]] 20 | 21 | /** 22 | * The Java classpath resembling the Kotlin compiler. 23 | * Default is derived from [[kotlinCompilerIvyDeps]]. 24 | */ 25 | def kotlinCompilerClasspath: T[Seq[PathRef]] = T { 26 | resolveDeps(kotlinCompilerIvyDeps)().toSeq 27 | } 28 | 29 | private[kotlin] def internalCompileJavaFiles( 30 | worker: ZincWorkerApi, 31 | upstreamCompileOutput: Seq[CompilationResult], 32 | javaSourceFiles: Seq[os.Path], 33 | compileCp: Agg[os.Path], 34 | javacOptions: Seq[String], 35 | compileProblemReporter: Option[CompileProblemReporter], 36 | reportOldProblems: Boolean 37 | )(implicit ctx: ZincWorkerApi.Ctx): Result[CompilationResult] = { 38 | worker.compileJava( 39 | upstreamCompileOutput = upstreamCompileOutput, 40 | sources = javaSourceFiles, 41 | compileClasspath = compileCp, 42 | javacOptions = javacOptions, 43 | reporter = compileProblemReporter 44 | ) 45 | } 46 | 47 | private[kotlin] def internalReportOldProblems: Task[Boolean] = T.task(false) 48 | 49 | } 50 | -------------------------------------------------------------------------------- /main/src-0.11/de/tobiasroeser/mill/kotlin/KotlinModulePlatform.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin 2 | 3 | import mill.{Agg, T} 4 | import mill.api.{PathRef, Result} 5 | import mill.define.{ModuleRef, Task} 6 | import mill.scalalib.api.{CompilationResult, ZincWorkerApi} 7 | import mill.scalalib.{Dep, JavaModule, ZincWorkerModule} 8 | 9 | trait KotlinModulePlatform extends JavaModule { 10 | 11 | type CompileProblemReporter = mill.api.CompileProblemReporter 12 | 13 | protected def zincWorkerRef: ModuleRef[ZincWorkerModule] = zincWorker 14 | 15 | protected def kotlinWorkerRef: ModuleRef[KotlinWorkerModule] = ModuleRef(KotlinWorkerModule) 16 | 17 | def kotlinCompilerIvyDeps: T[Agg[Dep]] 18 | 19 | /** 20 | * The Java classpath resembling the Kotlin compiler. 21 | * Default is derived from [[kotlinCompilerIvyDeps]]. 22 | */ 23 | def kotlinCompilerClasspath: T[Seq[PathRef]] = T { 24 | resolveDeps(T.task { kotlinCompilerIvyDeps().map(bindDependency()) })().toSeq 25 | } 26 | 27 | private[kotlin] def internalCompileJavaFiles( 28 | worker: ZincWorkerApi, 29 | upstreamCompileOutput: Seq[CompilationResult], 30 | javaSourceFiles: Seq[os.Path], 31 | compileCp: Agg[os.Path], 32 | javacOptions: Seq[String], 33 | compileProblemReporter: Option[CompileProblemReporter], 34 | reportOldProblems: Boolean 35 | )(implicit ctx: ZincWorkerApi.Ctx): Result[CompilationResult] = { 36 | worker.compileJava( 37 | upstreamCompileOutput = upstreamCompileOutput, 38 | sources = javaSourceFiles, 39 | compileClasspath = compileCp, 40 | javacOptions = javacOptions, 41 | reporter = compileProblemReporter, 42 | reportCachedProblems = reportOldProblems 43 | ) 44 | } 45 | 46 | private[kotlin] def internalReportOldProblems: Task[Boolean] = zincReportCachedProblems 47 | 48 | } 49 | -------------------------------------------------------------------------------- /main/src-0.9-/de/tobiasroeser/mill/kotlin/KotlinModulePlatform.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin 2 | 3 | import mill.{Agg, T} 4 | import mill.api.{PathRef, Result} 5 | import mill.define.Task 6 | import mill.scalalib.{Dep, JavaModule, ZincWorkerModule} 7 | import mill.scalalib.api.{CompilationResult, ZincWorkerApi} 8 | 9 | trait KotlinModulePlatform extends JavaModule { 10 | 11 | type CompileProblemReporter = mill.api.BuildProblemReporter 12 | 13 | type JavaModuleTests = super.Tests 14 | 15 | // compatibility with Mill 0.11 16 | protected type ModuleRef[T] = Function0[T] 17 | protected def zincWorkerRef: ModuleRef[ZincWorkerModule] = () => zincWorker 18 | 19 | protected def kotlinWorkerRef: ModuleRef[KotlinWorkerModule] = () => KotlinWorkerModule 20 | 21 | def kotlinCompilerIvyDeps: T[Agg[Dep]] 22 | 23 | /** 24 | * The Java classpath resembling the Kotlin compiler. 25 | * Default is derived from [[kotlinCompilerIvyDeps]]. 26 | */ 27 | def kotlinCompilerClasspath: T[Seq[PathRef]] = T { 28 | resolveDeps(kotlinCompilerIvyDeps)().toSeq 29 | } 30 | 31 | private[kotlin] def internalCompileJavaFiles( 32 | worker: ZincWorkerApi, 33 | upstreamCompileOutput: Seq[CompilationResult], 34 | javaSourceFiles: Seq[os.Path], 35 | compileCp: Agg[os.Path], 36 | javacOptions: Seq[String], 37 | compileProblemReporter: Option[CompileProblemReporter], 38 | reportOldProblems: Boolean 39 | )(implicit ctx: ZincWorkerApi.Ctx): Result[CompilationResult] = { 40 | worker.compileJava( 41 | upstreamCompileOutput = upstreamCompileOutput, 42 | sources = javaSourceFiles, 43 | compileClasspath = compileCp, 44 | javacOptions = javacOptions, 45 | reporter = compileProblemReporter 46 | ) 47 | } 48 | 49 | private[kotlin] def internalReportOldProblems: Task[Boolean] = T.task(false) 50 | 51 | } 52 | -------------------------------------------------------------------------------- /main/src/de/tobiasroeser/mill/kotlin/KotlinWorkerManagerImpl.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin 2 | 3 | import mill.PathRef 4 | import mill.api.{Ctx, PathRef} 5 | 6 | import java.io.PrintStream 7 | import java.net.{URL, URLClassLoader} 8 | 9 | class KotlinWorkerManagerImpl(ctx: Ctx) extends KotlinWorkerManager with AutoCloseable { 10 | 11 | private[this] var workerCache: Map[Seq[PathRef], (KotlinWorker, Int)] = Map.empty 12 | 13 | override def get(toolsClasspath: Seq[PathRef])(implicit ctx: Ctx): KotlinWorker = { 14 | val toolsCp = toolsClasspath.distinct 15 | val (worker, count) = workerCache.get(toolsCp) match { 16 | case Some((w, count)) => 17 | ctx.log.debug(s"Reusing existing AspectjWorker for classpath: ${toolsCp}") 18 | w -> count 19 | case None => 20 | ctx.log.debug(s"Creating Classloader with classpath: [${toolsCp}]") 21 | val classLoader = new URLClassLoader( 22 | toolsCp.map(_.path.toNIO.toUri().toURL()).toArray[URL], 23 | getClass().getClassLoader() 24 | ) 25 | 26 | val className = 27 | classOf[KotlinWorker].getPackage().getName() + ".impl." + classOf[KotlinWorker].getSimpleName() + "Impl" 28 | ctx.log.debug(s"Creating ${className} from classpath: ${toolsCp}") 29 | val impl = classLoader.loadClass(className) 30 | val worker = impl.getConstructor().newInstance().asInstanceOf[KotlinWorker] 31 | if (worker.getClass().getClassLoader() != classLoader) { 32 | ctx.log.error( 33 | """Worker not loaded from worker classloader. 34 | |You should not add the mill-kotlin-worker JAR to the mill build classpath""".stripMargin 35 | ) 36 | } 37 | if (worker.getClass().getClassLoader() == classOf[KotlinWorker].getClassLoader()) { 38 | ctx.log.error("Worker classloader used to load interface and implementation") 39 | } 40 | worker -> 0 41 | } 42 | workerCache += toolsCp -> (worker -> (1 + count)) 43 | ctx.log.debug(stats()) 44 | worker 45 | } 46 | 47 | def stats(): String = { 48 | s"""Cache statistics of ${this.toString()}: 49 | |${ 50 | workerCache.map { case (cp, (worker, count)) => 51 | s"""- worker: ${worker.toString()} 52 | | used: ${count} 53 | |""".stripMargin 54 | }.mkString 55 | }""".stripMargin 56 | } 57 | 58 | override def close(): Unit = { 59 | ctx.log.debug(stats()) 60 | 61 | // We drop cached worker instances 62 | workerCache = Map.empty 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | tags: 6 | - '**' 7 | pull_request: 8 | 9 | # cancel older runs of a pull request; 10 | # this will not cancel anything for normal git pushes 11 | concurrency: 12 | group: cancel-old-pr-runs-${{ github.workflow }}-${{ github.head_ref || github.run_id }} 13 | cancel-in-progress: true 14 | 15 | 16 | jobs: 17 | build: 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | os: [ubuntu-latest] 22 | java-version: [8, 11, 17] 23 | targets: 24 | - __.publishLocal $(pwd)/testRepo 25 | - "main[_].__.test" 26 | - "itest[0.11.8].test" 27 | - "itest[0.11.0].test" 28 | - "itest[0.10.13].test" 29 | - "itest[0.10.0].test" 30 | - "itest[0.9.12].test" 31 | - "itest[0.9.3].test" 32 | - "itest[0.8.0].test" 33 | - "itest[0.7.4].test" 34 | - "itest[0.7.0].test" 35 | runs-on: ${{ matrix.os }} 36 | continue-on-error: ${{ matrix.os == 'windows-latest' }} 37 | 38 | steps: 39 | - uses: actions/checkout@v4 40 | with: 41 | fetch-depth: 0 42 | 43 | - uses: actions/setup-java@v4 44 | with: 45 | java-version: ${{ matrix.java-version }} 46 | distribution: temurin 47 | 48 | - run: ./millw -i ${{ matrix.targets }} 49 | 50 | - run: ./millw __.scoverage.xmlReport 51 | 52 | - name: Upload scoverage reports to codecov.io 53 | uses: codecov/codecov-action@v4 54 | with: 55 | files: ./out/api/0.11/scoverage/xmlReport.dest/scoverage.xml,./out/api/0.10/scoverage/xmlReport.dest/scoverage.xml,./out/api/0.9/scoverage/xmlReport.dest/scoverage.xml,./out/api/0.7/scoverage/xmlReport.dest/scoverage.xml,./out/worker/0.11/scoverage/xmlReport.dest/scoverage.xml,./out/worker/0.10/scoverage/xmlReport.dest/scoverage.xml,./out/worker/0.9/scoverage/xmlReport.dest/scoverage.xml,./out/worker/0.7/scoverage/xmlReport.dest/scoverage.xml,./out/main/0.11/scoverage/xmlReport.dest/scoverage.xml,./out/main/0.10/scoverage/xmlReport.dest/scoverage.xml,./out/main/0.9/scoverage/xmlReport.dest/scoverage.xml,./out/main/0.7/scoverage/xmlReport.dest/scoverage.xml 56 | token: ${{ secrets.CODECOV_TOKEN }} 57 | continue-on-error: true 58 | 59 | publish: 60 | needs: build 61 | if: github.ref == 'refs/heads/main' && github.event_name == 'push' 62 | 63 | runs-on: ubuntu-latest 64 | 65 | steps: 66 | - uses: actions/checkout@v4 67 | with: 68 | fetch-depth: 0 69 | 70 | - uses: actions/setup-java@v4 71 | with: 72 | java-version: 8 73 | distribution: temurin 74 | 75 | - run: ./millw -i __.publishLocal $(pwd)/testRepo 76 | 77 | - name: Setup GPG secrets for publish 78 | run: | 79 | gpg --version 80 | cat <(echo "${{ secrets.GPG_SECRET_KEY }}") | base64 --decode | gpg --batch --import 81 | gpg --list-secret-keys --keyid-format LONG 82 | 83 | - name: Publish to Maven Central 84 | run: ./millw -i mill.scalalib.PublishModule/publishAll --sonatypeCreds "${{ secrets.SONATYPE_CREDS }}" --gpgArgs "--passphrase=${{ secrets.GPG_SECRET_KEY_PASS }},--batch,--yes,-a,-b,--pinentry-mode,loopback" --publishArtifacts __.publishArtifacts --readTimeout 600000 --release true --signed true 85 | 86 | -------------------------------------------------------------------------------- /millw: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # This is a wrapper script, that automatically download mill from GitHub release pages 4 | # You can give the required mill version with --mill-version parameter 5 | # If no version is given, it falls back to the value of DEFAULT_MILL_VERSION 6 | # 7 | # Project page: https://github.com/lefou/millw 8 | # 9 | # If you want to improve this script, please also contribute your changes back! 10 | # 11 | # Licensed under the Apache License, Version 2.0 12 | 13 | 14 | DEFAULT_MILL_VERSION=0.5.0 15 | 16 | set -e 17 | 18 | # Explicit commandline argument takes precedence over all other methods 19 | if [ "x$1" = "x--mill-version" ] ; then 20 | shift 21 | if [ "x$1" != "x" ] ; then 22 | MILL_VERSION="$1" 23 | shift 24 | else 25 | echo "You specified --mill-version without a version." 26 | echo "Please provide a version that matches one provided on" 27 | echo "https://github.com/lihaoyi/mill/releases" 28 | false 29 | fi 30 | fi 31 | 32 | # Please note, that if a MILL_VERSION is already set in the environment, 33 | # We reuse it's value and skip searching for a value. 34 | 35 | # If not already set, read .mill-version file 36 | if [ "x${MILL_VERSION}" = "x" ] ; then 37 | if [ -f ".mill-version" ] ; then 38 | MILL_VERSION="$(head -n 1 .mill-version 2> /dev/null)" 39 | fi 40 | fi 41 | 42 | if [ "x${XDG_CACHE_HOME}" != "x" ] ; then 43 | MILL_DOWNLOAD_PATH="${XDG_CACHE_HOME}/mill/download" 44 | else 45 | MILL_DOWNLOAD_PATH="${HOME}/.cache/mill/download" 46 | fi 47 | 48 | # If not already set, try to fetch newest from Github 49 | if [ "x${MILL_VERSION}" = "x" ] ; then 50 | # TODO: try to load latest version from release page 51 | echo "No mill version specified." 52 | echo "You should provide a version via '.mill-version' file or --mill-version option." 53 | 54 | mkdir -p "${MILL_DOWNLOAD_PATH}" 55 | LANG=C touch -d '1 hour ago' "${MILL_DOWNLOAD_PATH}/.expire_latest" 56 | if [ "${MILL_DOWNLOAD_PATH}/.latest" -nt "${MILL_DOWNLOAD_PATH}/.expire_latest" ] ; then 57 | # we know a current latest version 58 | MILL_VERSION="$(head -n 1 ${MILL_DOWNLOAD_PATH}/.latest 2> /dev/null)" 59 | fi 60 | 61 | if [ "x${MILL_VERSION}" = "x" ] ; then 62 | # we don't know a current latest version 63 | echo "Retrieving latest mill version ..." 64 | LANG=C curl -s -i -f -I https://github.com/lihaoyi/mill/releases/latest 2> /dev/null | grep Location: | sed s'/^.*tag\///' | tr -d '\r\n' > "${MILL_DOWNLOAD_PATH}/.latest" 65 | MILL_VERSION="$(head -n 1 ${MILL_DOWNLOAD_PATH}/.latest 2> /dev/null)" 66 | fi 67 | 68 | if [ "x${MILL_VERSION}" = "x" ] ; then 69 | # Last resort 70 | MILL_VERSION="${DEFAULT_MILL_VERSION}" 71 | echo "Falling back to hardcoded mill version ${MILL_VERSION}" 72 | else 73 | echo "Using mill version ${MILL_VERSION}" 74 | fi 75 | fi 76 | 77 | MILL="${MILL_DOWNLOAD_PATH}/${MILL_VERSION}" 78 | 79 | # If not already downloaded, download it 80 | if [ ! -x "${MILL}" ] ; then 81 | 82 | # support old non-XDG download dir 83 | MILL_OLD_DOWNLOAD_PATH="${HOME}/.mill/download" 84 | OLD_MILL="${MILL_OLD_DOWNLOAD_PATH}/${MILL_VERSION}" 85 | if [ -x "${OLD_MILL}" ] ; then 86 | MILL="${OLD_MILL}" 87 | else 88 | VERSION_PREFIX="$(echo -n $MILL_VERSION | cut -b -4)" 89 | case $VERSION_PREFIX in 90 | 0.0. | 0.1. | 0.2. | 0.3. | 0.4. ) 91 | DOWNLOAD_SUFFIX="" 92 | ;; 93 | *) 94 | DOWNLOAD_SUFFIX="-assembly" 95 | ;; 96 | esac 97 | unset VERSION_PREFIX 98 | 99 | DOWNLOAD_FILE=$(mktemp mill.XXXX) 100 | # TODO: handle command not found 101 | echo "Downloading mill ${MILL_VERSION} from https://github.com/lihaoyi/mill/releases ..." 102 | curl -L -o "${DOWNLOAD_FILE}" "https://github.com/lihaoyi/mill/releases/download/${MILL_VERSION%%-*}/${MILL_VERSION}${DOWNLOAD_SUFFIX}" 103 | chmod +x "${DOWNLOAD_FILE}" 104 | mkdir -p "${MILL_DOWNLOAD_PATH}" 105 | mv "${DOWNLOAD_FILE}" "${MILL}" 106 | 107 | unset DOWNLOAD_FILE 108 | unset DOWNLOAD_SUFFIX 109 | fi 110 | fi 111 | 112 | unset MILL_DOWNLOAD_PATH 113 | unset MILL_OLD_DOWNLOAD_PATH 114 | unset OLD_MILL 115 | unset MILL_VERSION 116 | 117 | exec $MILL "$@" 118 | -------------------------------------------------------------------------------- /main/src/de/tobiasroeser/mill/kotlin/KotlinModule.scala: -------------------------------------------------------------------------------- 1 | package de.tobiasroeser.mill.kotlin 2 | 3 | import java.io.File 4 | import java.net.{URL, URLClassLoader} 5 | import mill.{Agg, T} 6 | import mill.api.{Ctx, PathRef, Result} 7 | import mill.define.{Command, Task, Worker} 8 | import mill.modules.{Jvm, Util} 9 | import mill.scalalib.{Dep, DepSyntax, JavaModule, TestModule} 10 | import mill.scalalib.api.CompilationResult 11 | 12 | trait KotlinModule extends JavaModule with KotlinModulePlatform { outer => 13 | 14 | /** 15 | * All individual source files fed into the compiler. 16 | */ 17 | override def allSourceFiles = T { 18 | def isHiddenFile(path: os.Path) = path.last.startsWith(".") 19 | 20 | for { 21 | root <- allSources() 22 | if os.exists(root.path) 23 | path <- (if (os.isDir(root.path)) os.walk(root.path) else Seq(root.path)) 24 | if os.isFile(path) && !isHiddenFile(path) && Seq("kt", "kts", "java").exists(path.ext.toLowerCase() == _) 25 | } yield PathRef(path) 26 | } 27 | 28 | /** 29 | * All individual Java source files fed into the compiler. 30 | * Subset of [[allSourceFiles]]. 31 | */ 32 | def allJavaSourceFiles = T { 33 | allSourceFiles().filter(_.path.ext.toLowerCase() == "java") 34 | } 35 | 36 | /** 37 | * All individual Kotlin source files fed into the compiler. 38 | * Subset of [[allSourceFiles]]. 39 | */ 40 | def allKotlinSourceFiles = T { 41 | allSourceFiles().filter(path => Seq("kt", "kts").exists(path.path.ext.toLowerCase() == _)) 42 | } 43 | 44 | /** 45 | * The Kotlin version to be used (for API and Language level settings). 46 | */ 47 | def kotlinVersion: T[String] 48 | 49 | /** 50 | * The dependencies of this module. 51 | * Defaults to add the kotlin-stdlib dependency matching the [[kotlinVersion]]. 52 | */ 53 | override def ivyDeps: T[Agg[Dep]] = T { 54 | super.ivyDeps() ++ Agg( 55 | ivy"org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion()}" 56 | ) 57 | } 58 | 59 | /** 60 | * The version of the Kotlin compiler to be used. 61 | * Default is derived from [[kotlinVersion]]. 62 | */ 63 | def kotlinCompilerVersion: T[String] = T { kotlinVersion() } 64 | 65 | /** 66 | * The Ivy/Coursier dependencies resembling the Kotlin compiler. 67 | * Default is derived from [[kotlinCompilerVersion]]. 68 | */ 69 | override def kotlinCompilerIvyDeps: T[Agg[Dep]] = T { 70 | Agg(ivy"${Versions.millKotlinWorkerImplIvyDep}") ++ 71 | Agg(ivy"org.jetbrains.kotlin:kotlin-compiler:${kotlinCompilerVersion()}") ++ 72 | // ( 73 | // if (Seq("1.0.", "1.1.", "1.2").exists(prefix => kotlinVersion().startsWith(prefix))) 74 | // Agg(ivy"org.jetbrains.kotlin:kotlin-runtime:${kotlinCompilerVersion()}") 75 | // else Seq() 76 | // ) ++ 77 | ( 78 | if ( 79 | !Seq("1.0.", "1.1.", "1.2.0", "1.2.1", "1.2.2", "1.2.3", "1.2.4").exists(prefix => 80 | kotlinVersion().startsWith(prefix) 81 | ) 82 | ) 83 | Agg(ivy"org.jetbrains.kotlin:kotlin-scripting-compiler:${kotlinCompilerVersion()}") 84 | else Seq() 85 | ) 86 | // ivy"org.jetbrains.kotlin:kotlin-scripting-compiler-impl:${kotlinCompilerVersion()}", 87 | // ivy"org.jetbrains.kotlin:kotlin-scripting-common:${kotlinCompilerVersion()}", 88 | } 89 | 90 | // @Deprecated("Use kotlinWorkerTask instead, as this does not need to be cached as Worker") 91 | // def kotlinWorker: Worker[KotlinWorker] = T.worker { 92 | // kotlinWorkerTask() 93 | // } 94 | 95 | def kotlinWorkerTask: Task[KotlinWorker] = T.task { 96 | kotlinWorkerRef().kotlinWorkerManager().get(kotlinCompilerClasspath()) 97 | } 98 | 99 | /** 100 | * Compiles all the sources to JVM class files. 101 | */ 102 | override def compile: T[CompilationResult] = T { 103 | kotlinCompileTask()() 104 | } 105 | 106 | /** 107 | * Runs the Kotlin compiler with the `-help` argument to show you the built-in cmdline help. 108 | * You might want to add additional arguments like `-X` to see extra help. 109 | */ 110 | def kotlincHelp(args: String*): Command[Unit] = T.command { 111 | kotlinCompileTask(Seq("-help") ++ args)() 112 | () 113 | } 114 | 115 | protected def when(cond: Boolean)(args: String*): Seq[String] = if (cond) args else Seq() 116 | 117 | /** 118 | * The actual Kotlin compile task (used by [[compile]] and [[kotlincHelp]]. 119 | */ 120 | protected def kotlinCompileTask(extraKotlinArgs: Seq[String] = Seq()): Task[CompilationResult] = T.task { 121 | val ctx = T.ctx() 122 | val dest = ctx.dest 123 | val classes = dest / "classes" 124 | os.makeDir.all(classes) 125 | 126 | val javaSourceFiles = allJavaSourceFiles().map(_.path) 127 | val kotlinSourceFiles = allKotlinSourceFiles().map(_.path) 128 | 129 | val isKotlin = kotlinSourceFiles.nonEmpty 130 | val isJava = javaSourceFiles.nonEmpty 131 | val isMixed = isKotlin && isJava 132 | 133 | val compileCp = compileClasspath().map(_.path).filter(os.exists) 134 | val updateCompileOutput = upstreamCompileOutput() 135 | 136 | def compileJava: Result[CompilationResult] = { 137 | ctx.log.info( 138 | s"Compiling ${javaSourceFiles.size} Java sources to ${classes} ..." 139 | ) 140 | // The compile step is lazy, but it's dependencies are not! 141 | internalCompileJavaFiles( 142 | worker = zincWorkerRef().worker(), 143 | upstreamCompileOutput = updateCompileOutput, 144 | javaSourceFiles = javaSourceFiles, 145 | compileCp = compileCp, 146 | javacOptions = javacOptions(), 147 | compileProblemReporter = ctx.reporter(hashCode), 148 | reportOldProblems = internalReportOldProblems() 149 | ) 150 | } 151 | 152 | if (isMixed || isKotlin) { 153 | ctx.log.info( 154 | s"Compiling ${kotlinSourceFiles.size} Kotlin sources to ${classes} ..." 155 | ) 156 | val compilerArgs: Seq[String] = Seq( 157 | // destdir 158 | Seq("-d", classes.toIO.getAbsolutePath()), 159 | // classpath 160 | when(compileCp.iterator.nonEmpty)("-classpath", compileCp.iterator.mkString(File.pathSeparator)), 161 | kotlincOptions(), 162 | extraKotlinArgs, 163 | // parameters 164 | (kotlinSourceFiles ++ javaSourceFiles).map(_.toIO.getAbsolutePath()) 165 | ).flatten 166 | 167 | val workerResult = kotlinWorkerTask().compile(compilerArgs: _*) 168 | 169 | val analysisFile = dest / "kotlin.analysis.dummy" 170 | os.write(target = analysisFile, data = "", createFolders = true) 171 | 172 | workerResult match { 173 | case Result.Success(_) => 174 | val cr = CompilationResult(analysisFile, PathRef(classes)) 175 | if (!isJava) { 176 | // pure Kotlin project 177 | cr 178 | } else { 179 | // also run Java compiler and use it's returned result 180 | compileJava 181 | } 182 | case Result.Failure(reason, _) => 183 | Result.Failure(reason, Some(CompilationResult(analysisFile, PathRef(classes)))) 184 | case e: Result.Exception => e 185 | case Result.Aborted => Result.Aborted 186 | case Result.Skipped => Result.Skipped 187 | // case x => x 188 | } 189 | } else { 190 | // it's Java only 191 | compileJava 192 | } 193 | } 194 | 195 | /** 196 | * Additional Kotlin compiler options to be use by [[compile]]. 197 | */ 198 | def kotlincOptions: T[Seq[String]] = T { 199 | Seq("-no-stdlib") ++ 200 | when(!kotlinVersion().startsWith("1.0"))( 201 | "-language-version", 202 | kotlinVersion().split("[.]", 3).take(2).mkString("."), 203 | "-api-version", 204 | kotlinVersion().split("[.]", 3).take(2).mkString(".") 205 | ) 206 | } 207 | 208 | /** 209 | * A test sub-module linked to its parent module best suited for unit-tests. 210 | */ 211 | trait KotlinModuleTests extends JavaModuleTests with KotlinTestModule { 212 | override def kotlinVersion: T[String] = T { outer.kotlinVersion() } 213 | override def kotlinCompilerVersion: T[String] = T { outer.kotlinCompilerVersion() } 214 | override def kotlincOptions: T[Seq[String]] = T { outer.kotlincOptions() } 215 | } 216 | @deprecated("Use KotlinModuleTests instead.", "mill-kotlin after 0.2.2") 217 | trait Tests extends KotlinModuleTests 218 | 219 | } 220 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = mill-kotlin - Kotlin compiler support for mill 2 | :version: 0.3.0 3 | :mill-platform: 0.11 4 | :kotlinVersion: 1.9.21 5 | :projectHome: https://github.com/lefou/mill-kotlin 6 | :min-mill-version: 0.7.0 7 | 8 | ifdef::env-github[] 9 | image:https://github.com/lefou/mill-kotlin/workflows/.github/workflows/build.yml/badge.svg["Build Status (GitHub Actions)", link="https://github.com/lefou/mill-kotlin/actions"] 10 | image:https://codecov.io/gh/lefou/mill-kotlin/branch/main/graph/badge.svg[Test Coverage (Codecov.io), link="https://codecov.io/gh/lefou/mill-kotlin"] 11 | endif::[] 12 | 13 | Documentation for mill-kotlin, a mill plugin to support the https://kotlinlang.org/[Kotlin language and compiler]. 14 | 15 | == Quickstart 16 | 17 | Mill version {min-mill-version} or newer is required. 18 | 19 | [source,scala,subs="attributes,verbatim"] 20 | ---- 21 | // Load the plugin from Maven Central via ivy/coursier 22 | import $ivy.`de.tototec::de.tobiasroeser.mill.kotlin_mill{mill-platform}:{version}` 23 | 24 | import mill._ 25 | import mill.scalalib._ 26 | import mill.define._ 27 | 28 | import de.tobiasroeser.mill.kotlin._ 29 | 30 | object main extends KotlinModule { 31 | 32 | // Select the Kotlin version 33 | def kotlinVersion = T{ "{kotlinVersion}" } 34 | 35 | // Set additional Kotlin compiler options, e.g. the language level and annotation processor 36 | // Run `mill main.kotlincHelp` to get a list of supported options 37 | def kotlincOptions = super.kotlincOptions() ++ Seq("-verbose") 38 | 39 | } 40 | ---- 41 | 42 | == Configuration 43 | 44 | To target the JVM (kotlin-jvm), our module needs to extend `de.tobiasroeser.mill.kotlin.KotlinModule` which itself extends `mill.scalalib.JavaModule`. 45 | 46 | For convenience, you may derive your unit test projects from `de.tobiasroeser.mill.kotlin.KotlinModule.Tests` (or `KotlinModuleTests`) trait. 47 | 48 | The module trait `de.tobiasroeser.mill.kotlin.KotlinModule` has the following configuration options (over those from `mill.scalalib.JavaModule`). 49 | 50 | `def kotlinVersion: T[String]`:: 51 | The Kotlin version to be used (for API and Language level settings). 52 | 53 | `def kotlinCompilerVersion: T[String]`:: The version of the Kotlin compiler to be used. 54 | Default is derived from `kotlinVersion`. 55 | 56 | `def compile: T[CompilationResult]`:: 57 | Compiles all the sources to JVM class files. 58 | 59 | `def kotlincOptions: T[Seq[String]]`:: 60 | Additional Kotlin compiler options to be use by `compile`. 61 | 62 | `def ivyDeps: T[Agg[Dep]]`:: 63 | The compile and runtime dependencies. 64 | 65 | `def kotlincHelp(args: String*): Command[Unit]`:: 66 | Runs the Kotlin compiler with the `-help` argument to show you the built-in cmdline help. 67 | You might want to add additional arguments like `-X` to see extra help. 68 | 69 | `def kotlinCompilerIvyDeps: T[Agg[Dep]]`:: 70 | The Ivy/Coursier dependencies resembling the Kotlin compiler. 71 | Default is derived from `kotlinCompilerVersion`. 72 | 73 | `def kotlinCompilerClasspath: T[Seq[PathRef]]`:: 74 | The Java classpath resembling the Kotlin compiler. 75 | Default is derived from `kotlinCompilerIvyDeps`. 76 | 77 | `trait Tests extends TestModule with KotlinTestModule`:: 78 | A test sub-module linked to its parent module best suited for unit-tests. 79 | 80 | Mixed Kotlin/Java projects are also supported. Java compilation is based on mills `mill.scalalib.JavaModule` and Java options are configured via `javacOptions`. 81 | 82 | == Version Compatibility Matrix 83 | 84 | Mill is still in active development, and has no stable API yet. 85 | Hence, not all mill-kotlin versions work with every mill version. 86 | 87 | The following table shows a matrix of compatible mill and mill-kotlin versions. 88 | 89 | .Version Compatibility Matrix 90 | [options="header"] 91 | |=== 92 | | mill-kotlin | mill 93 | | 0.3.0 | 0.7.0 - 0.11.x 94 | | 0.2.4 | 0.7.0 - 0.11.x 95 | | 0.2.3 | 0.7.0 - 0.11.x 96 | | 0.2.2 | 0.6.0 - 0.10.x 97 | | 0.2.1 | 0.6.0 - 0.9.x 98 | | 0.2.0 | 0.6.0 - 0.9.x 99 | | 0.1.1 | 0.6.0 - 0.9.6 100 | | 0.1.0 | 0.6.0 - 0.8.0 101 | | 0.0.3 | 0.6.0 - 0.6.1 102 | | 0.0.2 | 0.5.7 103 | | 0.0.1 | 0.5.7 104 | |=== 105 | 106 | To ensure some basic compatibility, there are some integration tests in place. 107 | Newer mill versions may work as well. 108 | 109 | If you need support for other versions, please create an {projectHome}/issues[issue]. 110 | 111 | == Download 112 | 113 | You can download binary releases from https://search.maven.org/artifact/de.tototec/de.tobiasroeser.mill.kotlin_mill{mill-platform}_2.13[Maven Central]. 114 | 115 | Please make sure to use the correct _mill platform suffix_ matching your used mill version. 116 | 117 | .Mill Platform suffix 118 | [options="header"] 119 | |=== 120 | | mill version | mill platform | suffix | example 121 | | 0.11.x | 0.11 | `_mill0.11` | ```$ivy.`de.tototec::de.tobiasroeser.mill.kotlin::{version}```` 122 | | 0.10.x | 0.10 | `_mill0.10` | ```$ivy.`de.tototec::de.tobiasroeser 123 | .mill.kotlin::{version}```` 124 | | 0.9.3 - | 0.9 | `_mill0.9` | ```$ivy.`de.tototec::de.tobiasroeser.mill.kotlin_mill0.9:{version}```` 125 | | 0.7.0 - 0.8.0 | 0.7 | `_mill0.7` | ```$ivy.`de.tototec::de.tobiasroeser.mill.kotlin_mill0.7:{version}```` 126 | |=== 127 | 128 | 129 | == License 130 | 131 | This project is published under the terms of the https://www.apache.org/licenses/LICENSE-2.0[Apache License, version 2] 132 | 133 | == Supporters 134 | 135 | Thanks to https://iba-cg.de/[iba Consulting Gesellschaft mbH & Co KG] for the initial development support. 136 | 137 | == About 138 | 139 | Mill:: 140 | https://github.com/lihaoyi/mill[Mill] is a Scala-based open source build tool. 141 | In my opinion the best build tool for the JVM. 142 | It is fast, reliable and easy to understand. 143 | 144 | Me:: 145 | + 146 | -- 147 | I am https://github.com/lefou/[Tobias Roeser], a professional software developer who loves to create and use open source tools. 148 | I'm actively developing and maintaining mill as well as https://github.com/lefou?utf8=%E2%9C%93&tab=repositories&q=topic%3Amill&type=&language=[several mill plugins]. 149 | 150 | If you like my work, please star it on GitHub. You can also support me via https://github.com/sponsors/lefou[GitHub Sponsors]. 151 | -- 152 | 153 | Contributing:: 154 | If you found a bug or have a feature request, please open a {projectHome}/issues[new issue on GitHub]. 155 | I also accept {projectHome}/pulls[pull requests on GitHub]. 156 | 157 | == Changelog 158 | 159 | === 0.3.0 - 2023-11-29 160 | :version: 0.3.0 161 | :prev-version: 0.2.4 162 | :github-milestone: 8 163 | 164 | * Introduced a shared worker cache to speed up compilation and reduce memory usage 165 | 166 | _See 167 | ifeval::["{github-milestone}" != ""] 168 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 169 | and the 170 | endif::[] 171 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 172 | 173 | 174 | === 0.2.4 - 2023-10-23 175 | :version: 0.2.4 176 | :prev-version: 0.2.3 177 | :github-milestone: 7 178 | 179 | * Internal improvements and dependency updates 180 | 181 | _See 182 | ifeval::["{github-milestone}" != ""] 183 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 184 | and the 185 | endif::[] 186 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 187 | 188 | 189 | === 0.2.3 - 2023-06-12 190 | :version: 0.2.3 191 | :prev-version: 0.2.2 192 | :github-milestone: 6 193 | 194 | * Added support for Mill 0.11.x 195 | * Various internal improvements and version updates 196 | 197 | _See 198 | ifeval::["{github-milestone}" != ""] 199 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 200 | and the 201 | endif::[] 202 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 203 | 204 | 205 | === 0.2.2 - 2022-01-16 206 | :version: main 207 | :prev-version: 0.2.1 208 | :github-milestone: 5 209 | 210 | * Support for newer Mill versions including 0.10.0 211 | 212 | _See 213 | ifeval::["{github-milestone}" != ""] 214 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 215 | and the 216 | endif::[] 217 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 218 | 219 | 220 | === 0.2.1 - 2022-01-16 221 | :version: 0.2.1 222 | :prev-version: 0.2.0 223 | :github-milestone: 4 224 | 225 | * Improved integration test suite 226 | * Various dependency version updates 227 | 228 | _See 229 | ifeval::["{github-milestone}" != ""] 230 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 231 | and the 232 | endif::[] 233 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 234 | 235 | 236 | === 0.2.0 - 2021-01-17 237 | :version: 0.2.0 238 | :prev-version: 0.1.1 239 | :github-milestone: 240 | 241 | * Overall fixes and improvements 242 | * Enhanced integration test setup to detect Kotlin version differences 243 | * Proper support for Kotlin 1.3 and 1.4 244 | * Limited support for older Kotlin 1.0, 1.1 and 1.2 245 | + 246 | _These versions may work for you, but I haven't found a stable integration test setup that works reliable for all these Kotlin releases on different platforms and different Java versions. 247 | If you know what you're doing, all integration points are configurable, so these versions should work after same tweaking. 248 | Feedback and pull requests are highly appreciated._ 249 | 250 | _See 251 | ifeval::["{github-milestone}" != ""] 252 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 253 | and the 254 | endif::[] 255 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 256 | 257 | === 0.1.1 - 2020-12-01 258 | :version: 0.1.1 259 | :prev-version: 0.1.0 260 | :github-milestone: 3 261 | 262 | * Support for mill API 0.9.3 263 | * Introduced artifact suffix indicating the mill platform (e.g. `mill0.9`) 264 | 265 | _See 266 | ifeval::["{github-milestone}" != ""] 267 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 268 | and the 269 | endif::[] 270 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 271 | 272 | === 0.1.0 - 2020-06-30 273 | :version: 0.1.0 274 | :prev-version: 0.0.3 275 | :github-milestone: 2 276 | 277 | * Cross publish for Mill APi 0.6 and 0.7, also Scala 2.12 and Scala 2.13. 278 | 279 | _See 280 | ifeval::["{github-milestone}" != ""] 281 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 282 | and the 283 | endif::[] 284 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 285 | 286 | 287 | === 0.0.3 - 2020-02-25 288 | :version: 0.0.3 289 | :prev-version: 0.0.2 290 | :github-milestone: 291 | 292 | * Updated Mill API to 0.6.0 293 | 294 | _See 295 | ifeval::["{github-milestone}" != ""] 296 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 297 | and the 298 | endif::[] 299 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 300 | 301 | 302 | === 0.0.2 - 2020-02-25 303 | :version: 0.0.2 304 | :prev-version: 0.0.1 305 | :github-milestone: 1 306 | 307 | * Fixed non-functional `kotlincHelp` target 308 | 309 | _See 310 | ifeval::["{github-milestone}" != ""] 311 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 312 | and the 313 | endif::[] 314 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 315 | 316 | === 0.0.1 - 2020-02-20 317 | :version: 0.0.1 318 | :prev-version: 6756a7323d020eabedf9a9cd70f54c61fe30472a 319 | :github-milestone: 320 | 321 | * Initial release 322 | 323 | _See 324 | ifeval::["{github-milestone}" != ""] 325 | https://github.com/lefou/mill-kotlin/milestone/{github-milestone}?closed=1[milstone {version}] 326 | and the 327 | endif::[] 328 | https://github.com/lefou/mill-kotlin/compare/{prev-version}\...{version}[list of commits]_ 329 | --------------------------------------------------------------------------------