Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

@segunfamisa

Slide 3

Slide 3 text

Outline • Introduction • Scenarios & improvements #0, #1, #2 • Taking it a step further with Kotlin DSL • buildSrc • Migrating build scripts to Kotlin DSL from Groovy DSL • Kotlin DSL improvements • Custom Plugins • Resources

Slide 4

Slide 4 text

Improving your gradle experience

Slide 5

Slide 5 text

#0

Slide 6

Slide 6 text

Small project, single or few modules #0

Slide 7

Slide 7 text

// build.gradle apply plugin: 'com.android.application' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } #0

Slide 8

Slide 8 text

// build.gradle apply plugin: 'kotlin' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } // build.gradle apply plugin: 'com.android.application' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } #0

Slide 9

Slide 9 text

// build.gradle apply plugin: 'com.android.application' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } // build.gradle apply plugin: 'kotlin' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } #0

Slide 10

Slide 10 text

#0 // build.gradle apply plugin: 'com.android.application' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } // build.gradle apply plugin: 'kotlin' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } Managing dependencies versions becomes tedious

Slide 11

Slide 11 text

#0 - solution

Slide 12

Slide 12 text

#0 - solution Solving the duplication problem with Gradle extra (ext) properties feature

Slide 13

Slide 13 text

// dependencies.gradle ext { ... libraries = [ rxJavaVersion : '2.2.5' rxAndroidVersion : '2.1.0' kotlinVersion : '1.3.31' ] } 1. Externalize dependencies

Slide 14

Slide 14 text

1. Externalize dependencies 2. Apply dependencies.gradle to root project // root build.gradle buildScript {...} allprojects {...} apply from: 'relative/path/to/dependencies.gradle'

Slide 15

Slide 15 text

1. Externalize dependencies 2. Apply dependencies.gradle to root project 3. Reference the dependencies in the build.gradle files // build.gradle dependencies { ... def libs = rootProject.ext.libraries implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:rxjava:$libs.rxJavaVersion" }

Slide 16

Slide 16 text

1. Externalize dependencies 2. Apply dependencies.gradle to root project 3. Reference the dependencies in the build.gradle files // build.gradle dependencies { implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:rxjava:$libs.rxJavaVersion" } // build.gradle dependencies { ... def libs = rootProject.ext.libraries implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:...:$libs.rxJavaVersion" }

Slide 17

Slide 17 text

1. Externalize dependencies 2. Apply dependencies.gradle to root project 3. Reference the dependencies in the build.gradle files // build.gradle dependencies { implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:rxjava:$libs.rxJavaVersion" } // build.gradle dependencies { ... def libs = rootProject.ext.libraries implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:...:$libs.rxJavaVersion" }

Slide 18

Slide 18 text

• Managing/updating versions of dependencies is now easier - just need to change in one place • Still has the problem of duplication of dependencies

Slide 19

Slide 19 text

#1

Slide 20

Slide 20 text

#1 • Fairly complex projects • Multiple modules • You will find a lot of repetitions in the dependencies

Slide 21

Slide 21 text

#1 // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies }

Slide 22

Slide 22 text

#1 // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies }

Slide 23

Slide 23 text

#1 // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies }

Slide 24

Slide 24 text

#1 // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies }

Slide 25

Slide 25 text

#1 // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } Problem: Repeated declarations of dependencies in so many modules

Slide 26

Slide 26 text

#1 Solution: extract common/shared dependencies and apply to the modules

Slide 27

Slide 27 text

1. Extract common dependencies // shared-dependencies.gradle - contains all shared dependncies dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" ... testImplementation 'junit:junit:4.12' }

Slide 28

Slide 28 text

1. Extract common dependencies 2. Apply common dependencies to respective modules // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies }

Slide 29

Slide 29 text

1. Extract common dependencies 2. Apply common dependencies to respective modules // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies }

Slide 30

Slide 30 text

1. Extract common dependencies 2. Apply common dependencies to respective modules // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies }

Slide 31

Slide 31 text

1. Extract common dependencies 2. Apply common dependencies to respective modules // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies }

Slide 32

Slide 32 text

