Скомпилируйте проект JDK 8 + JDK 9 "module-info.java" в Gradle - PullRequest
1 голос
/ 11 марта 2019

Я работаю над библиотекой Java, нацеленной на JDK 8, и собираю ее в Gradle 5 с использованием OpenJDK 11. Для нацеливания на JDK 8 я использую javac --release.

Однако я бы хотел, чтобы моя библиотека была совместимой с JPMS.Другими словами:

  • Я хотел бы предоставить module-info.class, скомпилированный с --release 9 (вариант 3 в шкале Стивена Колебурна ),
  • в то время каквсе остальное скомпилировано с --release 8.

MCVE

build.gradle :

plugins {
    id 'java'
    id 'org.javamodularity.moduleplugin' version '1.4.1' // *
}

repositories {
    mavenCentral()
}

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.6'
}

compileJava.options.compilerArgs.addAll(['--release', '9']) // **

* org.javamodularity.moduleplugin устанавливает --module-path для compileJava

** пока нет Gradle DSL для --release: # 2510

src /main / java / module-info.java :

module pl.tlinkowski.sample {
  requires lombok;
  exports pl.tlinkowski.sample;
}

src / main / java / pl / tlinkowski / sample / Sample.java :

package pl.tlinkowski.sample;

@lombok.Value
public class Sample {
  int sample;
}

Этот MCVE компилируется, но все классы (вместо module-info.class) представлены в формате классов JDK 9 ( v.53 ).

Другие инструменты сборки

То, что я хочу сделать, безусловно возможно в:

  1. Maven
    • Например ThreeTen-Extra (их подход сводится к следующему: сначала скомпилируйте все с помощью --release 9, а затем скомпилировать все, кроме module-info.java с --release 8).
  2. Муравей
    • Например Ломбок (их подход сводится к следующему: иметь module-info.java в отдельном «наборе источников» - основной набор источников компилируется с помощью --release 8, а набор источников «информации модуля» компилируется с --release 9).

То, что я пробовал

Мне понравился подход Lombok, поэтому я манипулировал исходными наборами в build.gradle следующим образом:

sourceSets {
    main { // all but module-info
        java {
            exclude 'module-info.java'
        }
    }
    mainModuleInfo { // module-info only
        java {
            srcDirs = ['src/main/java']
            outputDir = file("$buildDir/classes/java/main")
            include 'module-info.java'
        }
    }
}

Затем я настроил задачузависимость и добавил правильные --release опции для обеих задач компиляции:

classes.dependsOn mainModuleInfoClasses

compileJava.options.compilerArgs.addAll(['--release', '8'])
compileMainModuleInfoJava.options.compilerArgs.addAll(['--release', '9'])

Если я сейчас скомпилирую, я получаю:

Ошибка: пакет lombok не существует

Так что я до сих пор не знаю как инструктировать org.javamodularity.moduleplugin:

  • не использовать --module-path для main
  • установите правильный --module-path для mainModuleInfo

1 Ответ

0 голосов
/ 13 марта 2019

РЕДАКТИРОВАТЬ: Эта функция теперь поддерживается Плагин Gradle Modules начиная с версии 1.5.0 .

Вот рабочая build.gradleФрагмент:

plugins {
    id 'java'
    id 'org.javamodularity.moduleplugin' version '1.5.0'
}

repositories {
    mavenCentral()
}

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.6'
}

modularity.mixedJavaRelease 8

ОК, мне удалось получить эту работу:

  1. отключение org.javamodularity.moduleplugin
  2. удаление пользовательского набора источников (этоне нужно)
  3. добавление пользовательской задачи compileModuleInfoJava и установка ее --module-path в classpath задачи compileJava (вдохновлено этим руководством Gradle )

Вот полный исходный код build.gradle:

plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.6'
}

compileJava {
    exclude 'module-info.java'

    options.compilerArgs = ['--release', '8']
}

task compileModuleInfoJava(type: JavaCompile) {
    classpath = files() // empty
    source = 'src/main/java/module-info.java'
    destinationDir = compileJava.destinationDir // same dir to see classes compiled by compileJava

    doFirst {
        options.compilerArgs = [
                '--release', '9',
                '--module-path', compileJava.classpath.asPath,
        ]
    }
}

compileModuleInfoJava.dependsOn compileJava
classes.dependsOn compileModuleInfoJava

Примечания:

  • он компилируется ?
  • Я проверил, что module-info.classв формате JDK 9 (8-й байт 0x35 v.53 ), в то время как другие классы представлены в формате JDK 8 (8-й байт 0x34 v.52 )?
  • однако отключение org.javamodularity.moduleplugin неудовлетворительно, поскольку это означает, что тесты больше не будут выполняться по пути к модулю и т. Д. ?
...