This chapter looks at some of the details of writing a build script.
本章では、ビルドスクリプトの記述についてもう少し詳しく見ていきます。
Gradle provides a domain specific language, or DSL, for describing builds. This build language is based on Groovy, with some additions to make it easier to describe a build.
Gradleは、ビルドシステムを記述するためのドメイン特化言語(DSL)を提供します。 このビルド用言語は、Groovyをベースに、ビルドシステムの記述を簡単にするための機能をいくつか追加したものです。
A build script can contain any Groovy language element. [9] Gradle assumes that each build script is encoded using UTF-8.
In the tutorial in 7章Javaクイックスタート we used, for example, the
apply()
method. Where does this method come from? We said earlier that the build script
defines a project in Gradle. For each project in the build, Gradle creates an object of type
Project
and associates this Project
object with
the build script. As the build script executes, it configures this Project
object:
例えば、7章Javaクイックスタートのチュートリアルで使用したapply()
メソッド、このメソッドはどこから来たのでしょうか。まず、前述のようにビルドスクリプトはGradleのプロジェクトを定義します。
ビルドに含まれるプロジェクトそれぞれに対し、Project
型のインスタンスが一つ作られ、ビルドスクリプトと関連づけられます。ビルドが実行されると、このプロジェクト・インスタンスは以下のように振る舞います。
Don't forget that your build script is simply Groovy code that drives the Gradle API. And the
Project
interface is your starting point for accessing everything
in the Gradle API. So, if you're wondering what 'tags' are available in your build script, you can
start with the documentation for the Project
interface.
ビルドスクリプトは、GradleのAPIを呼び出しているだけの単なるGroovyスクリプトだということを忘れないでください。Project
インターフェースが、GradleのAPIを呼び出すときのスタートポイントです。なので、ビルドスクリプトでどんな「文言」が使えるか分からないときはProject
インターフェースのドキュメントを見ることから始めるといいでしょう。
Any method you call in your build script which is not defined
in the build script, is delegated to the Project
object.
ビルドスクリプトで呼び出されたメソッドのうち、そのスクリプトで定義されていないものはProject
オブジェクトに委譲されます。
Any property you access in your build script, which is not defined
in the build script, is delegated to the Project
object.
ビルドスクリプトでのプロパティアクセスも、そのスクリプトで定義されていないプロパティについてはProject
オブジェクトに委譲されます。
Let's try this out and try to access the name
property of the
Project
object.
プロジェクトオブジェクトのname
プロパティにアクセスして試してみましょう。
例13.1 Projectオブジェクトへのアクセス
build.gradle
println name println project.name
gradle -q check
の出力
> gradle -q check projectApi projectApi
Both println
statements print out the same property. The first uses auto-delegation to
the Project
object, for properties not defined in the build script. The other
statement uses the project
property available to any build script, which returns the
associated Project
object. Only if you define a property or a method which has the
same name as a member of the Project
object, would you need to use the project
property.
どちらのprintln
も出力結果は同じです。最初のprintlnは、ビルドスクリプトで定義されていないプロパティへのアクセスを、暗黙のうちにプロジェクトオブジェクトに委譲しています。もう一方の例では、プロジェクトオブジェクトを返すproject
プロパティを使って、name
にアクセスしています。project
プロパティには、ビルドスクリプトのどこからでもアクセスできます。プロジェクトオブジェクトのプロパティやメソッドと同名のものをビルドスクリプトに定義している場合は、project
プロパティからアクセスすることになるでしょう。
The Project
object provides some standard properties, which are available in
your build script. The following table lists a few of the commonly used ones.
プロジェクトオブジェクトは標準でいくつかのプロパティを提供しており、ビルドスクリプトでこれらのプロパティにアクセスできます。次の表によく使うプロパティを少しですが載せてみました。
表13.1 プロジェクトプロパティProject Properties
プロパティ名Name | 型Type | デフォルト値Default Value |
project |
Project |
Project インスタンスThe Project instance |
name |
String |
プロジェクトディレクトリの名前The name of the project directory. |
path |
String |
プロジェクトの絶対パスThe absolute path of the project. |
description |
String |
プロジェクトの説明A description for the project. |
projectDir |
File |
ビルドスクリプトのあるディレクトリThe directory containing the build script. |
buildDir |
File |
|
group |
Object |
未設定 unspecified |
version |
Object |
未設定 unspecified |
ant |
AntBuilder |
AntBuilder インスタンスAn AntBuilder instance |
When Gradle executes a script, it compiles the script into a class which implements Script
.
This means that all of the properties and methods declared by the Script
interface
are available in your script.
ビルドスクリプトが実行されるときは、スクリプトはScript
を実装したクラスにコンパイルされます。つまり、ビルドスクリプトではScript
インターフェースで宣言されているプロパティとメソッドを全て使うことができるということです。
There are two kinds of variables that can be declared in a build script: local variables and extra properties.
ビルドスクリプトでは、二つの方法で変数を宣言できます。ローカル変数と拡張プロパティです。
Local variables are declared with the def
keyword. They are only visible in the scope where they have been declared.
Local variables are a feature of the underlying Groovy language.
ローカル変数は、def
キーワードで宣言する変数です。変数のスコープは、変数が宣言されている場所に制限されます。なお、ローカル変数はGroovy言語に依る機能です。
All enhanced objects in Gradle's domain model can hold extra user-defined properties. This includes, but is not limited to, projects, tasks,
and source sets. Extra properties can be added, read and set via the owning object's ext
property. Alternatively, an
ext
block can be used to add multiple properties at once.
Gradleのドメインモデルを構成する全ての拡張オブジェクトには、ユーザー定義のプロパティ、拡張プロパティを新たに追加することができます。
拡張プロパティを追加できるオブジェクトには、projects、tasks、source setsを始め、様々なオブジェクトがあります。
拡張プロパティをセットしたり読み込んだりするには、対象オブジェクトのext
プロパティを使用して下さい。また、ext
ブロックを使って複数のプロパティを一気に追加することもできます。
例13.3 拡張プロパティを使用する
build.gradle
apply plugin: "java" ext { springVersion = "3.1.0.RELEASE" emailNotification = "build@master.org" } sourceSets.all { ext.purpose = null } sourceSets { main { purpose = "production" } test { purpose = "test" } plugin { purpose = "production" } } task printProperties << { println springVersion println emailNotification sourceSets.matching { it.purpose == "production" }.each { println it.name } }
gradle -q printProperties
の出力
> gradle -q printProperties 3.1.0.RELEASE build@master.org main plugin
In this example, an ext
block adds two extra properties to the project
object. Additionally,
a property named purpose
is added to each source set by setting ext.purpose
to
null
(null
is a permissible value). Once the properties have been added, they can be read and set like
predefined properties.
この例では、ext
ブロックで二つの拡張プロパティをproject
オブジェクトに追加しています。
さらに、ext.purpose
にnull
をセットすることで(null
でも構いません)、全てのソースセットにpurpose
という拡張プロパティを追加しています。
一度プロパティが追加されれば、定義済みのプロパティと同じように読み込んだり書き込んだりすることができるようになります。
By requiring special syntax for adding a property, Gradle can fail fast when an attempt is made to set a (predefined or extra) property but the property is misspelled or does not exist. Extra properties can be accessed from anywhere their owning object can be accessed, giving them a wider scope than local variables. Extra properties on a project are visible from its subprojects.
For further details on extra properties and their API, see the ExtraPropertiesExtension
class in the API documentation.
Groovy provides plenty of features for creating DSLs, and the Gradle build language takes advantage of these. Understanding how the build language works will help you when you write your build script, and in particular, when you start to write custom plugins and tasks.
GroovyにはDSLを作るための機能が豊富に用意されていて、Gradleもその長所を活用しています。Gradleビルド言語がどういう仕組みで動いているか理解すれば、ビルドスクリプトを書くのに、特にカスタムプラグインやタスクを作り始めたときには役に立つはずです。
Groovy adds lots of useful methods to the standard Java classes. For example, Iterable
gets
an each
method, which iterates over the elements of the Iterable
:
Groovyは、たくさんの便利なメソッドをJavaの標準クラスに追加しています。たとえば、Iterable
にはeach
というメソッドが追加されていて、要素を走査するときに次のように書くことができます。
例13.4 Groovy JDKのメソッド
build.gradle
// Iterable gets an each() method
configurations.runtime.each { File f -> println f }
Have a look at http://groovy.codehaus.org/groovy-jdk/ for more details.
詳細はhttp://groovy.codehaus.org/groovy-jdk/をご参照ください。
Groovy automatically converts a property reference into a call to the appropriate getter or setter method.
Groovyは、プロパティ参照を自動的にゲッター/セッターメソッドの呼び出しに変換してくれます。
例13.5 プロパティアクセサ
build.gradle
// Using a getter method println project.buildDir println getProject().getBuildDir() // Using a setter method project.buildDir = 'target' getProject().setBuildDir('target')
Parentheses are optional for method calls.
Groovyではメソッド呼び出しのカッコは省略できます。
例13.6 カッコなしのメソッド呼び出し
build.gradle
test.systemProperty 'some.prop', 'value' test.systemProperty('some.prop', 'value')
Groovy provides some shortcuts for defining List
and Map
instances. Both kinds of literals are straightforward, but map literals have some interesting twists.
Groovyでは、List
やMap
のインスタンスを作るときにショートカット記法が使えます。
For instance, the “apply
” method (where you typically apply plugins) actually
takes a map parameter. However, when you have a line like “apply plugin:'java'
”, you
aren't actually using a map literal, you're actually using “named parameters”, which have almost exactly
the same syntax as a map literal (without the wrapping brackets). That named parameter list gets converted
to a map when the method is called, but it doesn't start out as a map.
例13.7 マップリテラル、リストリテラル
build.gradle
// List literal test.includes = ['org/gradle/api/**', 'org/gradle/internal/**'] List<String> list = new ArrayList<String>() list.add('org/gradle/api/**') list.add('org/gradle/internal/**') test.includes = list // Map literal. Map<String, String> map = [key1:'value1', key2: 'value2'] // Groovy will coerce named arguments // into a single map argument apply plugin: 'java'
The Gradle DSL uses closures in many places. You can find out more about closures here. When the last parameter of a method is a closure, you can place the closure after the method call:
GradleのDSLでは、クロージャ(詳細はこちら)を多用します。Groovyでは、メソッドの最後の引数がクロージャになっている場合、そのメソッドをクロージャをつけて呼び出すことができます。
例13.8 メソッドのクロージャ引数
build.gradle
repositories { println "in a closure" } repositories() { println "in a closure" } repositories({ println "in a closure" })
Each closure has a delegate
object, which Groovy uses to look up variable and method
references which are not local variables or parameters of the closure. Gradle uses this for
configuration closures, where the delegate
object is set to
the object to be configured.
すべてのクロージャは、delegate
オブジェクトを持っています。クロージャ内では、(クロージャ引数やローカル変数以外の)変数やメソッドはdelegate
オブジェクトから検索されます。Gradleの設定用クロージャでは、delegate
オブジェクトに設定対象のオブジェクトがセットされています。
例13.9 クロージャのdelegate
build.gradle
dependencies { assert delegate == project.dependencies testCompile('junit:junit:4.11') delegate.testCompile('junit:junit:4.11') }