Gradle勉強会を社内でやったときの資料(Gradleを使えるようになるために)

社内でGradle勉強会をやりました! その時の資料です。

Gradleを使えるようになるために

Gradleを使えるようになるにはドキュメント読むのが一番なんだけど、Gradle(とGroovy)を全く知らないとドキュメントがスラスラ読めない、という印象を持ってます。

私もGroovyやったことなかったし、Gradleのドキュメントを読んで理解するのに苦労しました。 なので、自分自身でドキュメントを読んで学んでいくためにおさえておくと良さそうだと思った部分を話しました。

それにしてもAndroidのおかげで社内のGradle化が捗りますねー、ありがたい!

以下スライド本文

2014/5/24 追記 スライドをmarkdownで書いてたので本文も載っけることにしました。

Gradleを使えるようになるために


目次

  • Gradleとは
  • とりあえず動かす
  • Gradleを使えるようになるためにはどうすれば?
  • 超シンプルな例
  • 超シンプルな例を詳しく見てみる
  • Androidプリプロジェクトのビルドスクリプト
  • まとめ

Gradleとは

  • JVMで動くビルドツール
  • ビルドスクリプトをGroovyで書く
  • ライブラリの依存関係管理もできる
  • Springなど、Javaのプロダクトのビルドで使われている
  • Androidアプリのビルドにも使われる(今後標準になる?)

Gradleを使えるようになるにはどうすれば?

  • ドキュメントを読もう!
  • でも何も分からない状態だとちょっと読みづらい・・・
  • 読むための知識を身につけよう!

とりあえず動かす

Gradleをダウンロードしてパスを通して実行してみる

$ gradle
:help

Welcome to Gradle 1.12.

To run a build, run gradle  ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

BUILD SUCCESSFUL

Total time: 2.464 secs

ビルドスクリプトはbuild.gradleにGroovyで書く

// build.gradle
println("hogehoge")

build.gradleと同じディレクトリで実行してみる

$ gradle
hogehoge

Welcome to Gradle 1.12.

To run a build, run gradle  ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

BUILD SUCCESSFUL

Total time: 2.464 secs

build.gradleに記述した通り"hogehoge"が出力されてる!


実際は、実行したい処理は タスク として記述する

// build.gradle
task hoge << {
    println("hogehoge")
}

gradle <task name> でタスクを実行する

$ gradle hoge
:hoge
hogehoge

BUILD SUCCESSFUL

Total time: 2.694 secs

-qオプションをつけるとタスクの出力のみを表示する

$ gradle -q hoge
hogehoge

タスク一覧を表示。hoge以外にも最初からいくつかある

$ gradle -q tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
dependencies - Displays all dependencies declared in root project 'fuga'.
dependencyInsight - Displays the insight into a specific dependency in root project 'fuga'.
help - Displays a help message
projects - Displays the sub-projects of root project 'fuga'.
properties - Displays the properties of root project 'fuga'.
tasks - Displays the tasks runnable from root project 'fuga'.

Other tasks
-----------
hoge

To see all tasks and more detail, run with --all.

タスク同士は依存関係を持つことができる

// build.gradle
task hoge << {
    println("hogehoge")
}

task fuga(dependsOn: "hoge") << {
    println("fugafuga")
}

fugaタスクはhogeタスクに依存している
fugaタスクを実行すると、先にhogeタスクが実行される

$ gradle -q fuga
hogehoge
fugafuga

tasksタスクの--allオプション
タスクの依存関係も表示してくれる

$ gradle -q tasks --all

・・・

Other tasks
-----------
fuga
    hoge

ちょっとまとめ

  • build.gradleにビルドスクリプトを書く
  • 処理はタスクという単位で書いたり実行したりする
  • tasksタスクで(gradle tasks)実行できるタスクを確認できる
  • -qオプションでタスクの出力以外を表示しない
  • タスク同士は依存関係を持てる
  • gradle tasks --all で依存関係を確認できる

超シンプルな例

// build.gradle
apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compile 'joda-time:joda-time:2.3'
}

プラグインの設定

apply plugin: 'java'
$ gradle -q tasks

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles classes 'main'.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles classes 'test'.

# 他にもいろいろ...


ディレクトリ構成

<PROJECT_HOME>
├── build.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── myapp
    │   │       └── Main.java
    │   └── resources
    └── test
        ├── java
        └── resources

ライブラリの依存関係管理

// build.gradle
repositories {
    mavenCentral()
}

dependencies {
    compile 'joda-time:joda-time:2.3'
}

ちょっとまとめ

  • build.scriptには、Groovyでごりごり実装していくのではなくDSLを使って設定を記述していく感じ
  • プラグインを使ってタスクを追加できる
  • プラグインで何ができるかはユーザーガイドで調べることができる
  • GradleでJavaをビルドする場合は、デフォルトで想定されるディレクトリ構成がある
  • Mavenリポジトリを使ったライブラリの依存関係管理ができる

超シンプルな例を詳しく見てみる

applyは何者?

