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?
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.
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
Please make sure you’re using a recent Gradle version.
./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.
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?
push
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.
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?
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;
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.
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.
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.
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?
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?
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?
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.
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).
Meta comment: since the lag between “feature hits JVM/JDK” and “features hits Android” seems to grow with time, and “feature is available on most Android devices” is even worse, I have to wonder whether that strategy is robust.
I mean, Android doesn’t even support Java 8 fully. (At least syntax level, which isn’t as relevant here.)
The problem is not in Android installed on Android devices, but rather in the Android build tools. And by users I mean the developers who use these build tools.