• Managing shared dependencies becomes easier • Eliminates repeated declaration of dependencies

Slide 33

Slide 33 text

#2

Slide 34

Slide 34 text

#2 • Fairly complex projects • Multiple modules • You will find a lot of repetitions in the configurations of the modules

Slide 35

Slide 35 text

#2

Slide 36

Slide 36 text

#2 // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} }

Slide 37

Slide 37 text

#2 // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig { minSdkVersion sdk.minSdkVersion targetSdkVersion sdk.targetSdkVersion versionCode 198828 versionName "1.5.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles 'consumer-rules.pro' ... } buildTypes {...} }

Slide 38

Slide 38 text

#2 // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes { debug { minifyEnabled ... proguardFiles ... } release { minifyEnabled ... proguardFiles ... } } }

Slide 39

Slide 39 text

#2 // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} }

Slide 40

Slide 40 text

#2 // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} } // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} }

Slide 41

Slide 41 text

#2 // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} } // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} } // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} }

Slide 42

Slide 42 text

#2 // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} } // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} } // build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} } Problem: Repeated configuration in so many modules

Slide 43

Slide 43 text

1. Extract common configuration into separate file https://handstandsam.com/2019/03/12/sharing-gradle-configuration-in-multi-module-android-projects/ // common-android-config.gradle apply plugin: 'kotlin-android' android { compileSdkVersion sdk.compileSdkVersion defaultConfig { minSdkVersion sdk.minSdkVersion targetSdkVersion sdk.targetSdkVersion versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } } Further reading:

Slide 44

Slide 44 text

1. Extract common configuration into separate file https://handstandsam.com/2019/03/12/sharing-gradle-configuration-in-multi-module-android-projects/ Further reading: 2. Apply config to android modules // build.gradle apply from: "$rootProject.projectDir/common-android-config.gradle" ...

Slide 45

Slide 45 text

• Eliminates repeated configuration of common build logic • Same applies to other common configuration you may have across multiple modules. https://handstandsam.com/2019/03/12/sharing-gradle-configuration-in-multi-module-android-projects/ Further reading:

Slide 46

Slide 46 text

Taking it even further with Kotlin DSL

Slide 47

Slide 47 text

Why Kotlin DSL? • Kotlin is now really popular • Same language for code & build logic

Slide 48

Slide 48 text

Why Kotlin DSL? • Kotlin is now really popular • Same language for code & build logic • Better IDE support for build scripts in Kotlin. • Jump to declaration, syntax highlighting, etc

Slide 49

Slide 49 text

buildSrc • Gradle allows us create a module to add complex build related logic - like plugins, custom tasks, etc.

Slide 50

Slide 50 text

buildSrc • Gradle allows us create a module to add complex build related logic - like plugins, custom tasks, etc. • It’s a regular module with it’s own: • build.gradle.kts • src/main/java or src/main/kotlin

Slide 51

Slide 51 text

Adding dependencies versions to buildSrc Anatomy of the buildSrc module for dependencies versioning

Slide 52

Slide 52 text

dependencies.gradle -> dependencies.kt // build.gradle.kts plugins { `kotlin-dsl` } repositories { jcenter() }

Slide 53

Slide 53 text

dependencies.gradle -> dependencies.kt // Dependencies.kt object SdkVersions { const val compileSdkVersion = 28 const val minSdkVersion = 21 const val targetSdkVersion = 28 } object Deps { const val kotlinStdLib = “org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41" const val gson = “com.google.code.gson:gson:2.8.5" ... object Rx { const val rxJava2 = "io.reactivex.rxjava2:rxjava:2.2.10" const val rxAndroid = "io.reactivex.rxjava2:rxandroid:2.1.1" } ... }

Slide 54

Slide 54 text

dependencies.gradle -> dependencies.kt // Dependencies.kt object SdkVersions { const val compileSdkVersion = 28 const val minSdkVersion = 21 const val targetSdkVersion = 28 } object Deps { const val kotlinStdLib = “org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41" const val gson = “com.google.code.gson:gson:2.8.5" ... object Rx { const val rxJava2 = "io.reactivex.rxjava2:rxjava:2.2.10" const val rxAndroid = "io.reactivex.rxjava2:rxandroid:2.1.1" } ... }

