Kotlin Support for Java 9 Module System?


#1

I wonder if Kotlin will support/integrate with the new module system? Is this on your roadmap?
Will the Compiler be aware of a module? Can I create a module in Kotlin?


Kotlin with java9 module
#2

Yes, supporting the Java 9 module system is one of the main priorities for Kotlin 1.2. The compiler will be fully aware of the new visibility rules. You’ll be able to create a module in Kotlin; the module-info file will have to remain in Java (because it’s effectively a separate DSL, and we don’t see much value in reinventing it), but the rest of implementation can be Kotlin.


#3

Kotlin 1.2 is out, so is this now possible? When I change the JDK version in my gradle file to 9, I get this:

e: Unknown JVM target version: 9.0
Supported versions: 1.6, 1.8


#4

Please make sure you’re using a recent Gradle version.


#5
./gradlew --version

------------------------------------------------------------
Gradle 4.4
------------------------------------------------------------

Build time:   2017-12-06 09:05:06 UTC
Revision:     cf7821a6f79f8e2a598df21780e3ff7ce8db2b82

Groovy:       2.4.12
Ant:          Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM:          1.8.0_152 (Oracle Corporation 25.152-b16)
OS:           Linux 4.9.0-3-amd64 amd64

This is the m most recent of gradle I guess.


#6

The same problem.
From https://kotlinlang.org/docs/reference/using-gradle.html :

Target version of the generated JVM bytecode (1.6 or 1.8), default is 1.6
Possible values: “1.6”, “1.8”

So where is java 9?


#7

push


#8

Kotlin currently doesn’t support JVM 9 bytecode generation, however JVM 1.8 bytecode is fully compatible with Java 9.

If you want to build/consume modular jars, you need to author module-info.java file in your project. This isn’t different from a java-only project, you can refer to this Gradle guide for details on how to do that.


#9

I followed the mentioned guide but get stuck at the point that the build fails with errors like the following:

module-info.java:2: error: package is empty or does not exist: ch.tutteli.atrium.assertions

I am able to tweak the build with the solution mentioned in a SO question:

compileKotlin.destinationDir = compileJava.destinationDir

but it seems like a hack to me, is there kind of an official way of doing it?


#10

I currently use the following gradle code in my root build.gradle, where I can place the module-info.java under src/module

if (JavaVersion.current() >= JavaVersion.VERSION_1_9) {
    subprojects {
        def moduleInfo = file("${project.projectDir}/src/module/module-info.java")
        if (moduleInfo.exists()) {

            sourceSets {
                module {
                    java {
                        srcDirs = ['src/module']
                        compileClasspath = main.compileClasspath
                        sourceCompatibility = '9'
                        targetCompatibility = '9'
                    }
                }
                main {
                    kotlin { srcDirs += ['src/module'] }
                }
            }

            compileModuleJava.configure {
                dependsOn compileKotlin
                destinationDir = compileKotlin.destinationDir
                doFirst {
                    options.compilerArgs = ['--module-path', classpath.asPath,]
                    classpath = files()
                }
            }
            jar.dependsOn compileModuleJava
        }
    }
}

Edit: I added src/module to the source of main.kotlin in order that the kotlin compiler analyses the module-info.java and complains if necessary.

@ilya.gorbunov when is kotlin turning its jars into modules? I currently get the following warning because I do not want to specify kotlin.stlib for every module:

warning: requires transitive directive for an automatic module
    requires transitive kotlin.stdlib;

#11

Not sure if I got it right @ilya.gorbunov. You mean… is it possible to compile my Kotlin source code (with JPMS modules) targeting JDK 8?

I am currently trying to build a simple HelloWorld project (without gradle) and it raises error when compiling targeting JDK8:
Error:Kotlin: Module java.base cannot be found in the module graph

When targeting higher JDK i.e. 10, it compiles successfull.


#12

I didn’t say and didn’t mean you can target JDK 8 to build modular code, I meant you can target JDK 9 or 10 and compile to the JVM 8 bytecode which can be executed on JVM 9 and 10.


#13

We have to wait until Android build tools of version 3.2 get large adoption, because the previous versions don’t work well with modular jars, see https://youtrack.jetbrains.com/issue/KT-21266 and https://issuetracker.google.com/issues/77587908 for details.


#14

Once Kotlin & Gradle together properly support JPMS modules, for a build that only has Kotlin source, plus a module-info.java but no other Java source, will the output directories for compileJava & compileKotlin have to be the same, as per the aforementioned SO hack? Or will the output directories be able to be separate on a per-language basis, as is the current case for non-JPMS Gradle outputs?

If the latter, how will this be supported? Is there any way for javac to include already compiled class files in a module defined in a module-info.java in the current build?


#15

We have to wait until Android build tools of version 3.2 get large adoption, because the previous versions don’t work well with modular jars, see https://youtrack.jetbrains.com/issue/KT-21266 12 and https://issuetracker.google.com/issues/77587908 7 for details.

@ilya.gorbunov - Are you saying that Kotliner’s using Kotlin on the JVM (eg for server-side development) instead of Android have to wait for the above issue to be resolved, even though the issue is specific to Android and not the JVM itself?


#16

Yes, unfortunately it is so. We don’t want to introduce a change that will break the build for the significant part of our users.

As a temporary alternative we’re considering to build and publish modular artifacts of our libraries under separate maven classifier, say org.jetbrains.kotlin:kotlin-stdlib:1.2.nn:modular. Would that help, in your opinion?


#17

I I think it is a great idea. I still have to wait for tornadofx to move to Java 9, but I hope they will do it soon.


#18

As a temporary alternative we’re considering to build and publish modular artifacts of our libraries under separate maven classifier, say org.jetbrains.kotlin:kotlin-stdlib:1.2.nn:modular. Would that help, in your opinion?

It would work for most situations (about 75% as a rough guesstimate), however the pragmatic move wouldn’t be enough in situations where Kotliner’s need to easily deploy a program via the jlink tool. One of the key requirements mandated by jlink is that the entire program is modularized (incl all dependencies).