Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Gradle入門
Search
Benoît Quenaudon
August 19, 2016
Programming
1
290
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
15
Instant Apps Eulogy
oldergod
1
7
36・15 Cash App
oldergod
1
240
Heuristics in Everyday Life
oldergod
1
16
Sweet Architecture
oldergod
1
420
Architecture at Scale (droidconNYC 2022)
oldergod
2
670
Managing gRPC with Wire
oldergod
2
610
Wire & Proto3
oldergod
0
100
Effective Reactive Architecture
oldergod
2
230
Other Decks in Programming
See All in Programming
【CA.ai #3】Google ADKを活用したAI Agent開発と運用知見
harappa80
0
310
これならできる!個人開発のすゝめ
tinykitten
PRO
0
100
Cap'n Webについて
yusukebe
0
130
認証・認可の基本を学ぼう後編
kouyuume
0
190
Rubyで鍛える仕組み化プロヂュース力
muryoimpl
0
120
Rediscover the Console - SymfonyCon Amsterdam 2025
chalasr
2
160
C-Shared Buildで突破するAI Agent バックテストの壁
po3rin
0
390
Context is King? 〜Verifiability時代とコンテキスト設計 / Beyond "Context is King"
rkaga
9
1.2k
AIコーディングエージェント(NotebookLM)
kondai24
0
190
DevFest Android in Korea 2025 - 개발자 커뮤니티를 통해 얻는 가치
wisemuji
0
140
AIコーディングエージェント(Manus)
kondai24
0
180
LLMで複雑な検索条件アセットから脱却する!! 生成的検索インタフェースの設計論
po3rin
3
720
Featured
See All Featured
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
54k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3k
A Modern Web Designer's Workflow
chriscoyier
698
190k
Designing Experiences People Love
moore
143
24k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Being A Developer After 40
akosma
91
590k
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.7k
Designing for humans not robots
tammielis
254
26k
The Pragmatic Product Professional
lauravandoore
37
7.1k
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