Slide 55

Slide 55 text

dependencies.gradle -> dependencies.kt // Dependencies.kt object Deps { const val kotlinStdLib = “org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41" const val gson = “com.google.code.gson:gson:2.8.5" } // Usage in build.gradle dependencies { implementation Deps.kotlinStdLib implementation Deps.gson ... }

Slide 56

Slide 56 text

dependencies.gradle -> dependencies.kt // Dependencies.kt object Deps { const val kotlinStdLib = “org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41" const val gson = “com.google.code.gson:gson:2.8.5" } // Usage in build.gradle dependencies { implementation Deps.kotlinStdLib implementation Deps.gson ... } Syntax highlighting ✅ “Jump to declaration” ✅

Slide 57

Slide 57 text

Kotlin DSL prerequisites • Gradle 5.0 • Java 8

Slide 58

Slide 58 text

Tips for migrating to Kotlin DSL

Slide 59

Slide 59 text

Tips for migrating to Kotlin DSL 1. <file.gradle> becomes <file.gradle.kts> 2. Single quotes become double quotes 3. Property assignments should have assignment operator ‘=‘ 4. Function calls should have parenthes

Slide 60

Slide 60 text

Migrating an Android project

Slide 61

Slide 61 text

// settings.gradle include ':app', ':data', ':domain'

Slide 62

Slide 62 text

// settings.gradle include ':app', ':data', ':domain' // settings.gradle.kts include(":app", ":data", ":domain")

Slide 63

Slide 63 text

// settings.gradle include ':app', ':data', ':domain' // settings.gradle.kts include(":app", ":data", ":domain") ’:app’ becomes “:app” include becomes include()

Slide 64

Slide 64 text

// app-level build.gradle

Slide 65

Slide 65 text

// app-level build.gradle apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android { compileSdkVersion 28 defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }

Slide 66

Slide 66 text

// app-level build.gradle.kts apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android { compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode = 1 versionName = "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro') } } } dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31") implementation("androidx.appcompat:appcompat:1.0.2") }

Slide 67

Slide 67 text

What changed? apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android { compileSdkVersion 28 defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }

Slide 68

Slide 68 text

What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android { compileSdkVersion 28 defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }

Slide 69

Slide 69 text

What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android { compileSdkVersion 28 defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }

Slide 70

Slide 70 text

What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android { compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }

Slide 71

Slide 71 text

What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android { compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }

Slide 72

Slide 72 text

What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android { compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile(‘...’), 'proguard-rules.pro') } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }

Slide 73

Slide 73 text

What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android { compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile(‘...’), 'proguard-rules.pro') } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }

Slide 74

Slide 74 text

What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android { compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile(‘...’), 'proguard-rules.pro') } } } dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31") implementation("androidx.appcompat:appcompat:1.0.2") }

Slide 75

Slide 75 text

// app-level build.gradle.kts apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android { compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode = 1 versionName = "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro') } } } dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31") implementation("androidx.appcompat:appcompat:1.0.2") }

Slide 76

Slide 76 text

// top-level build.gradle

Slide 77

Slide 77 text

// top-level build.gradle buildscript { ext.kotlin_version = '1.3.31' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() jcenter() } }

Slide 78

Slide 78 text

// top-level build.gradle.kts buildscript { extra.apply { set("kotlin_version", "1.3.31") } repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.4.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${extras.get("kotlin_version")}) } } allprojects { repositories { google() jcenter() } }

Slide 79

Slide 79 text

What changed?

Slide 80

Slide 80 text

// top-level build.gradle buildscript { ext.kotlin_version = '1.3.31' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() jcenter() } } What changed?

Slide 81

Slide 81 text

What changed? // top-level build.gradle.kts buildscript { extra.apply { set("kotlin_version", "1.3.31") } repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.4.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${extras.get("kotlin_version")}) } } allprojects { repositories { google() jcenter() } }

Slide 82

Slide 82 text

// top-level build.gradle buildscript { extra.apply { set("kotlin_version", "1.3.31") } repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() jcenter() } } What changed?

Slide 83

Slide 83 text

