第6章 ビルドスクリプトの基本

6.1. プロジェクトとタスクProjects and tasks

Everything in Gradle sits on top of two basic concepts: projects and tasks.


Every Gradle build is made up of one or more projects. What a project represents depends on what it is that you are doing with Gradle. For example, a project might represent a library JAR or a web application. It might represent a distribution ZIP assembled from the JARs produced by other projects. A project does not necessarily represent a thing to be built. It might represent a thing to be done, such as deploying your application to staging or production environments. Don't worry if this seems a little vague for now. Gradle's build-by-convention support adds a more concrete definition for what a project is.


Each project is made up of one or more tasks. A task represents some atomic piece of work which a build performs. This might be compiling some classes, creating a JAR, generating Javadoc, or publishing some archives to a repository.


For now, we will look at defining some simple tasks in a build with one project. Later chapters will look at working with multiple projects and more about working with projects and tasks.


6.2. Hello world

You run a Gradle build using the gradle command. The gradle command looks for a file called build.gradle in the current directory. [3] We call this build.gradle file a build script, although strictly speaking it is a build configuration script, as we will see later. The build script defines a project and its tasks.


To try this out, create the following build script named build.gradle.


例6.1 初めてのビルドスクリプト


task hello {
    doLast {
        println 'Hello world!'

In a command-line shell, move to the containing directory and execute the build script with gradle -q hello:

コンソールを開いてこのbuild.gradleのあるディレクトリに移動して、gradle -q helloと打ち込んでください。ビルドスクリプトが実行され、以下のように出力されるはずです。

-qオプションって何?What does -q do?

Most of the examples in this user guide are run with the -q command-line option. This suppresses Gradle's log messages, so that only the output of the tasks is shown. This keeps the example output in this user guide a little clearer. You don't need to use this option if you don't want to. See 18章ロギング for more details about the command-line options which affect Gradle's output.


例6.2 ビルドスクリプトの実行

gradle -q hello の出力

> gradle -q hello
Hello world!

What's going on here? This build script defines a single task, called hello, and adds an action to it. When you run gradle hello, Gradle executes the hello task, which in turn executes the action you've provided. The action is simply a closure containing some Groovy code to execute.

何が起こったのでしょう。ビルドスクリプトは、helloというタスクを一つ定義していて、このタスクにアクションを一つ追加しています。gradle helloと実行することで、Gradleがこのhelloを実行し、helloに追加したアクションが実行されたのです。アクションはGroovyコードを含む単なるクロージャです。

If you think this looks similar to Ant's targets, well, you would be right. Gradle tasks are the equivalent to Ant targets, but as you will see, they are much more powerful. We have used a different terminology than Ant as we think the word task is more expressive than the word target. Unfortunately this introduces a terminology clash with Ant, as Ant calls its commands, such as javac or copy, tasks. So when we talk about tasks, we always mean Gradle tasks, which are the equivalent to Ant's targets. If we talk about Ant tasks (Ant commands), we explicitly say Ant task.

Antのtargetに似ているなと思われたかもしれません。実際、GradleのtaskはAntでいえばtargetに相当するものです。ただ、これから見ていきますがGradleのtaskはAntのtargetよりもずっと強力なものです。Gradleではtaskという、Antとは異なる用語を採用しました。これはtaskという言葉が、targetという言葉よりも実態に合った表現だと考えたためです。しかし、残念ながらtaskという用語はAntでもcopyjavacといったコマンドを示すものとして使われており、Gradleのtaskと競合してしまいます。このため、Antのtaskについて述べるときには常にant taskと明示的にいい、単にtaskとしたときはGradleのタスクのことを示すものとします。

6.3. タスク定義のショートカットA shortcut task definition

There is a shorthand way to define a task like our hello task above, which is more concise.


例6.3 タスク定義のショートカット


task hello << {
    println 'Hello world!'

Again, this defines a task called hello with a single closure to execute. We will use this task definition style throughout the user guide.


6.4. ビルドスクリプトはコードですBuild scripts are code

Gradle's build scripts give you the full power of Groovy. As an appetizer, have a look at this:


例6.4 GradleタスクでGroovyを使う


task upper << {
    String someString = 'mY_nAmE'
    println "Original: " + someString 
    println "Upper case: " + someString.toUpperCase()

gradle -q upper の出力

> gradle -q upper
Original: mY_nAmE
Upper case: MY_NAME



例6.5 GradleタスクでGroovyを使う


task count << {
    4.times { print "$it " }

gradle -q count の出力

> gradle -q count
0 1 2 3

6.5. タスクの依存関係Task dependencies

As you probably have guessed, you can declare tasks that depend on other tasks.


例6.6 タスク間の依存関係を宣言する


task hello << {
    println 'Hello world!'
task intro(dependsOn: hello) << {
    println "I'm Gradle"

gradle -q intro の出力

> gradle -q intro
Hello world!
I'm Gradle

To add a dependency, the corresponding task does not need to exist.


例6.7 遅延評価のdependsOn - タスクがまだ宣言されていない場合


task taskX(dependsOn: 'taskY') << {
    println 'taskX'
task taskY << {
    println 'taskY'

gradle -q taskX の出力

> gradle -q taskX

The dependency of taskX to taskY is declared before taskY is defined. This is very important for multi-project builds. Task dependencies are discussed in more detail in 「タスクに依存関係を追加するAdding dependencies to a task.

taskXtaskYに依存していることが宣言されていますが、宣言した時点ではtaskYの定義文はありません。このことは、マルチプロジェクトのビルドで非常に重要になってきます。タスク間の依存関係については、「タスクに依存関係を追加するAdding dependencies to a taskでさらに詳しく述べられています。

Please notice, that you can't use a shortcut notation (see 「略記法Shortcut notations) when referring to a task that is not yet defined.

なお、未定義のタスクを参照する場合、略記法(「略記法Shortcut notations参照)は使えませんので注意してください。

6.6. 動的なタスクDynamic tasks

The power of Groovy can be used for more than defining what a task does. For example, you can also use it to dynamically create tasks.


例6.8 動的なタスク定義


4.times { counter ->
    task "task$counter" << {
        println "I'm task number $counter"

gradle -q task1 の出力

> gradle -q task1
I'm task number 1

6.7. 既存のタスクを操作するManipulating existing tasks

Once tasks are created they can be accessed via an API. For instance, you could use this to dynamically add dependencies to a task, at runtime. Ant doesn't allow anything like this.


例6.9 APIからタスクにアクセスする - 依存関係の追加


4.times { counter ->
    task "task$counter" << {
        println "I'm task number $counter"
task0.dependsOn task2, task3

gradle -q task0 の出力

> gradle -q task0
I'm task number 2
I'm task number 3
I'm task number 0

Or you can add behavior to an existing task.


例6.10 APIからタスクにアクセスする - アクションの追加


task hello << {
    println 'Hello Earth'
hello.doFirst {
    println 'Hello Venus'
hello.doLast {
    println 'Hello Mars'
hello << {
    println 'Hello Jupiter'

gradle -q hello の出力

> gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter

The calls doFirst and doLast can be executed multiple times. They add an action to the beginning or the end of the task's actions list. When the task executes, the actions in the action list are executed in order. The << operator is simply an alias for doLast.


6.8. 略記法Shortcut notations

As you might have noticed in the previous examples, there is a convenient notation for accessing an existing task. Each task is available as a property of the build script:


例6.11 ビルドスクリプトのプロパティとして既存のタスクにアクセスする


task hello << {
    println 'Hello world!'
hello.doLast {
    println "Greetings from the $hello.name task."

gradle -q hello の出力

> gradle -q hello
Hello world!
Greetings from the hello task.

This enables very readable code, especially when using the tasks provided by the plugins, like the compile task.


6.9. 拡張タスクプロパティ Extra task properties

You can add your own properties to a task. To add a property named myProperty, set ext.myProperty to an initial value. From that point on, the property can be read and set like a predefined task property.

独自のプロパティをタスクに追加することができます。例えば、myPropertyというプロパティを追加するには、ext.myPropertyに初期値を設定してください。 その時点で、このプロパティを定義済みのプロパティと同じように読み書きできるようになります。

例6.12 拡張プロパティをタスクに追加する


task myTask {
    ext.myProperty = "myValue"

task printTaskProperties << {
    println myTask.myProperty

gradle -q printTaskProperties の出力

> gradle -q printTaskProperties

Extra properties aren't limited to tasks. You can read more about them in 「拡張プロパティ Extra properties.

拡張プロパティを追加できるのは、タスクだけではありません。詳細については、「拡張プロパティ Extra propertiesを参照してください。

6.10. Antタスクの使用Using Ant Tasks

Ant tasks are first-class citizens in Gradle. Gradle provides excellent integration for Ant tasks by simply by relying on Groovy. Groovy is shipped with the fantastic AntBuilder. Using Ant tasks from Gradle is as convenient and more powerful than using Ant tasks from a build.xml file. From the example below, you can learn how to execute Ant tasks and how to access Ant properties:


例6.13 AntBuilderを使ってant.loadfileターゲットを実行する


task loadfile << {
    def files = file('../antLoadfileResources').listFiles().sort()
    files.each { File file ->
        if (file.isFile()) {
            ant.loadfile(srcFile: file, property: file.name)
            println " *** $file.name ***"
            println "${ant.properties[file.name]}"

gradle -q loadfile の出力

> gradle -q loadfile
*** agile.manifesto.txt ***
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration  over contract negotiation
Responding to change over following a plan
 *** gradle.manifesto.txt ***
Make the impossible possible, make the possible easy and make the easy elegant.
(inspired by Moshe Feldenkrais)

There is lots more you can do with Ant in your build scripts. You can find out more in 17章GradleからAntを使う.


6.11. メソッドの使用Using methods

Gradle scales in how you can organize your build logic. The first level of organizing your build logic for the example above, is extracting a method.


例6.14 メソッドを抽出してビルドロジックを整理する


task checksum << {
    fileList('../antLoadfileResources').each {File file ->
        ant.checksum(file: file, property: "cs_$file.name")
        println "$file.name Checksum: ${ant.properties["cs_$file.name"]}"

task loadfile << {
    fileList('../antLoadfileResources').each {File file ->
        ant.loadfile(srcFile: file, property: file.name)
        println "I'm fond of $file.name"

File[] fileList(String dir) {
    file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()

gradle -q loadfile の出力

> gradle -q loadfile
I'm fond of agile.manifesto.txt
I'm fond of gradle.manifesto.txt

Later you will see that such methods can be shared among subprojects in multi-project builds. If your build logic becomes more complex, Gradle offers you other very convenient ways to organize it. We have devoted a whole chapter to this. See 60章ビルドロジックの体系化.


6.12. デフォルトタスクDefault tasks

Gradle allows you to define one or more default tasks for your build.


例6.15 デフォルトタスクの定義


defaultTasks 'clean', 'run'

task clean << {
    println 'Default Cleaning!'

task run << {
    println 'Default Running!'

task other << {
    println "I'm not a default task!"

gradle -q の出力

> gradle -q
Default Cleaning!
Default Running!

This is equivalent to running gradle clean run. In a multi-project build every subproject can have its own specific default tasks. If a subproject does not specify default tasks, the default tasks of the parent project are used (if defined).

これは、gradle clean runと入力するのと同じです。マルチプロジェクトのビルドでは、すべてのサブプロジェクトが個別にデフォルトタスクを持つことができます。サブプロジェクトにデフォルトタスクが定義されていない時は、(定義されていれば)親プロジェクトの定義が使用されます。

6.13. DAGによる設定Configure by DAG

As we later describe in full detail (See 56章ビルドのライフサイクル) Gradle has a configuration phase and an execution phase. After the configuration phase, Gradle knows all tasks that should be executed. Gradle offers you a hook to make use of this information. A use-case for this would be to check if the release task is among the tasks to be executed. Depending on this, you can assign different values to some variables.


In the following example, execution of the distribution and release tasks results in different value of the version variable.


例6.16 選択したタスクによって異なる結果を得る


task distribution << {
    println "We build the zip with version=$version"

task release(dependsOn: 'distribution') << {
    println 'We release now'

gradle.taskGraph.whenReady {taskGraph ->
    if (taskGraph.hasTask(release)) {
        version = '1.0'
    } else {
        version = '1.0-SNAPSHOT'

gradle -q distribution の出力

> gradle -q distribution
We build the zip with version=1.0-SNAPSHOT

gradle -q release の出力

> gradle -q release
We build the zip with version=1.0
We release now

The important thing is that whenReady affects the release task before the release task is executed. This works even when the release task is not the primary task (i.e., the task passed to the gradle command).


6.14. 次のステップは?Where to next?

In this chapter, we have had a first look at tasks. But this is not the end of the story for tasks. If you want to jump into more of the details, have a look at 15章タスク詳解.


Otherwise, continue on to the tutorials in 7章Javaクイックスタート and 8章依存関係管理の基本 .

そうでなければ、7章Javaクイックスタート8章依存関係管理の基本 に進み、チュートリアルを続けてください。

[3] There are command line switches to change this behavior. See 付録D Gradle コマンドラインGradle Command Line)

[4] この動作はコマンドラインスイッチを使用して変更できます。付録D Gradle コマンドラインGradle Command Lineを参照してください。