Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add very basic Kotlin/JS support: ability to compile the binary #3678

Merged
merged 5 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions docs/modules/ROOT/pages/kotlinlib/web-examples.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ It covers setting up a basic backend server with a variety of server frameworks
== Ktor Hello World App

include::partial$example/kotlinlib/web/1-hello-ktor.adoc[]

== Ktor TodoMvc App

include::partial$example/kotlinlib/web/2-todo-ktor.adoc[]

== (Work In Progress) Simple KotlinJS Module

include::partial$example/kotlinlib/web/3-hello-kotlinjs.adoc[]

43 changes: 43 additions & 0 deletions example/kotlinlib/web/3-hello-kotlinjs/build.mill
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// KotlinJS support on Mill is still Work In Progress (WIP). As of time of writing it
// does not support third-party dependencies, Kotlin 2.x with KMP KLIB files, Node.js/Webpack
// test runners and reporting, etc.
//
// The example below demonstrates only the minimal compilation, running, and testing of a single KotlinJS
// module. For more details in fully developing KotlinJS support, see the following ticket:
//
// * https://github.com/com-lihaoyi/mill/issues/3611

package build
import mill._, kotlinlib._, kotlinlib.js._

object foo extends KotlinJSModule {
def moduleKind = ModuleKind.ESModule
def kotlinVersion = "1.9.25"
def kotlinJSRunTarget = Some(RunTarget.Node)
object test extends KotlinJSModule with KotlinJSKotlinXTests
}


/** Usage

> mill foo.run
Compiling 1 Kotlin sources to .../out/foo/compile.dest/classes...
Hello, world
stringifiedJsObject: ["hello","world","!"]

> mill foo.test # Test is incorrect, `foo.test`` fails
Compiling 1 Kotlin sources to .../out/foo/test/compile.dest/classes...
Linking IR to .../out/foo/test/linkBinary.dest/binaries
produce executable: .../out/foo/test/linkBinary.dest/binaries
...
error: AssertionError: Expected <Hello, world>, actual <Not hello, world>.

> cat out/foo/test/linkBinary.dest/binaries/test.js # Generated javascript on disk
...assertEquals_0(getString(), 'Not hello, world');...
...

> sed -i.bak 's/Not hello, world/Hello, world/g' foo/test/src/foo/HelloTests.kt

> mill foo.test # passes after fixing test

*/
11 changes: 11 additions & 0 deletions example/kotlinlib/web/3-hello-kotlinjs/foo/src/foo/Hello.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package foo

fun getString() = "Hello, world"

fun main() {
println(getString())

val parsedJsonStr: dynamic = JSON.parse("""{"helloworld": ["hello", "world", "!"]}""")
val stringifiedJsObject = JSON.stringify(parsedJsonStr.helloworld)
println("stringifiedJsObject: " + stringifiedJsObject)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package foo

import kotlin.test.Test
import kotlin.test.assertEquals

class HelloTests {

@Test
fun failure() {
assertEquals(getString(), "Not hello, world")
}
}

16 changes: 2 additions & 14 deletions kotlinlib/src/mill/kotlinlib/KotlinModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package kotlinlib

import mill.api.{Loose, PathRef, Result}
import mill.define.{Command, ModuleRef, Task}
import mill.kotlinlib.worker.api.KotlinWorker
import mill.kotlinlib.worker.api.{KotlinWorker, KotlinWorkerTarget}
import mill.scalalib.api.{CompilationResult, ZincWorkerApi}
import mill.scalalib.{JavaModule, Lib, ZincWorkerModule}
import mill.util.Jvm
Expand Down Expand Up @@ -92,11 +92,6 @@ trait KotlinModule extends JavaModule { outer =>
*/
def kotlinCompilerIvyDeps: T[Agg[Dep]] = Task {
Agg(ivy"org.jetbrains.kotlin:kotlin-compiler:${kotlinCompilerVersion()}") ++
// (
// if (Seq("1.0.", "1.1.", "1.2").exists(prefix => kotlinVersion().startsWith(prefix)))
// Agg(ivy"org.jetbrains.kotlin:kotlin-runtime:${kotlinCompilerVersion()}")
// else Seq()
// ) ++
(
if (
!Seq("1.0.", "1.1.", "1.2.0", "1.2.1", "1.2.2", "1.2.3", "1.2.4").exists(prefix =>
Expand All @@ -106,15 +101,8 @@ trait KotlinModule extends JavaModule { outer =>
Agg(ivy"org.jetbrains.kotlin:kotlin-scripting-compiler:${kotlinCompilerVersion()}")
else Seq()
)
// ivy"org.jetbrains.kotlin:kotlin-scripting-compiler-impl:${kotlinCompilerVersion()}",
// ivy"org.jetbrains.kotlin:kotlin-scripting-common:${kotlinCompilerVersion()}",
}

// @Deprecated("Use kotlinWorkerTask instead, as this does not need to be cached as Worker")
// def kotlinWorker: Worker[KotlinWorker] = Task.Worker {
// kotlinWorkerTask()
// }

def kotlinWorkerTask: Task[KotlinWorker] = Task.Anon {
kotlinWorkerRef().kotlinWorkerManager().get(kotlinCompilerClasspath())
}
Expand Down Expand Up @@ -264,7 +252,7 @@ trait KotlinModule extends JavaModule { outer =>
(kotlinSourceFiles ++ javaSourceFiles).map(_.toIO.getAbsolutePath())
).flatten

val workerResult = kotlinWorkerTask().compile(compilerArgs: _*)
val workerResult = kotlinWorkerTask().compile(KotlinWorkerTarget.Jvm, compilerArgs: _*)

val analysisFile = dest / "kotlin.analysis.dummy"
os.write(target = analysisFile, data = "", createFolders = true)
Expand Down
Loading
Loading