// top-level build.gradle.kts buildscript { extra.apply { set("kotlin_version", "1.3.31") } repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.4.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${extras.get("kotlin_version")}) } } allprojects { repositories { google() jcenter() } } What changed?

Slide 84

Slide 84 text

// top-level build.gradle.kts buildscript { extra.apply { set("kotlin_version", "1.3.31") } repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.4.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${extras.get("kotlin_version")}) } } allprojects { repositories { google() jcenter() } }

Slide 85

Slide 85 text

Custom Gradle Plugin

Slide 86

Slide 86 text

Custom Gradle Plugin • We could use a custom plugin to apply common configuration across multiple modules

Slide 87

Slide 87 text

class AwesomePlugin : Plugin { override fun apply(project: Project) { ... } }

Slide 88

Slide 88 text

class AwesomePlugin : Plugin { override fun apply(project: Project) { with(project) { project.plugins.all { when (this) { is AppPlugin, is LibraryPlugin -> extensions.getByType().apply { configureAndroidModule(extension = this, project = project) } } } } } }

Slide 89

Slide 89 text

class AwesomePlugin : Plugin { override fun apply(project: Project) { with(project) { project.plugins.all { when (this) { is AppPlugin, is LibraryPlugin -> extensions.getByType().apply { configureAndroidModule(extension = this, project = project) } } } } } }

Slide 90

Slide 90 text

class AwesomePlugin : Plugin { override fun apply(project: Project) { with(project) { project.plugins.all { when (this) { is AppPlugin, is LibraryPlugin -> extensions.getByType().apply { configureAndroidModule(extension = this, project = project) } } } } } }

Slide 91

Slide 91 text

private fun TestedExtension.configureAndroidModule(project: Project) { }

Slide 92

Slide 92 text

private fun TestedExtension.configureAndroidModule(project: Project) { setCompileSdkVersion(28) defaultConfig.apply { minSdkVersion(21) targetSdkVersion(28) compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } } ... }

Slide 93

Slide 93 text

Apply new plugin to all modules plugins { id("com.android.application") kotlin("android") kotlin("android.extensions") } apply { from("${rootProject.projectDir}/shared-dependencies.gradle") } apply() ...

Slide 94

Slide 94 text

Current pain points with Kotlin DSL

Slide 95

Slide 95 text

Current pain points with Kotlin DSL • IDE support is not yet at

Slide 96

Slide 96 text

Current pain points with Kotlin DSL • IDE support is not yet at • Additional configuration time in your build process

Slide 97

Slide 97 text

Current pain points with Kotlin DSL • IDE support is not yet at • Additional configuration time in your build process • Applying config from an external gradle.kts file doesn’t quite work: • You either have to leave as .gradle files or follow another work-around (see: https://github.com/gradle/kotlin-dsl/issues/1287)

Slide 98

Slide 98 text

Current pain points with Kotlin DSL • IDE support is not yet at • Additional configuration time in your build process • Applying config from an external gradle.kts file doesn’t quite work: • You either have to leave as .gradle files or follow another work-around (see: https://github.com/gradle/kotlin-dsl/issues/1287) • Weird, but sometimes, some things in the plugin show a compiler warning, but it actually works

Slide 99

Slide 99 text

Final words

Slide 100

Slide 100 text

Final words • Keep it DRY (Don’t Repeat Yourself) - rule of three applies here

Slide 101

Slide 101 text

Final words • Keep it DRY (Don’t Repeat Yourself) - rule of three applies here • Modular code rocks

Slide 102

Slide 102 text

Final words • Keep it DRY (Don’t Repeat Yourself) - rule of three applies here • Modular code rocks • Take advantage of IDE support with Kotlin DSL

Slide 103

Slide 103 text

Resources https://handstandsam.com/2019/03/12/sharing-gradle-configuration-in-multi-module-android-projects/ https://segunfamisa.com/posts/android-gradle-extra-properties https://gradle.com/blog/getting-started-with-gradle-kotlin-dsl/ https://github.com/gradle/kotlin-dsl Build Bigger, Better: Gradle for Large Projects (Google I/O'19)

Slide 104

Slide 104 text

Thanks! Segun Famisa, Android GDE