Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Gradle入門
Search
Benoît Quenaudon
August 19, 2016
Programming
1
250
Gradle入門
Benoît Quenaudon
August 19, 2016
Tweet
Share
More Decks by Benoît Quenaudon
See All by Benoît Quenaudon
36・15 Cash App
oldergod
1
170
Sweet Architecture
oldergod
1
330
Architecture at Scale (droidconNYC 2022)
oldergod
2
550
Managing gRPC with Wire
oldergod
2
500
Wire & Proto3
oldergod
0
74
Effective Reactive Architecture
oldergod
2
200
Wire 3 : Tackling gRPC with Kotlin
oldergod
0
950
Server Driven UI Workflow
oldergod
2
480
Applying Rx Best Practices to Your Architecture
oldergod
1
200
Other Decks in Programming
See All in Programming
シェーダーで魅せるMapLibreの動的ラスタータイル
satoshi7190
1
480
最新TCAキャッチアップ
0si43
0
140
GitHub Actionsのキャッシュと手を挙げることの大切さとそれに必要なこと
satoshi256kbyte
5
430
CSC509 Lecture 09
javiergs
PRO
0
140
イベント駆動で成長して委員会
happymana
1
320
Remix on Hono on Cloudflare Workers
yusukebe
1
280
ピラミッド、アイスクリームコーン、SMURF: 自動テストの最適バランスを求めて / Pyramid Ice-Cream-Cone and SMURF
twada
PRO
10
1.3k
リアーキテクチャxDDD 1年間の取り組みと進化
hsawaji
1
220
Realtime API 入門
riofujimon
0
150
型付き API リクエストを実現するいくつかの手法とその選択 / Typed API Request
euxn23
8
2.2k
as(型アサーション)を書く前にできること
marokanatani
9
2.6k
CSC509 Lecture 12
javiergs
PRO
0
160
Featured
See All Featured
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
25
1.8k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
506
140k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
720
A better future with KSS
kneath
238
17k
Agile that works and the tools we love
rasmusluckow
327
21k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
27
840
The World Runs on Bad Software
bkeepers
PRO
65
11k
The Language of Interfaces
destraynor
154
24k
Designing on Purpose - Digital PM Summit 2013
jponch
115
7k
Typedesign – Prime Four
hannesfritz
40
2.4k
Transcript
入門
• 2007年: 初リリース • OS: クロスプラットフォーム • 種類: ビルドツール •
サイト: www.gradle.org • 2013年: Android に選ばれた
Gradle Tasks • Gradleはタスクベース。 ◦ タスクって?なんでもあり。 ◦ 例:javac, cp /src
/out, print `hello`… • タスク同士の依存関係有り • インプットとアウトプットの設定有り
CLI Gradle • gradle コマンド • ラッパー $~ gradle wrapper
で生成 ◦ gradlew.sh Linux/OS X ◦ gradlew.bat Windows ◦ gradle/wrapper/gradle-wrapper.properties ▪ 環境変数 ▪ Gradleバージョン ◦ gradle/wrapper/gradle-wrapper.jar
gradlew(rapper) • gradle のインストール確認 ◦ インストールされていない場合properties に従って妥当 なバージョンの gradle をダウンロードする
⇒ どの環境でも同じバージョンで実行される事は保 証できる
タスク実行 • タスク実行 ◦ 例 initというタスク:./gradlew init • タスク一覧の表示 ◦
./gradlew tasks
Gradle Build Scripts apply plugin: 'com.android.application' android { compileSdkVersion 21
buildToolsVersion '21.1.2' defaultConfig { versionCode 1 versionName '1.0' } buildTypes { release { minifyEnabled false } } } task hello { doLast { println 'ハローワールド!' } } • 設定ファイル:build.gradle
Gradle Build Scripts apply plugin: 'com.android.application' android { compileSdkVersion 21
buildToolsVersion '21.1.2' defaultConfig { versionCode 1 versionName '1.0' } buildTypes { release { minifyEnabled false } } } task hello { doLast { println 'ハローワールド!' } } • 設定ファイル:build.gradle • android プラグインを適用
Gradle Build Scripts apply plugin: 'com.android.application' android { compileSdkVersion 21
buildToolsVersion '21.1.2' defaultConfig { versionCode 1 versionName '1.0' } buildTypes { release { minifyEnabled false } } } task hello { doLast { println 'ハローワールド!' } } • 設定ファイル:build.gradle • android プラグインを適用 • android プラグインの設定
Gradle Build Scripts apply plugin: 'com.android.application' android { compileSdkVersion 21
buildToolsVersion '21.1.2' defaultConfig { versionCode 1 versionName '1.0' } buildTypes { release { minifyEnabled false } } } task hello { doLast { println 'ハローワールド!' } } • 設定ファイル:build.gradle • android プラグインを適用 • android プラグインの設定 • hello タスクを定義
Gradle Build Scripts apply plugin: 'com.android.application' android { compileSdkVersion 21
buildToolsVersion '21.1.2' defaultConfig { versionCode 1 versionName '1.0' } buildTypes { release { minifyEnabled false } } } task hello { doLast { println 'ハローワールド!' } } • 設定ファイル:build.gradle • android プラグインを適用 • android プラグインの設定 • hello タスクを定義 • 宣言型(declarative)
Gradle Build Scripts apply plugin: 'com.android.application' android { compileSdkVersion 21
buildToolsVersion '21.1.2' defaultConfig { versionCode 1 versionName '1.0' } buildTypes { release { minifyEnabled false } } } task hello { doLast { println 'ハローワールド!' } } • 設定ファイル:build.gradle • android プラグインを適用 • android プラグインの設定 • hello タスクを定義 • 宣言型(declarative) • 命令はプラグインがやる
Gradle Build Scripts apply plugin: 'com.android.application' android { compileSdkVersion 21
buildToolsVersion '21.1.2' defaultConfig { versionCode 1 versionName '1.0' } buildTypes { release { minifyEnabled false } } } task hello { doLast { println 'ハローワールド!' } } • 設定ファイル:build.gradle • android プラグインを適用 • android プラグインの設定 • hello タスクを定義 • 宣言型(declarative) • 命令はプラグインがやる • 言語:Gradle DSL ◦ Groovy 拡張
• JVMのスクリプト言語 • オブジェクト指向 • 動的言語 • Java ⊆ Groovy
ほぼ
Groovy:Java Class class JavaGreeter { public void sayHello() { System.out.println("Hello
Java!"); } } JavaGreeter greeter = new JavaGreeter() greeter.sayHello() // Hello Java!
Groovy /* 動的 ⇒ 型チェックはランタイムに。 型定義も任意。*/ def foo = 6.5
// String interpolation println "foo has value: $foo" // foo has value: 6.5 println "Let's do some math. 5 + 6 = ${5 + 6}" // Let's do some math. 5 + 6 = 11
Groovy /* 型変更可能 や 型の確認もできる */ println "foo is of
type: ${foo.class} and has value: $foo" // foo is of type: java.math.BigDecimal and has value: 6.5 foo = "a string" println "foo is now of type: ${foo.class} and has value: $foo" // foo is now of type: java.lang.String and has value: a string
Groovy /* セミコロン 不要 */ def doubleIt(n) { n +
n // return 不要 } foo = 5 println "doubleIt($foo) = ${doubleIt(foo)}" // doubleIt(5) = 10 println "${doubleIt('foobar')}" // foobarfoobar
/* 関数の呼び出しに括弧不要:引数が一つ以上かつ不明でなければ */ def noArgs() { println "Called the no
args function" } def oneArg(x) { x } def twoArgs(x, y) { x + y } oneArg 500 // 括弧なし twoArgs 200, 300 // 括弧なし noArgs // エラー noArgs() // 引数ないため括弧必須 twoArgs oneArg 500, 200 // 不明でエラー twoArgs oneArg(500), 200 // 正常
Groovy:Closure /* Closure:引数や変数に渡せるメソッド(メソッドポインター) */ def foo = "カレー" def myClosure
= { println "Closureからの$foo" } myClosure() // Closureからのカレー foo = "寿司" def bar = myClosure bar() // Closureからの寿司
Groovy:Closure /* Closure に引数を渡すとき */ def doubleIt = { x
-> x + x } def applyTwice(func, arg){ func(func(arg)) } println applyTwice(doubleIt, 2) // 8 ((2 + 2) + 4)
Groovy:List ✠ Closure def myList = ["カレー", "寿司", "コカ・コーラ"] def
printItem = {item -> println "List item: $item"} myList.each(printItem) // List item: カレー // List item: 寿司 // List item: コカ・コーラ /* インライン Closure */ myList.each { println "引数のデフォルト名は it : $it" }
Groovy:Class /* java Class の sugar */ class Restaurant {
String greeting = "いらっしゃい" def printGreeting() { println "Greeting: $greeting" } } def myRestaurant = new Restaurant() myRestaurant.printGreeting() // Greeting: いらっしゃい myRestaurant.greeting = "まいどおおきに" myRestaurant.printGreeting() // Greeting: まいどおおきに
Groovy:Delegate /* closure に delegate オブジェクトを定義できる。 closure に存在しないリファレンスは delegate に対して評価される
*/ def greetingClosure = { greeting = "またおまえか" printGreeting() } greetingClosure() // greeting が not defined でエラー greetingClosure.delegate = myRestaurant greetingClosure() // Greeting: またおまえか
Groovy • まだまだある。 ⇒ Learn Groovy in Y minutes. ◦
https://learnxinyminutes.com/docs/groovy/
Gradle:タスク定義 • build.gradle 全体の delegate は project オブ ジェクトになる。 ◦
project.task("A") ⇒ task("A") ◦ task("A") ⇒ task "A" ◦ task "A" ⇒ task A
Gradle:タスク定義 // build.gradle println "Script start" task A A.description =
"タスク一覧にでる説明文" A.group = "タスク一覧のヘッダーになる" A.doLast { println "Do last" } A.doFirst { println "Do first" } A.leftShift { println "Do leftShift" } A << { println "Do crazy leftShift" } println "Script end"
Gradle:設定 closure // Configuration Closure を利用 // Gradle は変数のセッターを用意してくれるので //
description = "" も可能で description("") も可能。 // 例外:List の場合は = で値を設定するしかない task A { description "タスク一覧にでる説明文" group "タスク一覧のヘッダーになる" doLast { println "Do last" } }
Gradle Task:依存関係 • dependsOn: 自分の実行前に実行する • finalizedBy: 自分の実行後に実行する • mustRunAfter:
実行順番を設定する • shouldRunAfter: 実行順番を設定する ◦ 無視される場合もある。例:循環が発生する時とか
Gradle Task:依存関係 デモ タイム Yeah? https://github.dev.cybozu.co.jp/benoit/gradle-benkyokai/tree/master/dependencies
Typed Task • タイプ無し:ad hoc task ◦ task myTask {}
• タイプ有り:typed task ◦ コアタスクを拡張するイメージ ◦ task myTask(type: aType) {}
Typed Task 例、ファイルをコピーするタスク: task copy(type: Copy) { description 'resourceフォルダをtargetフォルダへコピーする' from
'resources' into 'target' } ※宣言的:どうやってコピーするかは関係ない。
Incremental Builds • 対応済のものはスキップする方針。 • どうやって判断する? ◦ Inputsのスナップショット ▪ 変更ある
⇒ 実行 ▪ 変更ない ⇒ Outputs確認 ◦ Outputsのスナップショット ▪ 変更ある ⇒ 実行 ▪ 変更ない ⇒ UP_TO_DATE ⇒ スキップする
Parameterised Task • 3つのパラメータ種 ◦ CLI ◦ gradle.properties ◦ プロパティ拡張
※プロパティ拡張>CLI>.properties
CLI // build.gradle task hello << { println world }
# shell ./gradlew hello -Pworld=value # value
gradle.properties // build.gradle task hello << { println world }
# ./build.properties # ~/.gradle/build.properties world = "value" # shell ./gradlew hello
プロパティ拡張 // build.gradle task hello << { println world }
// 全ドメインオブジェクトに world を追加する ext { world = "value" } # shell ./gradlew hello
Custom Task Type デモ タイム Yeah? https://github.dev.cybozu.co.jp/benoit/gradle-benkyokai/tree/master/custom-type
Custom Task Type class MyTask extends DefaultTask { String feeling
@TaskAction void myAction() { println "話寿司 は ${feeling}" } } task sushi(type: MyTask) su.feeling "好き"
Logging Levels • println = quiet • エラー時 ◦ スタックトレースはでない
◦ stacktrace ⇒ -s ◦ full-stacktrace ⇒ -S ▪ Gradleコアまででる Debug Info Warning Lifecycle Error Quiet -q デフォルト -i -d
Build Lifecycle Initialization Configuration Execution • シングルPJもマルチPJ もあるため • ビルドにどのPJが絡ま
れるかを確認して • 各PJのインスタンスを 作成 • どのタスクがあるか • 依存確認などのため • 各PJのビルドスクリプト が実行される ◦ build.gradle • タスクが生成され • 設定される • 生成されたタスクを • 依存関係に従って • 順番に実行する
Gradle Plugin • コアGradleが提供している機能が少ない • Plugin でできる事を増やす事が可能 • モジュール化がやりやすい •
build.gradle は宣言のみにできる
Gradle Plugin:Type • Script Plugin ◦ 他gradleスクリプトをインクルードするイメージ ◦ 例:apply from:
'other.gradle' • Binary Plugin ◦ Plugin インターフェースを実装したクラス ◦ 例:apply plugin: 'java'
Java Plugin • 用意されているタスク ◦ コンパイル ◦ Jar ◦ ドキュメンテーション
◦ テスト ◦ レポート
Java Build Lifecycle build check test testClasses process Test Resources
compile Test Java assemble jar classes process Resources compile Java
Java Plugin デモ タイム Yeah? https://github.dev.cybozu.co.jp/benoit/gradle-benkyokai/tree/master/java-plugin
⇒ Java Plugin:Convention / src test java resources main java
resources / build reports classes main test build tests test-results
依存管理:Repo repositories { // ローカル flatDir { dirs 'libs' }
// 有名レポ mavenCentral() jcenter() mavenLocal() // ~/.m2/repository // url 指定、http, sftp, file:///... maven { url 'https://maven.fabric.io/public' } // 認証 ivy { url 'https://curry.yummy.com/ credentials { username 'user' password 'secret' } } }
依存管理:Repo repositories { // ローカル flatDir { dirs 'libs' }
// 有名レポ mavenCentral() jcenter() mavenLocal() // ~/.m2/repository // url 指定、http, sftp, file:///... maven { url 'https://maven.fabric.io/public' } // 認証 ivy { url 'https://curry.yummy.com/ credentials { username 'user' password 'secret' } } }
依存管理:Repo repositories { // ローカル flatDir { dirs 'libs' }
// 有名レポ mavenCentral() jcenter() mavenLocal() // ~/.m2/repository // url 指定、http, sftp, file:///... maven { url 'https://maven.fabric.io/public' } // 認証 ivy { url 'https://curry.yummy.com/ credentials { username 'user' password 'secret' } } }
依存管理:Repo repositories { // ローカル flatDir { dirs 'libs' }
// 有名レポ mavenCentral() jcenter() mavenLocal() // ~/.m2/repository // url 指定、http, sftp, file:///... maven { url 'https://maven.fabric.io/public' } // 認証 ivy { url 'https://curry.yummy.com/ credentials { username 'user' password 'secret' } } }
依存管理:Repo repositories { // ローカル flatDir { dirs 'libs' }
// 有名レポ mavenCentral() jcenter() mavenLocal() // ~/.m2/repository // url 指定、http, sftp, file:///... maven { url 'https://maven.fabric.io/public' } // 認証 ivy { url 'https://curry.yummy.com/ credentials { username 'user' password 'secret' } } }
依存管理:Repo repositories { // ローカル flatDir { dirs 'libs' }
// 有名レポ mavenCentral() jcenter() mavenLocal() // ~/.m2/repository // url 指定、http, sftp, file:///... maven { url 'https://maven.fabric.io/public' } // 認証 ivy { url 'https://curry.yummy.com/ credentials { username 'user' password 'secret' } } }
依存管理:Dep dependencies { // ファイル参照 compile files('libs/foo.jar', 'libs/bar.jar') // 他PJを参照
compile project(':someProject') // レポジトリから参照、長い版と省略 compile group: 'com.google.android', name:'android', version:'2.1.2' compile 'com.google.android:android:2.1.2' // テストビルド用 testCompile junit: 'junit:junit:4.12' }
依存管理:Dep dependencies { // ファイル参照 compile files('libs/foo.jar', 'libs/bar.jar') // 他PJを参照
compile project(':someProject') // レポジトリから参照、長い版と省略 compile group: 'com.google.android', name:'android', version:'2.1.2' compile 'com.google.android:android:2.1.2' // テストビルド用 testCompile junit: 'junit:junit:4.12' }
依存管理:Dep dependencies { // ファイル参照 compile files('libs/foo.jar', 'libs/bar.jar') // 他PJを参照
compile project(':someProject') // レポジトリから参照、長い版と省略 compile group: 'com.google.android', name:'android', version:'2.1.2' compile 'com.google.android:android:2.1.2' // テストビルド用 testCompile junit: 'junit:junit:4.12' }
依存管理:Dep dependencies { // ファイル参照 compile files('libs/foo.jar', 'libs/bar.jar') // 他PJを参照
compile project(':someProject') // レポジトリから参照、長い版と省略 compile group: 'com.google.android', name:'android', version:'2.1.2' compile 'com.google.android:android:2.1.2' // テストビルド用 testCompile junit: 'junit:junit:4.12' }
依存管理:Dep dependencies { // ファイル参照 compile files('libs/foo.jar', 'libs/bar.jar') // 他PJを参照
compile project(':someProject') // レポジトリから参照、長い版と省略 compile group: 'com.google.android', name:'android', version:'2.1.2' compile 'com.google.android:android:2.1.2' // テストビルド用 testCompile junit: 'junit:junit:4.12' }
依存管理:Dep dependencies { // ファイル参照 compile files('libs/foo.jar', 'libs/bar.jar') // 他PJを参照
compile project(':someProject') // レポジトリから参照、長い版と省略 compile group: 'com.google.android', name:'android', version:'2.1.2' compile 'com.google.android:android:2.1.2' // テストビルド用 testCompile junit: 'junit:junit:4.12' }
Dependencies Report ./gradlew dependencyInsight
Gradle:Dry Run -m $ ./gradlew -m assemble :compileJava SKIPPED :processResources
SKIPPED :classes SKIPPED :jar SKIPPED :assemble SKIPPED BUILD SUCCESSFUL
Gradle:Dry Run -m $ ./gradlew -m assemble :compileJava SKIPPED :processResources
SKIPPED :classes SKIPPED :jar SKIPPED :assemble SKIPPED BUILD SUCCESSFUL
Gradle Daemon • GradleはJVM上で動くので起動に時間かかる ◦ いくつかのライブラリも必要で更にかかる • Daemonを使う事でいろいろキャッシュされる • デフォルトで無効
◦ 3.0(8月15日〜) からデフォルトで有効 • CIでは無効するのがおすすめ ◦ gradle.properties:org.gradle.daemon=false
Gradle Android Plugin ? Not today
Gradle 入門 以上
Gradle 入門:Reference • Udacity コース ◦ https://www.udacity.com/course/gradle-for-android-and-java--ud867 • Gradle ◦
http://gradle.org/ • Gradle vs Maven ◦ https://gradle.org/maven_vs_gradle/ • デモのレポジトリ ◦ https://github.dev.cybozu.co.jp/benoit/gradle-benkyokai