Gradle 6.7 で追加された Toolchain サポート

f:id:Naotsugu:20200726205049p:plain


JVM プロジェクトのツールチェーンサポート

Gradle 6.7 にて New JVM ecosystem features として JVM プロジェクトのツールチェーンサポートが追加されました。

通常は Gradle 自体の実行とビルド処理には同じバージョンの JVM が使われます。Gradle 6.7 以前では異なるバージョンを設定するにはいくつかの手順が必要でした。

Gradle 6.7 では、ツールチェーンという概念が導入されました。 ツールチェーンはインストールされた javac コンパイラ、java コマンドなどのセットであり、ビルド処理で利用されます。

ツールチェーンは以下のようにして使います。

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(14)
    }
}

Gradle Kotlin DSL の場合は以下となります。

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(8))
    }
}

toolchain の指定により Gradle は指定されたツールチェーンから javac、java、javadoc コマンドを使用するようになります。

この時、ローカルにインストールされている Java のバージョンを検出して、指定されたバージョンのJava ツールが選択されます。 ローカルに対象のバージョンが存在しない場合は、AdoptOpenJDK から JDK を自動的にダウンロードして利用します。

ローカルの Java の検出は、オペレーティングシステム上の共通のインストール場所や、asdf-vm、jabba、SDKMAN などの一般的なパッケージマネージャをサポートしています。


ツールチェーン の利用

複数のサブプロジェクト間で共通の設定を行うには convention プラグインを追加します。

buildSrc/src/main/groovy/myproject.java-conventions.gradle

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(14)
    }
}

このようにツールチェーンを指定すると、ビルド時に以下の処理が行われます。

  • すべてのコンパイル、テスト、javadocタスクを定義されたツールチェーンを使用するように設定
  • ローカルにインストールされた JVM を検出
  • ビルドの要件にマッチするJRE/JDKを選択します
  • マッチする JVM が見つからない場合、AdoptOpenJDK から対象の JDK を自動的にダウンロード
    • ダウンロードした JDK は Gradle ユーザーホームディレクトリにインストールされる

convention プラグインについては以下を参照してください。


ツールチェーンのカスタマイズ

それぞれのタスクで異なるバージョンを使用する場合は以下のように設定できます。

tasks.withType(JavaCompile).configureEach {
    javaCompiler = javaToolchains.compilerFor {
        languageVersion = JavaLanguageVersion.of(8)
    }
}
test {
    javaLauncher = javaToolchains.launcherFor {
        languageVersion = JavaLanguageVersion.of(14)
    }
}

この例ではコンパイルとテストに JDK8、ユニット・テストにJDK 14 を使用しています。

ツールチェーンのツールプロバイダは javaToolchains エクステンションから取得できます。

  • JavaCompileタスクで使用されるツール : JavaCompiler
  • JavaExec や Test タスクで使用されるツール : JavaLauncher。
  • Javadocタスクが使用するツール : JavadocTool


ツールチェーンにはメタデータがあり、それらの情報を利用することもできます。

def compiler = javaToolchains.compilerFor {
    languageVersion = JavaLanguageVersion.of(11)
}

tasks.withType(KotlinJvmCompile).configureEach {
    kotlinOptions.jdkHome = compiler.get().metadata.installationPath.asFile.absolutePath
}


ツールチェーンの自動検出を無効化するには、起動オプションとして -Porg.gradle.java.installations.auto-detect=false を指定するか、gradle.propertiesorg.gradle.java.installations.auto-detect=false を指定します。

自動ダウンロードを無効化するには、起動オプションとして -Porg.gradle.java.installations.auto-download=false を指定するか、gradle.propertiesorg.gradle.java.installations.auto-download=false を指定します。


ツールチェーンの場所を個別に指定する場合は環境変数に定義し、その環境変数を Gradle に伝えることができます。

org.gradle.java.installations.fromEnv=JDK8,JRE14

または、個別にインストールパスをカンマ区切りで指定することができます。

org.gradle.java.installations.paths=/custom/path/jdk1.8,/shared/jre11


まとめ

Gradle 6.7 で導入された ツールチェーン サポートについて見てきました。 JDKのバージョンアップサイクルが早くなったこともあり、自動で JDK をダウンロードできるのはとても便利です。

現在のバージョンでは、このツールチェーンサポートは、Javaプラグインとそれらが定義するタスクでのみ利用可能なため、Groovy と Scala プラグインに関しては利用できないので注意してください。