↔️

build.gradle.kts で gradle.properties (project properties) を参照する

2023/11/05に公開

はじめに

Groovy と kts で project property の参照方法が違っていたのでまとめました。

gradle.properties (project properties)

  • gradle.properties で定義されたプロパティは project properties と呼ばれ、gradle のビルドスクリプト内で参照できる
  • project properties は(gradle.properties 含め)以下の入力元から値が読み込まれる
    • gradle.properties
    • app/gradle.properties
    • $GRADLE_USER_HOME/gradle.properties
      • ( $GRADLE_USER_HOME のデフォルト値は $HOME/.gradle )
    • 環境変数 (例えば ORG_GRADLE_PROJECT_conf_foo=foo など)
    • gradle の -P 実行オプション
  • gradle.properties から値を渡すことで、設定値を一元管理したり、ソースコードと設定値を分離したり、環境ごとに設定値を切り替えたりできる

gradle.properties の例

gradle.properties では以下のような key-value 形式で値を設定する

gradle.properties

conf_foo=_foo_

Groovy での参照方法

build.gradle

// OK パターン
conf_foo                        # => _foo_
project.conf_foo                # => _foo_
project.properties["conf_foo"]  # => _foo_

// NG パターン
properties["conf_foo"]          # => null (なぜ?)

kts での参照方法

build.gradle.kts

// OK パターン
val conf_foo: String by project  # => conf_foo == "_foo_"
project.properties["conf_foo"]   # => _foo_
properties["conf_foo"]           # => _foo_

// NG パターン
conf_foo                         # => Unresolved reference
project.conf_foo                 # => Unresolved reference

書き方の違いについて

Groovy はメタプログラミングができるので conf_foo あるいは project.conf_foo を参照したときに project.properties["conf_foo"] に移譲するような実装になっている。 [1]

一方 Kotlin の val conf_foo: String by project では provideDelegate operator で PropertyDelegate 委譲オブジェクトを生成している。委譲オブジェクトを使う書き方があるということは Groovy と同じような conf_foo あるいは project.conf_foo での参照は kotlin の文法的にできなそうな雰囲気を感じる。

(おまけ) buildConfigField

buildConfigField を defaultConfig や BuildType あるいは BuildFlavor の中に記述し、プロジェクトプロパティを渡すことで BuildConfig.FOO のような形でアプリケーションコードから値を参照できるようになる。

defaultConfig {
    // ...    
    buildConfigField("String", "FOO", "\"${properties["conf_foo"]}\"")
}

ダブルクォーテーションを(エスケープして)値に含めているのは、そうしないと生成される BuildConfig.java 内で

public static final String FOO = foo;

のように出力されてエラーになるからであり、何か特別なシンタックスというわけではない。

また、上記の書き方では参照する project property が存在しない場合に

public static final String FOO = "null";

となってしまうので注意が必要。

参考

脚注
  1. metaClass の invokeMethod / methodMissing / propertyMissing あたりを使っているっぽいがちゃんとコードを追ってはいない ↩︎

Discussion