web-dev-qa-db-fra.com

Construire un Kotlin + Java 9 avec Gradle

Je suis assez nouveau sur Gradle (et Java 9, pour être honnête), et j'essaie d'utiliser Gradle pour construire un projet de bibliothèque simple qui est un mélange de Java 9 et Kotlin. Plus en détail, il y a une interface dans Java et une implémentation dans Kotlin; je ferais tout dans Kotlin, mais le modules-info.Java est Java de toute façon, j'ai donc décidé de faire les choses de cette façon.

Je m'appuie sur IntelliJ Idea, avec le plugin kotlin 1.2.0 et gradle 4.3.1 définis en externe.

Le schéma du système de fichiers est:

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

module-info.Java est:

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

et build.gradle est:

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"
}

Notez que je devais spécifier un chemin de module sur la tâche de compilation Java, ou la compilation échoue avec:

erreur: module introuvable: kotlin.stdlib nécessite kotlin.stdlib;

Quoi qu'il en soit, maintenant cette construction échoue avec cette erreur, et je ne peux pas comprendre comment le résoudre:

erreur: le package some.package.impl n'existe pas

importez some.package.impl.RoundaboutImpl;

erreur: impossible de trouver le symbole

return new RoundaboutImpl <> (queueSize, parallelism, worker, threadPool);

Je pense que la partie Kotlin de la compilation se passe bien, alors la partie Java échoue car elle ne "voit" pas le côté kotlin, pour ainsi dire.

Je pense que je devrais lui dire en quelque sorte de charger les classes kotlin déjà compilées dans le chemin de classe; mais (d'abord) comment faire ça en gradle? et (deuxième) est-ce même possible? Je pense que vous ne pouvez pas mélanger le chemin du module et le chemin de la classe dans Java 9.

Comment puis-je resoudre ceci? Je pense que c'est une situation assez courante, car chaque module de style Java9 sera un module mixte (à cause de module-info.Java), donc je pense qu'il me manque quelque chose de vraiment basique ici.

Merci d'avance!

17
Germano Rizzo

Résolu! Il suffisait de définir le répertoire de compilation kotlin sur le même répertoire que Java:

compileKotlin.destinationDir = compileJava.destinationDir

Cela fonctionne maintenant, à la fois avec les sources dans le même arbre ou dans des arbres différents; mais avec une bizarrerie: la tâche jar produit un bocal avec toutes les entrées dupliquées. Je vais travailler sur le problème, ensuite.

Merci à tout le monde!

11
Germano Rizzo

J'utilise le script gradle suivant où je mets le module-info.Java sous src/module. Il est automatiquement inclus dans le pot (sans doublons):

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
        }
    }
}

Je ne le mettrai plus à jour, jetez un œil à https://github.com/robstoll/atrium/blob/master/build.gradle pour voir la version actuelle en cours d'utilisation.

2
Robert Stoll

La réponse acceptée n'a pas fonctionné pour moi (du moins pas la façon dont elle a été présentée), mais c'est ce qui a fonctionné:

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

compileKotlin {
    doFirst {
        destinationDir = compileJava.destinationDir
    }
}

jar {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

Le faire comme le suggère la réponse acceptée m'a conduit à obtenir cette erreur:

Le répertoire '/ path/to/project/build/classes/kotlin/main' spécifié pour la propriété 'compileKotlinOutputClasses' n'existe pas.


version Gradle: 5.6

0
smac89