概要: Gradleのビルドスクリプトで利用する変数定義や引数の渡し方、filetreeによるファイル操作、タスクの順序制御、並列実行の設定方法を解説します。さらにGradle 8から9への移行時に注意すべき非推奨機能とmanaged devicesへの対応についても紹介します。
Gradleの変数定義と引数の渡し方(hasPropertyの使い方)
変数定義の基本:Groovy DSLとKotlin DSLの違い
Gradleで変数を定義する方法は、使用するDSLによって異なる。Groovy DSLではdefキーワードやextブロックを使用するが、Kotlin DSLではvalまたはvarを使う。
- Groovy DSL:
def appVersion = "1.0.0"/ext { junitVersion = "5.10.2" } - Kotlin DSL:
val appVersion = "1.0.0"
Kotlin DSLでは静的型付けの型安全アクセサが利用でき、IDEによるコード補完や設定エラーのコンパイル時検出が可能になる。新規プロジェクトではKotlin DSLの採用が推奨されている。
要点:変数定義はKotlin DSLならval/var、Groovy DSLならdefまたはextを使用する。新規ビルドでは型安全なKotlin DSLが推奨される。(出典:JetBrains公式「Migrate Gradle build scripts to Kotlin DSL」)
hasPropertyを使ったプロパティの存在確認と条件分岐
hasProperty()は、プロジェクトプロパティがビルドスクリプトに定義されているかどうかを判定するメソッドである。-Pオプションやgradle.propertiesで渡されたプロパティの有無を確認できる。
使用例として、if (hasProperty("buildProfile")) { ... }のように条件分岐に利用する。プロパティが存在する場合のみ特定の設定やタスクを実行したい場合に有効だ。
Gradle 9.6.1では、設定フェーズで実際に読み込まれないorg.gradle.project.*システムプロパティやORG_GRADLE_PROJECT_*環境変数の値が変わってもConfiguration Cacheを再利用できるよう改善された。これはCIで多数のプロジェクトプロパティを渡す場合にキャッシュヒット率を向上させる。
要点:hasProperty()はプロパティの存在確認に使い、-Pオプションやgradle.propertiesで渡された値を条件分岐で活用できる。Gradle 9.6.1では未使用プロパティの変更がキャッシュに影響しなくなった。(出典:Gradle公式「9.6.1 Release Notes」)
コマンドラインからプロパティを渡す方法
ビルド時に外部から値を渡すには、-Pオプションを使用する。例えば./gradlew build -Penv=productionのように指定し、ビルドスクリプト内でproject.property("env")またはhasProperty("env")と組み合わせて参照する。
gradle.propertiesファイルにenv=developmentと記述する方法もある。プロジェクト固有のデフォルト値を定義する場合に適している。
システムプロパティを渡す場合は-Dオプションを使うが、これはGradleのプロジェクトプロパティとは区別される。ビルドロジックで使う値は-Pで渡すのが基本だ。
要点:外部からの値の受け渡しは-Pオプションが基本。gradle.propertiesにデフォルト値を定義し、CIやローカル環境で上書きするパターンが一般的。
Gradleでのfiletreeとfileによるファイル操作の基本
fileTreeを使ったファイル集合の指定
fileTree()は、特定のディレクトリ配下にあるファイル群を一括して指定するためのメソッドである。ディレクトリをルートとして、その配下の全ファイルを再帰的に取得できる。
基本的な使い方は以下のとおり。
fileTree("src/main/resources"):指定ディレクトリ配下の全ファイルfileTree(dir: "libs", include: "*.jar"):libs配下のJARファイルのみfileTree(dir: "src", exclude: "**/*.java"):Javaファイル以外を取得
include/excludeパターンにはAntスタイルのワイルドカードが使えるため、柔軟なファイルフィルタリングが可能だ。依存関係ではなくローカルファイルの集合を扱う場合に利用する。
要点:fileTreeはディレクトリ配下のファイルをまとめて指定する。include/excludeパターンで柔軟にフィルタリングでき、ローカルJARの依存関係追加などに使う。
fileを使った単一ファイルの参照
file()は単一のファイルまたはディレクトリを参照するためのメソッドである。相対パスで指定した場合、プロジェクトディレクトリからの相対パスとして解決される。
使用例は以下のとおり。
file("build/output.jar"):プロジェクト配下のファイルを参照file("$buildDir/libs/app.jar"):変数を組み合わせたパス指定
file()はjava.io.Fileオブジェクトを返すため、exists()やmkdirs()などのJava標準APIと組み合わせて使える。ファイルの存在確認やディレクトリ作成に便利だ。
要点:file()は単一ファイルの参照に使い、Java標準File APIと連携できる。相対パスはプロジェクトルートが基準となる。
file操作の実践的なユースケース
ビルドスクリプトでファイル操作が必要になる場面は多い。代表的な用途として、特定ディレクトリのJARファイルを依存関係に追加するケースがある。
例えば、implementation fileTree(dir: "libs", include: "*.jar")と記述すれば、libsフォルダ内の全JARを依存関係として扱える。また、生成物のパスを動的に指定する場合もfile()が活用できる。
タスク内でファイルをコピー・削除する場合は、copy・deleteタスクと組み合わせると効率的だ。ファイルの集合を柔軟に扱えることがGradleの強みである。
要点:fileTreeはローカルJARの一括依存関係追加に、file()は動的パス指定や存在確認に使う。タスクのcopy/deleteと組み合わせると強力。
Gradleのタスク順序制御(finalizedBy・mustRunAfter)の使い方
タスク順序制御の基本概念
Gradleではタスク間の実行順序を制御する仕組みが複数ある。代表的なものがdependsOn、finalizedBy、mustRunAfterの3つだ。
それぞれの役割は以下のとおり異なる。
| 制御方法 | 実行順序の意味 | 主な用途 |
|---|---|---|
| dependsOn | 指定タスクの後に実行 | 必須の前提処理 |
| finalizedBy | タスク終了後に必ず実行 | クリーンアップ・後処理 |
| mustRunAfter | 順序の制約のみ指定 | 明示的な依存関係を作らない |
dependsOnは依存関係を作るが、mustRunAfterは順序の制約を指定するだけで依存関係は作らない点が重要だ。
要点:dependsOnは依存関係を作り、finalizedByは終了後の実行を保証し、mustRunAfterは順序制約のみを指定する。用途に応じて使い分ける。
finalizedByの使い方と注意点
finalizedByは、指定したタスクが正常終了・失敗に関わらず、その後に必ず実行されるタスクを定義する仕組みである。テスト後のレポート生成や、ビルド後のクリーンアップ処理に適している。
使用例として、test.finalizedBy("testReport")のように記述する。testタスクが終了した後にtestReportタスクが必ず実行される。
注意点として、finalizedByで指定されたタスクは、元のタスクが失敗しても実行される。失敗時に後続タスクを実行したくない場合は、dependsOnを使うべきだ。
要点:finalizedByはタスク終了後に必ず実行される後処理向け。失敗時も実行される点に注意し、条件付き実行が必要ならdependsOnを検討する。
mustRunAfterによる順序制約の付与
mustRunAfterは、タスク間に明示的な依存関係を作らず、実行順序の制約のみを指定する方法である。両方のタスクが実行される場合にのみ順序が保証される。
使用例として、taskB.mustRunAfter("taskA")と記述する。両方のタスクがビルドに含まれる場合、taskBはtaskAの後に実行される。
この仕組みの利点は、不要な依存関係を作らないことである。タスク単独でも実行可能な独立性を維持しながら、同時実行時の順序だけを制御できる。複数のタスクが同じリソースにアクセスする場合などに有効だ。
要点:mustRunAfterは依存関係を作らず順序制約のみ付与する。両タスクが実行される場合のみ順序が保証され、タスクの独立性を保てる。
Gradleの並列実行とmaxParallelForksによるテスト高速化設定
Gradleの並列実行機能の概要
Gradleにはビルドを高速化するための並列実行機能がある。org.gradle.parallelプロパティを有効にすると、マルチプロジェクトビルドで独立したプロジェクトのタスクを並列実行できる。
gradle.propertiesにorg.gradle.parallel=trueと記述して有効化する。Configuration Cacheを有効化した場合、並列実行は暗黙的に有効になる。
並列実行の効果はプロジェクト構成に依存する。独立したモジュールが多いマルチプロジェクト構成では効果が高いが、直列依存の多いプロジェクトでは効果が限定的だ。
要点:org.gradle.parallel=trueでプロジェクト間のタスク並列実行が可能になる。効果はプロジェクト構成に依存し、独立モジュールが多いほど高い。
maxParallelForksによるテスト並列化の設定
maxParallelForksは、テストタスク内で同時に実行するテストプロセスの最大数を指定するプロパティである。テスト実行の高速化に直接的な効果がある。
設定方法は以下のとおり。
- ビルドスクリプトで
tasks.test { maxParallelForks = 4 }と記述 - コマンドラインで
./gradlew test --max-workers=4を指定
注意点として、テストクラスが独立している必要がある。共有リソースや順序依存のあるテストでは、並列化により失敗する可能性がある。まず少ない数から試し、テストの安定性を確認しながら増やすのが安全だ。
要点:maxParallelForksでテストプロセスの並列数を指定できる。テストが独立している場合に有効だが、共有リソースがある場合は注意が必要。
並列実行とキャッシュを組み合わせた高速化
並列実行とビルドキャッシュを組み合わせると、さらにビルド時間を短縮できる。Gradleには増分ビルド、ビルドキャッシュ、Configuration Cacheという3つの高速化機能がある。
Configuration Cacheは設定フェーズをキャッシュし、9.6.1では未使用プロパティの変更がキャッシュに影響しないよう改善された。CIで多数のプロパティを渡す場合のキャッシュヒット率が向上している。
リモートビルドキャッシュは、チーム全体やCIでタスク出力を共有できるが、ネットワーク環境によってはローカル実行より遅くなる場合がある点に注意が必要だ。
要点:並列実行とキャッシュ機能の組み合わせで高速化できる。リモートキャッシュはネットワーク次第で逆効果になる場合があるため、環境に応じて判断する。(出典:Kotlin公式ドキュメント「Gradle best practices」)
Gradle 8から9への移行手順と非推奨機能への対応
Gradle 9.0.0の主な破壊的変更
Gradle 9.0.0への移行には、複数の破壊的変更への対応が必須である。公式アップグレードガイドで明示されている主な変更点は以下のとおり。
| 変更項目 | 内容 | 対応方法 |
|---|---|---|
| jcenter()削除 | jcenterリポジトリが完全削除 | mavenCentral()へ移行 |
| Convention API削除 | org.gradle.api.plugins.Conventionが削除 | Extensions APIへ移行 |
| カスタムビルドファイル指定の削除 | -c/–settings-file、-b/–build-fileが使用不可 | GradleBuildタスクのbuildFileプロパティも削除 |
| 最小JVM要件の引き上げ | 実行環境がJava 17以上必須 | Java 17以上のJDKを用意 |
自作プラグインでConvention APIを使用している場合、9.0.0でビルドが失敗する。Extensions APIへの移行が必須となる。
要点:Gradle 9.0.0ではjcenter削除、Convention API削除、カスタムビルドファイル指定の削除、Java 17以上の必須化が主な破壊的変更。(出典:Gradle公式「Upgrading to Gradle 9.0.0」)
移行の具体的な手順とツール
Gradle 8から9への移行は、以下の手順で進めるのが安全である。
- 実行環境のJDKを17以上に更新する
- jcenter()をmavenCentral()に置き換える
- Convention API使用箇所をExtensions APIに移行する
- カスタムビルドファイル指定(-b/-c)の使用をやめる
- Wrapperのバージョンを9.x系に更新し、ビルドを検証する
移行を自動化するOpenRewriteのレシピ(org.openrewrite.gradle.MigrateToGradle9)も存在する。ただし、サードパーティツールである点に注意が必要だ。
Gradle 9系からはセマンティックバージョニングが採用され、--gradle-version=9と指定すれば最新の9.x.yに解決できる。
要点:移行はJDK更新→リポジトリ・API置換→Wrapper更新の順で進める。OpenRewriteの自動化レシピも利用可能だが、サードパーティ製である点に留意する。
Kotlinプラグインの互換性への対応
Gradle 8から9への移行では、Kotlinプラグインのバージョン要件にも注意が必要だ。Gradle 9以降はKotlin 2.2.xランタイムへ移行し、KGP(Kotlin Gradle Plugin)2.0.0以上が必要となる。Kotlinプロジェクトでは事前のバージョン確認が重要だ。
要点:Gradle 9移行ではKGP 2.0.0以上が必要となるため、Kotlinプロジェクトはプラグインの互換性確認が必須。
“`
まとめ
よくある質問
Q: Gradleで変数を定義する方法は?
A: Gradleではbuild.gradleやbuild.gradle.kts内で変数を定義できます。Groovy DSLでは”def 変数名 = 値”、Kotlin DSLでは”val 変数名 = 値”と記述します。また、プロジェクト全体で共有したい場合は、gradle.propertiesに記述するか、extブロック(Groovy)やextraプロパティ(Kotlin)を利用する方法もあります。
Q: Gradleのタスク実行順序を制御するには?
A: finalizedByは指定したタスクの実行後に必ず実行するタスクを指定でき、mustRunAfterは指定したタスクより後に実行することを強制します。これらを使うことで、テスト後にレポートを生成する、ビルド前にクリーンアップするなどの順序制御が可能です。
Q: Gradleで並列実行を有効にするには?
A: gradle.propertiesに”org.gradle.parallel=true”を設定することで、プロジェクト間のタスク並列実行が有効になります。また、テストタスクの並列実行にはmaxParallelForksを設定し、JVMプロセス数を指定します。これらの設定によりビルド時間の短縮が期待できます。
Q: Gradle 8から9に移行する際の注意点は?
A: Gradle 9.0.0ではjcenter()の完全削除、Convention APIの削除、-c/–settings-fileオプションの削除など複数の破壊的変更が含まれます。また、実行にはJVM 17以上が必要です。移行前に公式のアップグレードガイドで非推奨機能を確認し、プラグインの互換性をチェックすることが重要です。
Q: Gradle Managed Devicesとは何ですか?
A: Gradle Managed DevicesはAndroidテストで利用される機能で、エミュレータやデバイスの管理をGradleが自動的に行う仕組みです。ただし、この記事ではJava/JVMプロジェクトを対象としているため、Android固有のManaged Devicesの詳細な設定方法については扱っていません。
