Создание проекта Kotlin + Java 9 с помощью Gradle

Я новичок в Gradle (и, честно говоря, Java 9), и я пытаюсь использовать Gradle для создания простого проекта библиотеки, представляющего собой сочетание Java 9 и Kotlin. Более подробно, есть интерфейс в Java и реализация в Котлине; Я бы сделал все в Котлине, но modules-info.java - это Java, так что я решил сделать так.

Я основываюсь на IntelliJ Idea, с плагином 1.2.0 kotlin и Gradle 4.3.1, определенным извне.

Схема файловой системы:

+ src
  + main
    + java
      + some.package
        - Roundabout.java [an interface]
      - module-info.java
    + kotlin
      + some.package.impl
        - RoundaboutImpl.kt [implementing the interface]

module-info.java:

module some.package {
  requires kotlin.stdlib;
  exports some.package;
}

и build.gradle:

buildscript {
    ext.kotlin_version = '1.2.0'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

group 'some.package'
version '1.0-PRE_ALPHA'

apply plugin: 'java-library'
apply plugin: 'kotlin'

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

sourceCompatibility = 9

compileJava {
    dependsOn(':compileKotlin')
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
        ]
        classpath = files()
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: "$kotlin_version"
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

Обратите внимание, что мне пришлось указать путь к модулю в java-компиляционной задаче или сбой компиляции:

Ошибка: модуль не найден: kotlin.stdlib требует kotlin.stdlib;

В любом случае, теперь эта сборка завершилась с ошибкой, и я не могу понять, как ее решить:

Ошибка: пакет some.package.impl не существует

import some.package.impl.RoundaboutImpl;

ошибка: не удается найти символ

вернуть новый RoundaboutImpl < > (queueSize, parallelism, worker, threadPool);

Я думаю, что часть Kotlin компиляции идет нормально, тогда java-часть терпит неудачу, потому что она не "видит" сторону kotlin, так сказать.

Я думаю, что мне нужно как-то сказать загрузить уже скомпилированные классы kotlin в classpath; но (сначала), как это сделать в gradle? и (второй), это даже возможно? Я думаю, вы не можете смешивать путь к модулю и путь класса в Java 9.

Как я могу это решить? Я думаю, что это довольно распространенная ситуация, так как каждый модуль java9-стиля будет модулем на смешанном языке (из-за module-info.java), поэтому я думаю, что мне не хватает чего-то действительно основного.

Спасибо заранее!

Ответ 1

Решено! Достаточно было установить каталог компиляции kotlin в тот же каталог, что и Java:

compileKotlin.destinationDir = compileJava.destinationDir

Теперь он работает как с источниками в одном и том же дереве, так и на разных деревьях; но с quirk: задача jar создает банку со всеми дублируемыми элементами. Я поработаю над этим, затем.

Спасибо всем!

Ответ 2

Я использую следующий скрипт gradle, где я помещаю module-info.java в src/module. Он автоматически включается в банку (без дубликатов):

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

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

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

Я больше не буду обновлять его, взгляните на https://github.com/robstoll/atrium/blob/master/build.gradle чтобы увидеть текущую версию в использовании.

Ответ 3

Принятый ответ не работает для меня (по крайней мере, не так, как он был представлен), но это то, что сработало:

plugins {
    id "org.jetbrains.kotlin.jvm" version "1.3.50"
}

compileKotlin {
    doFirst {
        destinationDir = compileJava.destinationDir
    }
}

jar {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

В соответствии с принятым ответом я получил эту ошибку:

Каталог '/path/to/project/build/classes/kotlin/main', указанный для свойство compileKotlinOutputClasses не существует.


Версия Gradle: 5,6