Запуск Gradle с Java8 и компиляция Java13 с помощью fork

Я хочу запустить Gradle с системной JRE по умолчанию, в моем случае Java8.

И в сборке я хочу использовать конкретный JDK 13 с option.fork=true

compileJava {
    options.encoding = 'UTF-8'
    sourceCompatibility = 13
    targetCompatibility = 13
    options.compilerArgs << "-parameters"
    options.compilerArgs << "--release" << "13"
    options.compilerArgs << "--enable-preview"
    options.fork = true
    options.forkOptions.executable = "${projectDir}/tools/java/bin/javac.exe"
}

Когда я запускаю gradle с JRE 8, это не срабатывает с сообщением:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Could not target platform: 'Java SE 13' using tool chain: 'JDK 8 (1.8)'.

Но когда я устанавливаю JAVA_HOME на JDK 13, он работает успешно.

Есть ли способ выполнить этот запуск, если Gradle запущен с JRE8, но с использованием JDK13 для сборки?

Фрэнк

1 ответ

Решение

У Gradle есть проверка, что targetCompatibilityне выше, чем текущая версия Java. Честно говоря, я не знаю, почему он проверяет это, когда вы разветвляете компилятор на более новую версию (вместо этого он, вероятно, должен проверить эту версию). Но, может быть, на то есть веская причина.

Однако эти два свойства также полностью избыточны, когда вы используете --releaseфлаг. Это уже говорит компилятору, что он должен сгенерировать байтовый код для этой конкретной версии. Я даже не думаю, что компилятор поддерживает обаsource а также target аргументы вместе с --releaseв то же время. Итак, если вы удалите два свойстваsourceCompatibility а также targetCompatibility, он должен работать.

Кроме того, компилятор Java по умолчанию выполняет компиляцию для той же версии, поэтому вам также не нужен флаг --release.

Наконец, вы настраиваете только компиляцию "основного" исходного набора, и вы должны сделать то же самое и для "теста". И хотя это может быть не важно, вы также можете настроитьJavaDoc и любые задачи типа JavaExec использовать Java 13, или они по умолчанию будут использовать Java 8.

Итак, чтобы собрать все вместе, при нацеливании на более высокую версию Java, чем та, которая используется для Gradle, используйте что-то вроде этого:

// Paths for the various executables in the Java 'bin' directory
def javaHome = "${projectDir}/tools/java"
def javaCompilerPath = "$javaHome/bin/javac.exe"
def javaExecutablePath = "$javaHome/bin/java.exe"
def javaDocPath = "$javaHome/bin/javadoc.exe"

tasks.withType(AbstractCompile) { // Configures all compile tasks (both for main and test)
    // The sourceCompatibility and targetCompatibility properties have been removed
    options.encoding = 'UTF-8'
    options.compilerArgs.addAll(["-parameters", "--enable-preview"]) // The --release flag is optional when used for the same version
    options.fork = true
    options.forkOptions.executable = javaCompilerPath
    options.forkOptions.javaHome = file(javaHome)
}

tasks.withType(Javadoc) { // Configures JavaDoc to use the tool in Java 13
    executable = javaDocPath
}

tasks.withType(JavaExec) { // Only needed if you have any tasks of this type
    executable = javaExecutablePath
}

Когда выйдет Gradle 6.0, примерно через неделю, он будет поддерживать Java 13, поэтому вам ничего из этого не понадобится (пока вы не решите выполнить обновление до Java 14, прежде чем Gradle получит для него поддержку).

Другие вопросы по тегам