Gradle:gradle.propertiesの値をどこでも利用できるようにする
gradle.propertiesは、他の設定ファイルとは異なり、マシンに一つだけなので、ここに様々な共通設定を書いておく、あるいは、より複雑な設定ファイルの場所を示しておくことができる。
さらに、公開ソフトウェアを開発中でも個人的なアカウントやパスワードは当然隠しておきたいのだが、これらをgradle.propertiesに記述しておくことによって、成果物から分離しておくことができる。
しかし、問題点がある。
プロパティとしてしか使えない
gradle.propertiesファイルはその名の通り、プロパティファイルとしてしか使用できない。
つまり、単純に名称/文字列値のペアしか格納ができない。文字列格納の際のクォーテーションも必要無い。
CENTRAL_REPOSITORY=http://10.8.92.1:8080/artifactory/libs-release
INHOUSE_REPOSITORY=http://10.8.92.1:8080/artifactory/libs-release-local
INHOUSE_USER=user
INHOUSE_PASSWORD=password
COMMON_GRADLE=C:/devel/common.gradle
この値が見える場所と見えない場所がある
この値は「プロジェクト」の中に格納されるようで、プロジェクトに無関係の部分から参照することができない。
例えば、当然のことながらclassのメソッド中では参照できない。
class Sample {
def showit() {
println COMMON_GRADLE // エラー
}
}
Globalsのstatic変数に変更する
これでは使いづらいので、別の変数にそのまま移動させることにする。gradle.propertisの値はproject.propertiesに格納されるので、ここから値を取り出し、クラスのstaticフィールドにセットする。
これらのstaticフィールドとプロパティの名称が同一でなければいけない。
/* グローバル変数の定義
* これらは、gradle.propertiesに定義されたものをそのまま引き継ぐ、ただし、値が事前に格納されている
* ものについてはそのままいじらない
*/
class Globals {
static String CENTRAL_REPOSITORY
static String COMMON_GRADLE
static String INHOUSE_REPOSITORY
static String INHOUSE_USER
static String INHOUSE_PASSWORD
static void setup(Project project) {
Globals.getDeclaredFields().each {
// フィールド名称を取得し、'_'、'$'で開始するもの、metaClassは無視する。
String name = it.getName();
if (name =~ /^[_\$].*|metaClass$/)
return
// 既に値が格納されているものは無視する
it.setAccessible(true)
if (it.get(null) != null) return;
// project.propertiesから値を取得する。存在しなければエラー
String value = project.properties[name]
if (value == null) throw new RuntimeException("No " + name + " in gradle.properties")
// 値を格納する
it.set(null, value)
}
}
}
Globals.setup(project)
クラス変数に格納後のアクセス
このようにすれば、このクラスを指定してアクセスが可能になる
class Sample {
def showit() {
println Globals.COMMON_GRADLE
}
}
スクリプトファイルが分割されている場合
しかし、これでもアクセスができない場合がある。以下のようにスクリプトファイルが分離しているケースだ。
sample.gradle
// Globalsの定義とセットアップ
class Globals {
}
ext.Globals = Globals // これが必要
build.gradle
apply from: 'sample.gradle'
def ShowClosure = {
println Globals.COMMON_GRADLE // OK
}
task Show {
println Globals.COMMON_GRADLE // OK
}
class Sample {
def showit() {
println Globals.COMMON_GRADLE // NG
}
}
この場合は、なぜかクラスメソッドからはアクセスできなくなる。
さんざん調べてみたのだが、このケースではどうやっても何らかの形で引数として与えてやる以外に、この値にアクセスする方法は今のところ見つからない。