// build.gradle
apply plugin: 'java'
  • Projectオブジェクトのapply()メソッド
  • build.gradleではProjectオブジェクトのメソッドが呼べる
  • DSLリファレンスで他のメソッドも分かる -> Project
  • ただのメソッド呼び出しがGroovyのおかげで設定項目のように見える
    • メソッド呼び出しの()を省略できる
    • メソッドの最後の引数がMapであるとき、名前付き引数のように指定できる

repositoriesとdependenciesもProjectのメソッド

// build.gradle
repositories {
    mavenCentral()
}

dependencies {
    compile 'joda-time:joda-time:2.3'
}
repositories {
    mavenCentral()
}
repositories(function(){
    mavenCentral()
});

じゃあmavenCentral()もProjectのメソッド

// build.gradle
repositories {
    mavenCentral()
}
  • 違う
  • リファレンスを見てもProjectにmavenCentral()はない
  • じゃあ、誰のメソッドを呼び出しているのか?

DSLリファレンスで
repositoriesスクリプトブロックを調べる

"The RepositoryHandler is passed to the closure as the closure's delegate."

Delegates to: RepositoryHandler from repositories

[ 引用 ] Gradleビルド言語リファレンス


なぜクロージャ内からRepositoryHandlerの
メソッドを呼べるのか?

  • クロージャの暗黙的引数であるdelegateを利用している
  • delegate変数にRepositoryHandlerオブジェクトが渡される
  • "delegate"を省略してメソッド名のみで呼ぶことができる(thisのように省略できる)。つまり、以下の2つは同じ
repositories {
    mavenCentral()
}
repositories {
    delegate.mavenCentral()
}

ちょっとまとめ

  • build.gradleではProjectのメソッドが呼べる
    • DSLリファレンスでProjectを調べれば、build.gradleに何を書けるのか分かる
  • メソッドの中にはクロージャを渡せるものがあり、スクリプトブロックとなる
  • ブロック内(クロージャ)では、Project以外のオブジェクトのメソッドも呼べる
    • ブロック内から参照できるオブジェクトはDSLリファレンスの「Deletes to:」を見ると分かる

Androidプリプロジェクトのビルドスクリプト

Android Studioで作成したプロジェクトを見てみよう!


Gradle関連のファイルをピックアップ

<PROJECT_HOME>
  |- build.gradle
  |- gradle/
  |   `- wrapper/
  |      |- gradle-wrapper.jar
  |      `- gradle-wrapper.properties
  |- gradlew
  |- gradlew.bat
  |- settings.gradle
  |
  `- app/
      `- build.gradle

gradlew, gradlew.bat, gradle/

  • Gradleラッパーという仕組みがある
  • ユーザーガイド => Gradleラッパー
  • gradlewコマンドを実行するとgradle-wrapper.propertiesに書いてあるバージョンのGradleをダウンロードして使ってくれる
  • 各環境にあるgradleコマンドを使うのではなく、プロジェクト上のgradlewを使うことで環境依存を減らせる
<PROJECT_HOME>
  |- gradle/
  |   `- wrapper/
  |      |- gradle-wrapper.jar
  |      `- gradle-wrapper.properties
  |- gradlew
  `- gradlew.bat

build.gradle

<PROJECT_HOME>
  |- build.gradle
  |- settings.gradle
  `- app/
      `- build.gradle

マルチプロジェクト

  • Gradleはサブプロジェクトを持つ階層型のプロジェクト構成を定義できる
  • Androidではマルチプロジェクト構成となっている
  • Android開発ではライブラリプロジェクトをサブプロジェクトとして追加していくことができる
  • ユーザーガイド => マルチプロジェクトのJavaビルド

settings.gradle

  • マルチプロジェクト構成におけるサブプロジェクトを定義する
<PROJECT_HOME>
  |- build.gradle
  |- settings.gradle
  `- app/
      `- build.gradle

settings.gradleの中身

// settings.gradle
include ':app'

includeは何者?


build.gradle

中身を見てみよう!もう調べられるはず!

<PROJECT_HOME>
  |- build.gradle
  |- settings.gradle
  `- app/
      `- build.gradle

ちょっとまとめ

  • Gradleラッパーで環境によらず同じバージョンのGradleを使える
  • Gradleではマルチプロジェクト構成にできる
    • サブプロジェクトはsettings.gradleで定義
    • settings.gradleではSettingsのメソッドが呼べる
  • Androidアプリ開発ではマルチプロジェクト構成になる

全体のまとめ

  • Gradleでは色々できる
  • 何ができるかはドキュメントを読むと分かる
  • だけど何も知らないとドキュメントは読みづらい
  • 以下の点を知っておくと読みやすくなると思う
    • Gradleにはおおまかにどんな機能があるか
    • build.gradleに記述できる内容をどうやって調べるか

  • 今日出てきたGradleの機能たち
    • タスク
    • プラグイン
    • ライブラリの依存関係の管理
    • マルチプロジェクト
    • Gradleラッパー
  • ユーザーガイドを見ると各機能について調べられる
  • 標準的な各種プラグインで何ができるかもユーザーガイドを見れば分かる



おしまい