mike-neckのブログ

Java or Groovy or Swift or Golang

Gradleでプラグインを利用する方法

今更なタイトルですが…

incubatingなAPIで plugins DSLと呼ばれている方法です。plugins DSLはgradleのplugin repositoryにあるプラグインをid(とバージョン)だけで引っ張ってこれるようにする方法で、gradleの2.10くらいに登場しています。gradleにデフォルトに添付されているプラグインとgradle のplugin repository にあるプラグイン以外をこのDSLで指定する方法は登場した当初はなかったのですが、最近はsettings.gradleで頑張ればできるということ(そして、multipleなプロジェクトになるとすごく便利になるということ)を教えてもらったので、忘れてもいいようにメモしておきます。


実例としてJUnit5のプラグイン org.junit.platform.gradle.plugin を使います。

plugins ブロックの中に適用するプラグインのidを記入します。
plugins {
  id 'java'
  id 'org.junit.platform.gradle.plugin'
}

gradleの推奨するプラグインの名前はパッケージ名と同じような名前である id.namespace + id.name のようです。JUnit5のプラグインの場合ですと、 org.junit.platform.gradleid.namespacepluginid.name です。雑に言えば、最後のドットから右が id.name 左が id.namespace です。

org.junit.platform.gradle.plugin は gradle plugin repository にはないので、プラグインに使われるartifactの解決をしなければなりません。artifactを解決する方法として pluginManagement DSLがありそれを settings.gradle ファイルに記述します。
pluginManagement {

}

pluginManagement DSL内部では二つのブロックを書けます。一つは repositories ブロックであり、こちらは名前からわかるようにレポジトリーのURLを記述していきます。もう一つは resolutionStrategy であり、こちらにはプラグインの名前からどのartifactを使うかを記述します。

repositories ブロックには1つのブロックと1つのメソッドが提供されています。 maven ブロックではgradle plugin repository以外のレポジトリーのURLを記述します。 gradlePluginPotal メソッドを呼び出すと gradle plugin repository を使う宣言ができます。gradle plugin repository が不要な場合は gradlePluginPotal を呼び出さなければよいです。なお、maven centralやjcenterなどのおなじみのメソッドが生えていないので、それぞれのURLを書かなければなりません。JUnit5の例では、プラグインのjarはmaven centralにあるので、maven ブロックの中でmaven central のURLを指定します。
repositories {
  maven {
    url ('http://repo1.maven.org/maven2/')
  }
  gradlePluginPortal()
}
resolutionStrategy ブロックの中に eachPlugin ブロックを書いて、その中でプラグインのid(およびバージョン)とその扱いを決定します

requested というプロパティに指定したプラグインのidなどの識別する情報が含まれています。 requested の中には3つのプロパティ(idmoduleversion)が含まれていますが、多くの場合は id 以外は null です。 requested.id の中には次のプロパティが含まれています。

  • id: String - id の文字列表現
  • name: String - idname(最後のドットから右)
  • namespace: String - idnamespace(最後のドットから左)

これを if 文などでマッチングさせて、 eachPlugin ブロックに生えている useModule メソッドから artifact を指定します。artifact の指定方法は dependencies ブロックでの指定方法と同じです。JUnit5の例ではプラグインのidが org.junit.platform.gradle.plugin の場合に org.junit.platform:junit-platform-gradle-plugin:1.0.0 を使いたいので、そのようなマッチングと useModule の指定をします

resolutionStrategy {
  eachPlugin {
    if (requested.id.id == 'org.junit.platform.gradle.plugin') {
      useModule 'org.junit.platform:junit-platform-gradle-plugin:1.0.0'
    }
  }
}

以上の内容を合わせると次のようなスクリプトができます

pluginManagement {
  repositories {
    maven {
      url 'http://repo1.maven.org/maven2/'
    }
  }
  resolutionStrategy {
    eachPlugin {
      if (requested.id.id == 'org.junit.platform.gradle.plugin') {
        useModule 'org.junit.platform:junit-platform-gradle-plugin:1.0.0'
      }
    }
  }
}

なお、 pluginManagement ブロックは settings.gradle の中で一番最初に書かないといけないようです


ここまで試した感じですが、わりと面倒でしたが、 subprojects ブロックで新しいプラグインを読み込ませる方法などを考えると、致し方ないのかなぁという気持ちになります

あと、途中文字が太くなってたりしますが、個々のタイトルを考えるのが面倒で、すべてh5で記述していました…