0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

カスタムGradleプラグインのartifactIdを明示的に指定する方法、Gradleマルチプロジェクトで

Last updated at Posted at 2024-03-27

解決したい問題

カスタムGradleプラグインの作り方を学ぼうとしました。ひとつ新しくディレクトリを作り、その中で gradle init コマンドを実行してGradleプロジェクトを初期化しました。Gradle v8.5を使いました。

$ cd ~/tmp
$ mkdir 
$ cd ArtifactId_of_custom_Gradle_plugin_in_multiproject_how_to_specify
$ gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 4

Select implementation language:
  1: Groovy
  2: Java
  3: Kotlin
Enter selection (default: Java) [1..3] 1

Select build script DSL:
  1: Kotlin
  2: Groovy
Enter selection (default: Groovy) [1..2] 2

このあと、入力を求めるプロンプトが何回か続きました。

Project name (default: ArtifactId_of_custom_Gradle_plugin_in_multiproject_how_to 

これに対してはENTERするのみ。

Source package (default: artifactid_of_custom_gradle_plugin_in_multiproject_how_

これに対しては com.kazurayam.gradleplugins を入力した。

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) 

これに対してはENTERするのみ。

> Task :init
For more information, please refer to https://docs.gradle.org/8.5/userguide/custom_plugins.html in the Gradle documentation.

BUILD SUCCESSFUL in 6m 42s
2 actionable tasks: 2 executed

無事終了しました。Gradleが下記のようなフォルダ・ツリーを生成しました。

01

このフォルダー・ツリーを使うことにしました。ArtifactId_of_custom_Gradle_plugin_in_multiproject_how_to_specifyという長い名前のフォルダのことを以下ではrootと呼ぶことにします。ここで注目してほしいポイントがひとつあります。gradle initコマンドはここでGradleの言葉遣いでいうところの「マルチプロジェクト」を生成しました。pluginという名前のフォルダが生成されました。

わたしはpluginフォルダの中にGroovyコードを配置してカスタムgradleプラグインを実装しました。カスタムgradleプラグインの作り方を解説する記事をネット検索しました。Tom Gregoryの下記の記事を写経することにしました。

Tomさんによるサンプル・コードをコピペしました。Extension class, Task class, Plugin class, Test for the pluginとか。瑣末な箇所(パッケージ名とか)を改めましたが、基本的にTomさんのコードそのままです。コンパイルが通り、テストもパスしました。

次に .m2/repository つまりMavenローカルレポジトリにJARをパブリッシュしようとしました。plugins/build.gradle ファイルの中身は次の通り。

plugins {
    id 'java-gradle-plugin'
    id 'groovy'
    id 'maven-publish'
}

group = 'com.kazurayam'
version = '0.1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    // Use the awesome Spock testing and specification framework
    testImplementation libs.spock.core
    // Junit dependencies
    testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

test {
    useJUnitPlatform()
    testLogging {
        events "started", "passed", "skipped", "failed"
    }
}

gradlePlugin {
    plugins {
        fileDiff {
            id = 'com.kazurayam.file-diff'
            implementationClass = 'com.kazurayam.gradleplugins.filediff.FileDiffPlugin'
        }
    }
}

下記のコマンドを実行しました。

~/tmp/ArtifactId_of_custom_Gradle_plugin_in_multiproject_how_to_specify (master)
$ cd plugin
~/tmp/ArtifactId_of_custom_Gradle_plugin_in_multiproject_how_to_specify/plugin (master)
$ gradle publishToMavenLocal

このコマンドが成功しました。~/.m2ディレクトリの様子を見ました。

02

問題があります! gradle publishToMavenLocalコマンドは下記2つのディレクトリを生成しました。

  • .m2/repository/com/kazurayam/file-diff
  • .m2/repository/com/kazurayam/plugin

一番目のディレクトリは問題ない。二番目のディレクトリの名前 plugin が気に入りません。わたしはこれを file-diff-plugin ないしは file-diff-impl というような名前にしたい。でもどうすればいいのでしょうか?

ここでpluginという値が設定された概念のことをGradleのMaven Publishプラグインは「artifactId」という集合名詞で言い表しています。

わたしの疑問

gradle initコマンドによって自動生成されたフォルダ構造とbuild.gradleのままだとgradleプラグインのartifactIdが plugin というよろしくない名前になってしまう。それを明示的に指定したい。どうすればいいのか?

解決方法

plugin/build.gradleファイルを修正します。下記の行を追加せよ。

publishing {
    publications {
        maven(MavenPublication) {
            artifactId = 'file-diff-plugin'
        }
    }
}

この修正をした後で gradle publishToMavenLocal を再実行すると、下記のようになりました。

03

成功しました。

説明

publishToMavenLocalタスクがartifactIdを決定します。このタスクを提供するのは maven-publish プラグインの働きです。maven-publishプラグインのドキュメント にこう書いてあります。

Identity values in the generated POM

The attributes of the generated POM file will contain identity values derived from the following project properties:

  • groupId - Project.getGroup()
  • artifactId - Project.getName()
  • version - Project.getVersion()

これによると、artifactIdは Project.getName()に基づいている。で、Project.getName()の値はプロジェクトのディレクトリ名に基づいている。artifactIdが plugin と設定されたのは、サブプロジェクトのディレクトリ名が plugin であったから。

ドキュメントにはこうも書いてあります。

Overriding the default identity values is easy: simply specify the groupId, artifactId or version attributes when configuring the MavenPublication.

だからわたしは plugin/build.gradle ファイルを上記のように修正しました。

結論

カスタムGradleプラグインの作り方を解決する記事はネット上にたくさんありますが、わたしの見るところ、それら記事はみなシングルなgradleプロジェクトを素材としていて、マルチ・プロジェクトの事例は見当たらなかった。ところが gradle init でプロジェクト・ツリーを初期構築するとマルチ・プロジェクトになる。するとjarファイルの名前が plugin-0.1.0.jar という妙な名前になってしまう。これを file-diff-plugin-0.1.0.jarというようにわたし好みのartifactIdに改めたい。どうすればいいのか?

その答えをようやく見つけました。Maven publishプラグインのマニュアルを読んで、その通りに設定すればいいだけだった。気づいてしまえば簡単なことだった。しかしこれに気づくまでにえらく時間(たぶん三年)がかかった。ああ!

参考

GitHubにコードをホストしています。

補足: "gradle jar"コマンドが生成するjarファイルのartifactIdを明示的に指定する方法

メモを添えておきます。わたしは次のコマンドを実行した。

$ cd <root dir>/plugin
$ gradle clean jar

すると plugin/build/libs ディレクトリの下にJARファイルが出力された。JARのファイル名は plugin-x.x.x.jar という形だった。

11

このファイル名はいただけない。JARのartifactIdを明示的に指定して file-diff-plugin-x.x.x.jar としたい。どうすればできるか?

答え: plugin/build.gradle ファイルを修正すればよい。Gradleを実行したとき projectオブジェクトが artifactsBaseNameプロパティを持つ。そのデフォルト値はプロジェクトのディレクトリ名すなわち plugin であるが、任意の文字列で置き換えることができる。つまり下記のようにすればいい。

12

JarタスクのドキュメントGradle Jar taskを参照のこと。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?