https://docs.gradle.org/5.2/userguide/plugins.html#sec:plugin_management
2.1ぐらいからincubatingな New Gradle Plugin APIのPluginManagementのResolutionStrategyをそろそろ理解する。
Plugin作成
とりあえずPluginを実装します。はい。実装しました。
ではPlugin配布の為のビルドスクリプトを書いていきます。 java-gradle-plugin
のplugin applyをお忘れなく。まずはGradlePluginの設定です。
Kotlin DSLですが、だいたいGroovyDSLなので良いでしょう。
gradlePlugin {
plugins {
register("greatPlugin") {
id = "com.github.uzzu.gradle.great"
implementationClass = "com.github.uzzu.gradle.GreatPlugin"
}
register("superPlugin") {
id = "super-uzzu"
implementationClass = "com.github.uzzu.gradle.SuperPlugin"
}
}
デプロイスクリプトを書きます。GradlePluginPortalやその他maven repositoryに配布する場合はその記述が必要ですが今回は省略します。 maven-publish
のplugin applyをお忘れなく。
group = "com.github.uzzu.gradle.awesome"
version = "1.0"
publishing {
repositories {
mavenLocal()
}
(publications) {
register("pluginMaven", MavenPublication::class) {
artifactId = "awesome-plugin"
}
}
}
やりました。では ./gradlew publish
します。はい。しました。
Plugin読込(解決)
ではデプロイしたPluginを読み込んでみます。
settings.gradle(.kts)にPluginManagementの記述をしていきます。 enableFeaturePreview
を使用している場合はその下に書きます。
pluginManagement {
repositories {
mavenLocal()
}
resolutionStrategy {
}
}
書きました。では実際にprojectから読み込んでみます。
plugins {
id("com.github.uzzu.gradle.great") version "1.0"
id("super-uzzu") version "1.0"
}
読み込めました。
以下の形でも大丈夫です。
// settings.gradle.kts
pluginManagement {
repositories {
mavenLocal()
}
resolutionStrategy {
eachPlugin {
when (requested.id.id) {
"com.github.uzzu.gradle.great",
"super-uzzu" -> {
useVersion("1.0")
}
}
}
}
}
// build.gradle.kts
plugins {
id("com.github.uzzu.gradle.great")
id("super-uzzu")
}
従来のように buildscript
の classpath
を記述せずともPluginを読み込めました。そしてデプロイしたはずの com.github.uzzu.gradle.awesome-plugin
の記述はありません。どういう理屈なのでしょうか。
色々覗いてみる
まずはmaven repositoryを覗きます。
やたら名前が長い感じのrepositoryになってます。POMも見てみます。
GreatPlugin
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.uzzu.gradle.great</groupId>
<artifactId>com.github.uzzu.gradle.great.gradle.plugin</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>com.github.uzzu.gradle</groupId>
<artifactId>awesome-plugin</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
SuperPlugin
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>super-uzzu</groupId>
<artifactId>super-uzzu.gradle.plugin</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>com.github.uzzu.gradle</groupId>
<artifactId>awesome-plugin</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
AwesomePlugin
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.uzzu.gradle</groupId>
<artifactId>awesome-plugin</artifactId>
<version>1.0</version>
<dependencies>
<!-- (omitted) -->
</dependencies>
</project>
はーなるほど、POMのみのartifactを作って、そこでPlugin本体である所のAwesomeの依存を解決して読み込んでいる。AwesomePluginのjarの中を見るとこんな感じ
├── META-INF
│ ├── MANIFEST.MF
│ └── gradle-plugins
│ ├── com.github.uzzu.gradle.great.properties
│ └── super-uzzu.properties
└── com
└── github
└── uzzu
└── gradle
├── GreatPlugin.class
└── SuperPlugin.class
$ cat META-INF/gradle-plugins/com.github.uzzu.gradle.great.properties
implementation-class=com.github.uzzu.gradle.GreatPlugin
$ cat META-INF/gradle-plugins/super-uzzu.properties
implementation-class=com.github.uzzu.gradle.SuperPlugin
なるほどですね。
実際にPOMを作っている部分のソースを見てみます。
おおなるほど、確かに POMに書かれている通りgroupIdとartifactIdを生成している。
読込側も見てみます。
余談
Android Gradle PluginやKotlin Gradle PluginはNew Gradle Plugin APIには対応してなさそう。 useModule
で単体では読み込めても、 Kotlin MPP + multimoduleをやっていると同2つのpluginの適用ががうまくいかない。根気が尽きた。Kotlinにおいては中の人的にもincubating featureだから使ってない旨のissue commentをどっかでみたけど忘れた。忘れてください。Gradle難しい。最悪、今まで通りbuildscript使えばいいのでまあいいでしょう。
結論
個人的には「これいるのかな…」という感じで、ずっとincubating なのも頷けます。pluginManagementにおけるresolutionStrategyはいまいち目的が見えない。誰か教えてください。ライブラリ管理におけるresolutionStrategyはexclude地獄を排除できるのでぼちぼち便利なんですけどね。うーん。