ひとつのbuild.gradle.ktsファイルでマルチプロジェクトを構成したい
概要
複数ファイルで構成するサンプルはよく見かけるけど、1つのファイルで構成するサンプルを見かけなかったので作ってみました。
これが正解かはわかりません。
環境
------------------------------------------------------------ Gradle 6.6.1 ------------------------------------------------------------ Build time: 2020-08-25 16:29:12 UTC Revision: f2d1fb54a951d8b11d25748e4711bec8d128d7e3 Kotlin: 1.3.72 Groovy: 2.5.12 Ant: Apache Ant(TM) version 1.10.8 compiled on May 10 2020 JVM: 1.8.0_242 (AdoptOpenJDK 25.242-b08) OS: Mac OS X 10.15.6 x86_64
TL;DR
- 全体の設定は
allProjects
に - サブプロジェクト全体の設定は
subprojects
に - 各プロジェクト固有の設定は
project("MODULE_NAME")
に
どうすればいいか
とりあえず親プロジェクトを用意する
ゼロから用意するのは面倒なので、SpringInitializerで生成しちゃいます。
今回は親プロジェクトはナシで、サブプロジェクトになるものを2つ用意しました。
スタートはこんな感じです。ここから少しずつ分解していきます。
rootProject.name = "one-file-gradle-multi-project" include("sub-project-1") include("sub-project-2")
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.springframework.boot") version "2.3.3.RELEASE" id("io.spring.dependency-management") version "1.0.10.RELEASE" kotlin("jvm") version "1.3.72" kotlin("plugin.spring") version "1.3.72" } group = "com.example.footaku.scratches" version = "0.0.1-SNAPSHOT" java.sourceCompatibility = JavaVersion.VERSION_1_8 repositories { mavenCentral() } dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3") runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") { exclude(group = "org.junit.vintage", module = "junit-vintage-engine") } } tasks.withType<Test> { useJUnitPlatform() } tasks.withType<KotlinCompile> { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") jvmTarget = "1.8" } }
全体に適用したいものを抜き出す
repositoriesは全体に関係するのでallProjects
に移動します。
allprojects { repositories { mavenCentral() } }
サブプロジェクト全体に適用するものを分ける
すべてのサブプロジェクトで使うdependencies
とtasks
はsubprojects
へ移動します。
ついでにplugin
やsourceSets
の設定も足します。
subprojects { apply(plugin = "java") apply(plugin = "kotlin") apply(plugin = "kotlin-spring") apply(plugin = "org.springframework.boot") apply(plugin = "io.spring.dependency-management") group = "com.example.footaku.scratches" version = "0.0.1-SNAPSHOT" java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 sourceSets { main { java.srcDir("src/main/kotlin") resources.srcDir("src/main/resources") } test { java.srcDir("src/test/kotlin") resources.srcDir("src/test/resources") } } dependencies{...} tasks.withType<...> {...} }
プロジェクト固有の設定を分ける
さらに、一部のプロジェクトだけに適用するdependencies
などはproject
でプロジェクト名を指定します。
今回はDBを使う設定をsub-project-1
にだけ適用してみます。
この場合sub-project-1
はDataSourceの設定をapplication.yml(.properties)
に書かないとSpringBootは起動できなくなりますが、sub-project-2
ではその依存が入っていないので設定が無くても大丈夫です。
project(":sub-project-1") { dependencies { implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3") runtimeOnly("org.postgresql:postgresql") } }
完成
出来上がりがこちらです。
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.springframework.boot") version "2.3.3.RELEASE" id("io.spring.dependency-management") version "1.0.10.RELEASE" kotlin("jvm") version "1.3.72" kotlin("plugin.spring") version "1.3.72" } allprojects { repositories { mavenCentral() } } subprojects { apply(plugin = "java") apply(plugin = "kotlin") apply(plugin = "kotlin-spring") apply(plugin = "org.springframework.boot") apply(plugin = "io.spring.dependency-management") group = "com.example.footaku.scratches" version = "0.0.1-SNAPSHOT" java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 sourceSets { main { java.srcDir("src/main/kotlin") resources.srcDir("src/main/resources") } test { java.srcDir("src/test/kotlin") resources.srcDir("src/test/resources") } } dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") testImplementation("org.springframework.boot:spring-boot-starter-test") { exclude(group = "org.junit.vintage", module = "junit-vintage-engine") } } tasks.withType<Test> { useJUnitPlatform() } tasks.withType<KotlinCompile> { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") jvmTarget = "1.8" } } } project(":sub-project-1") { dependencies { implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3") runtimeOnly("org.postgresql:postgresql") } }
困っていること
バージョンの指定方法
Mavenではバージョンなどの値を<properties>
で設定すればどこでも使えるけれど、
Gradleにはそういう機能がないっぽいのが困りどころだなーと感じてます。
ワークアラウンド?としてext
を使う方法をよく見かけますが、こちらはplugin
の指定では使えず、
一方でbuildSrc
に定義すればどこでも使える様になる代わりに、定義する場所が分散してしまうのでうーん…
できれば「このファイルだけ見ればOK」という状態にしたいのですが、
自分なりに「これがベスト!」という方法が見つかってません。
あってるかがわからない
とりあえず動いてるけどこれが正しいのかがわかってません。