kagamihogeの日記

kagamihogeの日記です。

gradleの複数プロジェクトで共通設定をpluginでまとめる

単一プロジェクト内のsubproject間の共通設定をpluginにまとめる方法はgradle initでプロジェクト作ればそこに例があるし、自分のblogだと gradle initの複数subproject構成を見る(6.8.3)にまとめている。

ここでは複数プロジェクト間の共通設定をpluginにまとめるやり方について。基本的には、大規模プロジェクト構成例の公式リファレンス https://docs.gradle.org/current/userguide/structuring_software_products.html のサンプルコード https://docs.gradle.org/current/samples/sample_structuring_software_projects.html から対象部分を抜粋した形となる。

やり方の概要としては、まずnaming conventionを行うgroovy-gradle-pluginで記述しpluginディレクトリに配置、includeBuildでそのディレクトリをincludeし、plugins { id '...'}でそのpluginを使用する、といったところ。

環境

  • java 11
  • gradle 7.2

ソースコード

ファイルのレイアウトはおおむね以下となる。

  • build-logic - pluginディレクトリとなる、共通設定を記述するpluginファイルの配置箇所。下の例だとcom.example.commons.gradleがpluginの実体。
  • project1 - プロジェクトその1。下の例だとsubprojectにappを持っている。
  • project2 - プロジェクトその2
build-logic
 settings.gradle
 commons
  build.gradle
  src/main/groovy
   com.example.commons.gradle
project1
 settings.xml
 app
   build.gradle
project2
 settings.xml
 ...

build-logic

このディレクトリの名前自体は何でもよいが、gradleのサンプルプロジェクトの名前をそのまま使用している。

settings.gradle

dependencyResolutionManagement {
    repositories {
        gradlePluginPortal()
    }
}

rootProject.name = 'build-logic'

include('commons')

一般的なプロジェクト例同様にinclude('commons')commonsディレクトリをincludeする。

gradlePluginPortal()のところは今回くらいシンプルだと要らないけど大抵は必要になると思う。

commons/build.gradle

plugins {
    id('groovy-gradle-plugin')
}

pluginはnaming conventionを使用して記述するので、そのためのgroovy-gradle-pluginを記述する。

src/main/groovy/com.example.commons.gradle

groovy-gradle-pluginの形式に従いsrc/main/groovyディレクトリにplugin-name.gradleを記述する。後述する通りplugin-nameというidで参照可能になる。

println '### com.example.commons.gradle'

中身はデバッグ用のprintfだけ。

project1

settings.xml

pluginManagement {
    includeBuild('../build-logic')
}

rootProject.name = 'project1'

include('app')

最初のincludeBuild('../build-logic')でpluginディレクトリをincludeする。includeBuildディレクトリというかプロジェクトまるごと取り込むのがポイント。

app/build.gradle

最後にアプリケーションのプロジェクトで対象のpluginを使用する。

plugins {
    id('com.example.commons')
}

com.example.commons.gradleという名前なのでid('com.example.commons')で使用できる。

実行時の様子

>gradlew build

> Configure project :app
### com.example.commons.gradle

plugin内のprintが実行されてるのが分かる。

バリエーション

その他使いそうなplugin定義方法のメモ。

同一ディレクトリ内のplugin使用

例えば、以下のときにcom.example.commons.gradleからsample.gradleを参照したい場合。

commons/src/main/groovy
 com.example.commons.gradle
 sample.gradle

単純にpluginの名前で参照できる。

plugins {
  id 'sample'
}

println '### com.example.commons.gradle'

別のディレクトリを参照する

例えば、以下のようにcommonsfoobarがあり、前者から後者を参照したい場合。

build-logic
 commons
 foobar

まずbuild-logic/settings.xmlfoobarを追加する。

include('foobar')
include('commons')

foobarの中身はほとんどcommonsと同じなので省略。次にbuild-logic/foobar/src/main/groovy/foo.bar.gradleという名前のpluginファイルを作成した、とする。

commons/build.gradlefoobarを取り込む。

plugins {
    id('groovy-gradle-plugin')
}

dependencies {
    implementation(project(':foobar'))
}

gradle公式のサンプル見るとspring-bomはimplementation(platform(...))を使ってる。このへん公式サンプル読み込めてないないんだが取り込む対象の種類によって使い分ける必要があるのだと思う。

最後にcom.example.commons.gradlefoo.bar pluginを使用する。

plugins {
  id 'sample'
  id 'foo.bar'
}

println '### com.example.commons.gradle'

ハマりどころ

apply pluginは使えない

下記のようにnot foundになる。もしかしたら何か方法があるかもしれないがそこまで調べてない。

* What went wrong:
A problem occurred evaluating project ':app'.
> Plugin with id 'com.example.commons' not found.