282 Views
December 23, 25
スライド概要
エンジニア達の「完全に理解した」Talk #72 での発表資料です
Gradle Build Scriptの第0歩: 仕組みから書き方を理解する どもも (@Udomomo) 2025-12-23 エンジニア達の「完全に理解した」Talk #72
プロフィール • どもも (@Udomomo) • バックエンドエンジニア • 普段使いの言語はKotlin • アカウントIDの可読性が低いのが悩み
今日のテーマ「Gradle」
こんなことありませんか? • ビルドの設定ファイルで何をやっているかわからない • 正直言って他の設定ファイルからコピペしてる • 書き方を調べても、何がどうなっているかのイメージが全然わかない… → 個々の文法以前に、Build Scriptまわりのエコシステムについてざっくりとイ メージできることが重要
今日の目的 • Gradle Build Scriptの設定記述~実行までの仕組みについて、脳内に大まかな イメージができること ※ Gradleの基礎知識やコマンドの実行方法には立ち入りません ※ 普段使いがKotlinなのでKotlinを前提にしています
Gradleで最初に悩んだこと
plugins {
kotlin("jvm") version "2.2.21"
kotlin("plugin.spring") version "2.2.21"
id("org.springframework.boot") version "4.0.1"
id("io.spring.dependency-management") version "1.1.7"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
description = "Demo project for Spring Boot"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.jetbrains.kotlin:kotlin-reflect")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
kotlin {
compilerOptions {
freeCompilerArgs.addAll("-Xjsr305=strict", "-Xannotation-default-target=param-property")
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
Gradleで最初に悩んだこと この文法 なに?
GradleのDSLとAPI
Gradle DSL • DSLとは? • Domain Speci c Language • 特定のドメインにおける問題解決のために作成されたプログラミング言語 fi • 汎用的なプログラミング言語の機能を使って、DSLを作ることもできる
Gradle DSL • Gradle DSLとは? • Gradleを操作するためのDSLで、Groovy DSLとKotlin DSLが存在する • build.gradle.ktsの内容はValidなKotlinコード • GradleがDSL向けに用意している型のリファレンス https://docs.gradle.org/current/dsl/index.html • Kotlin公式によるDSLの書き方ガイド https://kotlinlang.org/docs/type-safe-builders.html
Gradle API • Gradleのコアとして用意されているAPI • Gradleを操作するために必要なメソッドやクラスなど • Gradle APIのリファレンス https://docs.gradle.org/current/javadoc/index.html
Gradle DSLとGradle APIの関係 Gradle Core Gradle API 利用 DSL 記述 Build Script
Gradle DSLだけ覚えればいいのか? • Gradle DSLがAPIを隠蔽することで、開発者は直感的にBuild Scriptを書く ことができる • とはいえ、DSLの文法の知識しかないと、複雑なTaskを書くときに詰まる • Gradle APIの側で、Taskの設定は (だいたい) どのように行われているか?の イメージを持つことが重要
Gradle Taskの設定の仕組み
Gradle APIのContainer Type • Gradle APIには “Container Type” と呼ばれる型がいくつかある • リソースの取得・作成・更新などは、対応するContainerのAPIを通じて行う
例: TaskContainer tasks.withType<Test> { useJUnitPlatform() } • TaskContainerを通じて、そのprojectのTaskのうちTest型を継承する ものを取得 • テスト実行時にJUnit5を使えるように設定を追加
Projectも型である • Projectはbuild.gradle.ktsと1対1 の関係で作られる • ProjectのAPIを使うことで、 Project全体の設定の取得・操作が 可能 fi • tasksやdependenciesなどは、 projectに生えているAPIである Project tasks dependencies con gurations …
Pluginが行っていること ktlint { verbose.set(true) filter { exclude("**/build/**") } } • PluginはProjectのAPIを拡張している • 例: KtlintのPluginは、ProjectにktlintというAPIを追加し、独自のTaskやプ ロパティを設定可能にしている
TaskとTaskの関係性
Gradleの実行ステップ ( https://docs.gradle.org/current/userguide/build̲lifecycle.html )
Task Graph • GradleはBuild Scriptの内容を確認し、タスクの依存関係のグラフを作る • Task単体の設定だけでなく、Task同士の関係性の設定もBuild Scriptの役割 のひとつ
例: Taskに依存関係を追加する val ktlintCheck = tasks.named("ktlintCheck") tasks.named("check") { dependsOn(ktlintCheck) } • Ktlint pluginを導入すると、ktlintCheckというTaskが利用可能になる • このtaskを取得し、check Taskから依存させる
Task Graphを作るうえでの工夫 • tasks.namedで取得されるのはtaskの実体ではなく、taskを参照する TaskProviderである • checkタスク以外を実行するときは、ktlintCheckやcheckをTask Objectと して作らずに済むので、パフォーマンスが向上する • このような機能のあるAPIは Con guration Avoidance API と呼ばれ、利用 fi fi が推奨されている ( https://docs.gradle.org/current/userguide/ task̲con guration̲avoidance.html )
他にも様々な機能がある • Task GraphをキャッシュするCon guration Cache • ビルドの途中成果物をキャッシュして使い回すBuild Cache など… • ビルドはコードの追加・変更のたびに頻繁に行うもの。Gradleは正確なTask fi Graphの構築とパフォーマンス向上との両立を目指している。
今日のまとめ • Gradleの設定は、DSLで隠蔽されたGradle APIを叩き、Gradle Coreをどう 操作するかを定義したものである • GradleはTask Graphの構築と最適化を担っており、そのために多くの機能が 存在する • 設定の際は、Task間の依存関係やパフォーマンスの観点を意識するとよい