2011年3月15日火曜日

Gradleでプロパティなどの設定情報を外出しして切り替えて使う

@bluepapa32さんの記事に触発されて書いてみました。

次のようなビルドスクリプトがあるとき、
task hello << {
println "Hello, $yourname"
}
Gradleでプロパティ「$yourname」の設定を外だしにして、ビルドごとに結果を柔軟に変えたい、といったことを実現する方法ですね。

@bluepapa32さんも書かれているように、Gradleではさまざまな方法でこれを実現できます。
ここでは、主にGradleの機能を使ってこれを実現する方法について書いてみます。

ビルドスクリプトの設定をいろいろ切り替えるには


task hello << {
println "Hello, $yourname"
}
上記のビルドスクリプトをそのまま「gradle hello」と実行しても、yournameなんてプロパティはないですと怒られて失敗するので、プロパティyournameをビルドスクリプトに設定してやる必要があります。

このとき、プロパティyournameのような設定情報をビルドスクリプトの外で設定し、切り替えられるようにするには、

  • コマンドライン引数で直接設定
  • 環境変数→プロパティ自動変換機能を使う
  • gradle.propertiesをユーザーのホームディレクトリまたはプロジェクトディレクトリに置く
  • 外部ファイルをビルドスクリプトなどの先頭で読み込む
  • 初期化スクリプト(init.gradle)を使う
の方法が考えられます。

詳しくはユーザーガイド(Gradleプロパティとシステムプロパティ)など見てもらうとして、ここでは一つずつ使いどころなど簡単に考えてみたいと思います。

コマンドライン引数で直接設定


コマンドラインオプションを使って、yournameのようなプロパティを設定できます。
gradle -Pyourname=literalice hello

:hello
Hello, literalice

BUILD SUCCESSFUL
設定したいプロパティが少ないときや簡単なデモなどで使えますね。

環境変数→プロパティ自動変換機能を使う


Gradleは、プレフィックス「ORG_GRADLE_PROJECT_」の付いた環境変数を定義しておくと、その値をプロパティに変換してくれる機能があります。
set ORG_GRADLE_PROJECT_yourname=literalice

gradle hello

:hello
Hello, literalice

BUILD SUCCESSFUL
設定するプロパティの数がそう多くない場合で、ビルドするマシンごとにプロパティを切り替えたいとき、jenkinsなどのCIサーバー上で簡単にビルドを設定したいときなどに。

Gradleだと、環境変数を直接ビルドスクリプトで読む(System.getenv) ようなシチュエーションは限られますね。(外部ツールとの連携時とか?)

gradle.propertiesをユーザーのホームディレクトリまたはプロジェクトディレクトリに置く


gradle.propertiesという名前でプロパティファイルを作成し、プロジェクトディレクトリまたはユーザーのホームディレクトリに置いておくと、読み込んで使ってくれます。

なお、プロジェクトディレクトリ→ユーザーのホームディレクトリの順に読み込まれます。

ユーザーのホームディレクトリのプロパティが優先して使われる(上書きする)ということです。

~/.gradle/gradle.properties
yourname=literalice
実行結果
gradle hello

:hello
Hello, literalice

BUILD SUCCESSFUL

ホームディレクトリのgradle.propertiesは、すべてのビルドスクリプトで使われます。

ツールの場所(grailsHomeとか、javaHomeとか)、ユーザーの(sshやwebページなどへの)ログイン情報などを設定するのに良いかもしれません。

ちなみに、ここまでの設定方法だと、どれ選んだ場合でもビルドスクリプトの方は変更する必要ないんですよね。素晴らしい。

外部ファイルをビルドスクリプトなどの先頭で読み込む


いくつか方法はありますが、

  • Groovyの機能で外部ファイルを読み込んで展開する
  • 外部のスクリプトファイルを読み込む

の二つを紹介しようと思います。

1. Groovyの機能で外部ファイルを読み込んで展開する

この方法は、@bluepapa32さんが解説されています。

GroovyのConfigSlurperを使って、Groovyスクリプト形式の設定ファイルを読み込み、プロパティに展開しています。

既存の設定ファイル(GrailsのDataSource.groovyやBuildConfig.groovyなど)を読み込むときに便利です。

2. 外部のスクリプトファイルを読み込む

たとえば、プロパティのセットをLinux向け、Windows向けなどいくつか定義しておいて、それらを簡単に切り替えできるようにしたい、というときはこの方法が使えます。

build.gradle
apply from:"default.config.gradle"
apply from:"${env}.config.gradle"

task hello << {
println "Hello, $yourname"
}

設定ファイルをいくつか用意します。
default.config.gradle
yourname = "the name in the default config"
linux.config.gradle
yourname = "the name in the linux config"
windows.config.gradle
yourname = "the name in the windows config"

実行するときは、こんな感じ

gradle -Penv=windows hello

:hello
Hello, the name in the windows config

BUILD SUCCESSFUL

イメージとしては、apply from:"..."で読み込んだファイルが、そのままペーストされる感じで動きます。

読み込んでいる外部スクリプトは、ただのGradleビルドスクリプトなので、上記のようなプロパティの設定だけでなく、タスクの定義やプロジェクト設定の変更など、Gradleでできることはなんでもできます

初期化スクリプト(init.gradle)を使う


Gradleには初期化スクリプトという仕組みがあって、マシン固有の設定をここでも行うことができます。

具体的には、「init.gradle」というファイルをユーザーのホームディレクトリに置いたり、コマンドラインオプションで渡してやったりすると、ビルドが構築される前に「init.gradle」が実行されるというものです。

初期化スクリプト

このスクリプトで、今までのように単純なプロジェクトプロパティをセットするにはかなりめんどくさい方法をとる必要があり現実的ではないです。

ビルドのライフサイクルに対するリスナーや、カスタムのロガーを登録する、外部ツールとの連携に便利らしいのですが、私の使用した範囲だとまだ使いこなせたことはないですね…

まとめ


Gradleのビルドを設定する方法をいくつか見てきましたが、こんな風にいろいろな方法を選ぶことができるのはGradleの魅力の一つだと思います。

場面場面に応じて、適切な方法を選んでいきたいですね。