kagamihogeの日記

kagamihogeの日記です。

gradle initの複数subproject構成を見る(6.8.3)

動機

gradle勉強のためgradle initが生成する複数のsubproject構成を見る。基本的には https://docs.gradle.org/6.8.3/samples/sample_building_java_applications_multi_project.html と書いてる事は変わらない。

複数のsubprojectを作る場合はネットをぐぐるallprojectssubprojectsを使う方法が多く出てくる。対してgradle initプラグインによる設定共有でこれを実現している。なのでその辺を学ぶのが目的。

環境

6.8.3

ソースコード

まずsettings.gradleを見る。

rootProject.name = 'sample'
include('app', 'list', 'utilities')

各プロジェクト間の関係は後々それぞれのbuild.gradleで見るが以下になっている。

app -> utilities -> list

次にbuildSrc/src/main/groovyを見る。ここには、このプロジェクト内で使用するgradleのプラグインが配置されている。プラグインに共通設定を記述し、各プロジェクトからそのプラグインを使用する、という構成となっている。

まずは各プラグインファイルの中身を見る。

sample.java-common-conventions.gradle

plugins {
    id 'java'
}

repositories {
    jcenter()
}

dependencies {
    constraints {
        implementation 'org.apache.commons:commons-text:1.9'
    }
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}

tasks.named('test') {
    useJUnitPlatform()
}

sample.java-application-conventions.gradle

plugins {
    id 'sample.java-common-conventions'
    id 'application'
}

sample.java-library-conventions.gradle

plugins {
    id 'sample.java-common-conventions'
    id 'java-library'
}

プラグイン自体にも参照関係があり以下になっている。これも後に各プロジェクトのbuild.gradleで見るが、どのプロジェクトがどのプラグイン使うのかはファイル名からなんとなく予想がつく。

application -+
|-common
ilbrary-----+

commonは全プラグインの共通設定がある。id 'java'とかjcenter()とかどのプロジェクトでも使用するdependenciesとかそのあたり。

applicationはmainのあるプロジェクトを想定しているので、commonにプラスでid 'application'を含む。

libraryapplicationとは対照的にcommonプラスid 'java-library'を含む。

buildSrc/build.gradleには以下の記述がある。

plugins {
    id 'groovy-gradle-plugin'
}

repositories {
    gradlePluginPortal()
}

id 'groovy-gradle-plugin'はconvention pluginsというもので、名前の通り、上記で見たプラグインファイルを命名規則に従って自動的に登録してくれる。なのでbuild.gradleに適切なプラグイン名さえ書けばビルド時によしなにやってくれる。

というわけで各プロジェクトのbuild.gradleを見ていく。ポイントはplugins {...}のところ。

app

plugins {
    id 'sample.java-application-conventions'
}

dependencies {
    implementation 'org.apache.commons:commons-text'
    implementation project(':utilities')
}

application {
    // Define the main class for the application.
    mainClass = 'sample.app.App'
}

utilities

plugins {
    id 'sample.java-library-conventions'
}

dependencies {
    api project(':list')
}

list

plugins {
    id 'sample.java-library-conventions'
}

appはmainを置くアプリケーション本体なのでそれ用の設定が書かれたプラグインid 'sample.java-application-conventions'を使用する。

utilities, listは被使用側のプロジェクトなのでプラグインid 'sample.java-library-conventions'を使用する。

まとめ

といった感じで、gradle initが生成するプロジェクトは、そのプロジェクト用のプラグインを作成してそこに共通設定を記述、そして各プロジェクトからそれを参照、という作りになっている。

なお、更に複雑なプロジェクトの場合は https://docs.gradle.org/6.8.3/userguide/structuring_software_products.html という方法もあるらしい。

なんにしてもプロジェクトの複雑度に応じて方法を使い分けてね、という事なんだと思う。