Share
Embed
Managing Multi-module Android Project with Gradle Plugin and Kotlin
In this talk, I will discuss how the Gradle plugin works, and how we can write a custom plugin in Kotlin to help us manage an Android multi-module project. I will also present techniques to provide custom configurations in our Gradle plugin so that we can modify our build depending on the module, and further, extend the plugin's capabilities by integrating it with other Gradle plugins; e.g., Jacoco plugin. Lastly, I will share our experience of building a Gradle plugin and explore the benefits and limitations that I've encountered.
Malvin Sutanto
December 15, 2020
Transcript
189 slides
-
©2020 Wantedly, Inc. Managing Multi-module Project with Gradle Plugin and
Kotlin .droidcon APAC 2020 15 Dec 2020 - Malvin Sutanto Photo by Jan Antonin Kolar on Unsplash -
©2020 Wantedly, Inc. Introduction Malvin Sutanto Software Engineer - Android
Twitter/ Medium: @malvinsutanto -
©2020 Wantedly, Inc. BQQ MJCOBWJHBUJPO QSFGFSFODFT MJCBOBMZUJDT EBUB OFUXPSL GFBUVSFTFBSDI
GFBUVSFVTFS Multi module setup in Android -
©2020 Wantedly, Inc. BQQ MJCOBWJHBUJPO QSFGFSFODFT MJCBOBMZUJDT EBUB OFUXPSL GFBUVSFTFBSDI
GFBUVSFVTFS Multi module setup in Android -
©2020 Wantedly, Inc. Multi module setup in Android • Faster
build time • Easier to manage and work with -
©2020 Wantedly, Inc. Multi module setup in Android • Faster
build time • Easier to manage and work with • New features • Instant apps • Dynamic feature modules -
©2020 Wantedly, Inc. • Each module need a build.gradle file
Multi module setup in Android -
©2020 Wantedly, Inc. • Each module need a build.gradle file
• Duplicate build script across modules Multi module setup in Android -
©2020 Wantedly, Inc. • Each module need a build.gradle file
• Duplicate build script across modules • Build files became hard to maintain Multi module setup in Android -
©2020 Wantedly, Inc. build.gradle file for a library module Multi
module setup in Android plugins { id 'com.android.library' id 'kotlin-android' } android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android.material:material:1.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } -
©2020 Wantedly, Inc. build.gradle file for a library module Multi
module setup in Android plugins { id 'com.android.library' id 'kotlin-android' } android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android.material:material:1.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } • Declares Gradle plugins • Sets build parameters • Declares dependencies -
©2020 Wantedly, Inc. What is Gradle? • “Generic” build automation
tool • Declares input and output files -
©2020 Wantedly, Inc. What is Gradle? • “Generic” build automation
tool • Declares input and output files • Tasks as its core -
©2020 Wantedly, Inc. Gradle Build phases Gradle build phases *OJUJBMJ[BUJPO
$POpHVSBUJPO &YFDVUJPO -
©2020 Wantedly, Inc. build.gradle file Domain Specific Language (DSL) plugins
{ id 'com.android.library' id 'kotlin-android' } android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android.material:material:1.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } • Configuration file • Describes build steps • Available in Groovy and Kotlin Gradle Build.gradle file -
©2020 Wantedly, Inc. build.gradle file Domain Specific Language (DSL) plugins
{ id 'com.android.library' id 'kotlin-android' } android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android.material:material:1.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } • Configuration file • Describes build steps • Available in Groovy and Kotlin Extension block Gradle Build.gradle file -
©2020 Wantedly, Inc. build.gradle file Domain Specific Language (DSL) plugins
{ id 'com.android.library' id 'kotlin-android' } android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android.material:material:1.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } • Configuration file • Describes build steps • Available in Groovy and Kotlin Gradle plugins Extension block Gradle Build.gradle file -
©2020 Wantedly, Inc. Gradle Plugin • Extends the Gradle model
• Adds new configuration block and options -
©2020 Wantedly, Inc. Gradle Plugin • Extends the Gradle model
• Adds new configuration block and options • Configures project according conventions • Adds new tasks • Configures sensible defaults -
©2020 Wantedly, Inc. Gradle Plugin • Extends the Gradle model
• Adds new configuration block and options • Configures project according conventions • Adds new tasks • Configures sensible defaults • Applies specific configuration • Enforces standards -
©2020 Wantedly, Inc. Script plugin • Additional build script that
is located separately. • Can exist in local filesystem or remote location. • Multiple script plugins can be applied. • apply from: 'other.gradle' Types of Gradle Plugin Gradle Plugin -
©2020 Wantedly, Inc. Script plugin • Additional build script that
is located separately. • Can exist in local filesystem or remote location. • Multiple script plugins can be applied. • apply from: 'other.gradle' Binary plugin • Written programmatically by implementing Plugin interface, • Applied using unique plugin id • plugins { id 'com.android.library' id 'kotlin-android' } Types of Gradle Plugin Gradle Plugin -
©2020 Wantedly, Inc. Script plugin • Additional build script that
is located separately. • Can exist in local filesystem or remote location. • Multiple script plugins can be applied. • apply from: 'other.gradle' Binary plugin • Written programmatically by implementing Plugin interface, • Applied using unique plugin id • plugins { id 'com.android.library' id 'kotlin-android' } Types of Gradle Plugin Gradle Plugin -
©2020 Wantedly, Inc. What will the plugin do? For each
module, it will: Gradle Plugin -
©2020 Wantedly, Inc. • Apply other Gradle plugins What will
the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files • Enable Java 8 features What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files • Enable Java 8 features • Declare dependencies What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files • Enable Java 8 features • Declare dependencies • Configure Jacoco and custom extensions What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. plugins { id("com.android.library") // or .application id("my-custom-plugin-id")
} android { buildTypes { getByName("debug") { isTestCoverageEnabled = true } } } myPluginOptions { jacoco { isEnabled = true } } dependencies { … } my-lib/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { id("com.android.library") // or .application id("my-custom-plugin-id")
} android { buildTypes { getByName(“debug") { isTestCoverageEnabled = true } } } myPluginOptions { jacoco { isEnabled = true } } dependencies { … } my-lib/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { id("com.android.library") // or .application id("my-custom-plugin-id")
} android { buildTypes { getByName(“debug") { isTestCoverageEnabled = true } } } myPluginOptions { jacoco { isEnabled = true } } dependencies { … } my-lib/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { id("com.android.library") // or .application id("my-custom-plugin-id")
} android { buildTypes { getByName(“debug") { isTestCoverageEnabled = true } } } myPluginOptions { jacoco { isEnabled = true } } dependencies { … } my-lib/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { id("com.android.library") // or .application id("my-custom-plugin-id")
} android { buildTypes { getByName(“debug") { isTestCoverageEnabled = true } } } myPluginOptions { jacoco { isEnabled = true } } dependencies { … } my-lib/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { id("com.android.library") id("my-custom-plugin-id") } android {
buildTypes { getByName(“debug") { isTestCoverageEnabled = true } } } myPluginOptions { jacoco { isEnabled = true } } dependencies { … } my-lib/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { id("com.android.library") id("my-custom-plugin-id") } android {
buildTypes { getByName(“debug") { isTestCoverageEnabled = true } } } myPluginOptions { jacoco { isEnabled = true } } dependencies { … } plugins { id 'com.android.library' id 'kotlin-android' } android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android.material:material:1.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } my-lib/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. my-project/ - buildSrc/ - build.gradle.kts - src/main/kotlin/com/mypackage/
- MyCustomPlugin.kt - app/ - my-lib/ Project Structure Gradle Plugin -
©2020 Wantedly, Inc. my-project/ - buildSrc/ - build.gradle.kts - src/main/kotlin/com/mypackage
- MyCustomPlugin.kt - app/ - my-lib/ Project Structure Gradle Plugin -
©2020 Wantedly, Inc. buildSrc/src/build.gradle.kts plugins { `java-gradle-plugin` `kotlin-dsl` } repositories
{ google() mavenCentral() } dependencies { implementation("com.android.tools.build:gradle:$agpVersion") implementation(kotlin("gradle-plugin")) } Gradle Plugin -
©2020 Wantedly, Inc. plugins { `java-gradle-plugin` `kotlin-dsl` } repositories {
google() mavenCentral() } dependencies { implementation("com.android.tools.build:gradle:$agpVersion") implementation(kotlin("gradle-plugin")) } buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { `java-gradle-plugin` `kotlin-dsl` } repositories {
google() mavenCentral() } dependencies { implementation("com.android.tools.build:gradle:$agpVersion") implementation(kotlin("gradle-plugin")) } buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { `java-gradle-plugin` `kotlin-dsl` } repositories {
google() mavenCentral() } dependencies { implementation("com.android.tools.build:gradle:$agpVersion") implementation(kotlin("gradle-plugin")) } buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { `java-gradle-plugin` `kotlin-dsl` } repositories {
google() mavenCentral() } dependencies { implementation("com.android.tools.build:gradle:$agpVersion") implementation(kotlin("gradle-plugin")) } buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { `java-gradle-plugin` `kotlin-dsl` } repositories {
google() mavenCentral() } dependencies { implementation("com.android.tools.build:gradle:$agpVersion") implementation(kotlin("gradle-plugin")) } https://android-developers.googleblog.com/2020/12/announcing-android-studio-arctic-fox.html buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. my-project/ - buildSrc/ - build.gradle.kts - src/main/kotlin/com/mypackage/
- MyCustomPlugin.kt - app/ - my-lib/ Project Structure Gradle Plugin -
©2020 Wantedly, Inc. Gradle Plugin class MyCustomPlugin : Plugin<Project> {
buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. Gradle Plugin class MyCustomPlugin : Plugin<Project> {
Module buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. Gradle Plugin class MyCustomPlugin : Plugin<Project> {
override fun apply(project: Project) { // TODO: Write build configurations here. } } Module buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files • Enable Java 8 features • Declare dependencies • Configure Jacoco and custom extensions What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. override fun apply(project: Project) { Gradle Plugin
buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { project.plugins.apply("kotlin-android") }
Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { project.plugins.apply("kotlin-android") }
Plugin id // build.gradle plugins { id 'com.android.library' id 'kotlin-android' } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files • Enable Java 8 features • Declare dependencies • Configure Jacoco and custom extensions What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. override fun apply(project: Project) { … val
androidExtension = project.extensions.getByName("android") if (androidExtension is BaseExtension) { androidExtension.applyAndroidSettings() } } private fun BaseExtension.applyAndroidSettings() { compileSdkVersion(30) defaultConfig { targetSdkVersion(30) minSdkVersion(23) // etc. } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { … val
androidExtension = project.extensions.getByName("android") if (androidExtension is BaseExtension) { androidExtension.applyAndroidSettings() } } private fun BaseExtension.applyAndroidSettings() { compileSdkVersion(30) defaultConfig { targetSdkVersion(30) minSdkVersion(23) // etc. } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { … val
androidExtension = project.extensions.getByName("android") if (androidExtension is BaseExtension) { androidExtension.applyAndroidSettings() } } private fun BaseExtension.applyAndroidSettings() { compileSdkVersion(30) defaultConfig { targetSdkVersion(30) minSdkVersion(23) // etc. } } // build.gradle android { compileSdkVersion 30 defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { … val
androidExtension = project.extensions.getByName("android") if (androidExtension is BaseExtension) { androidExtension.applyAndroidSettings() } } private fun BaseExtension.applyAndroidSettings() { compileSdkVersion(30) defaultConfig { targetSdkVersion(30) minSdkVersion(23) // etc. } } // build.gradle android { compileSdkVersion 30 defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { … val
androidExtension = project.extensions.getByName("android") if (androidExtension is BaseExtension) { androidExtension.applyAndroidSettings() } } private fun BaseExtension.applyAndroidSettings() { compileSdkVersion(30) defaultConfig { targetSdkVersion(30) minSdkVersion(23) // etc. } } // build.gradle android { compileSdkVersion 30 defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" } } Base class for all Android plugin extension classes Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { … val
androidExtension = project.extensions.getByName("android") if (androidExtension is BaseExtension) { androidExtension.applyAndroidSettings() } } private fun BaseExtension.applyAndroidSettings() { compileSdkVersion(30) defaultConfig { targetSdkVersion(30) minSdkVersion(23) // etc. } } // build.gradle android { compileSdkVersion 30 defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { … val
androidExtension = project.extensions.getByName("android") if (androidExtension is BaseExtension) { androidExtension.applyAndroidSettings() } } private fun BaseExtension.applyAndroidSettings() { compileSdkVersion(30) defaultConfig { targetSdkVersion(30) minSdkVersion(23) // etc. } } // build.gradle android { compileSdkVersion 30 defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files • Enable Java 8 features • Declare dependencies • Configure Jacoco and custom extensions What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. Application module • Set isMinifyEnabled only on
release Library module id("com.android.application") id("com.android.library") Types of plugin Gradle Plugin -
©2020 Wantedly, Inc. Application module • Set isMinifyEnabled only on
release • Specify proguard files using proguardFiles() Library module id("com.android.application") id("com.android.library") Types of plugin Gradle Plugin -
©2020 Wantedly, Inc. Application module • Set isMinifyEnabled only on
release • Specify proguard files using proguardFiles() Library module • Specify proguard files using consumerProguardFiles() id("com.android.application") id("com.android.library") Types of plugin Gradle Plugin -
©2020 Wantedly, Inc. override fun apply(project: Project) { … val
androidExtension = project.extensions.getByName(“android") if (androidExtension is BaseExtension) { androidExtension.applyAndroidSettings() androidExtension.applyProguardSettings() } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } proguard-rules.pro files in each module’s root Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } // build.gradle plugins { id 'com.android.library' id 'my-custom-plugin-id' } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } // build.gradle plugins { id 'com.android.library' id 'my-custom-plugin-id' } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } // build.gradle plugins { id 'com.android.library' id 'my-custom-plugin-id' } // build.gradle android { defaultConfig { ... consumerProguardFiles "proguard-rules.pro" } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } // build.gradle plugins { id 'com.android.application' id 'my-custom-plugin-id' } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } Enable obfuscation only on "release" build // build.gradle plugins { id 'com.android.application' id 'my-custom-plugin-id' } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.applyProguardSettings() { val proguardFile =
"proguard-rules.pro" when (this) { is LibraryExtension -> defaultConfig { consumerProguardFiles(proguardFile) } is AppExtension -> buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), proguardFile ) } } } } Enable obfuscation only on "release" build // build.gradle plugins { id 'com.android.application' id 'my-custom-plugin-id' } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files • Enable Java 8 features • Declare dependencies • Configure Jacoco and custom extensions What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. override fun apply(project: Project) { … val
androidExtension = project.extensions.getByName("android") if (androidExtension is BaseExtension) { ... androidExtension.enableJava8(project) } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.enableJava8(project: Project) { compileOptions {
isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } project.tasks.withType<KotlinCompile>().configureEach { kotlinOptions { jvmTarget = "1.8" } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.enableJava8(project: Project) { compileOptions {
isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } project.tasks.withType<KotlinCompile>().configureEach { kotlinOptions { jvmTarget = "1.8" } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.enableJava8(project: Project) { compileOptions {
isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } project.tasks.withType<KotlinCompile>().configureEach { kotlinOptions { jvmTarget = "1.8" } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.enableJava8(project: Project) { compileOptions {
isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } project.tasks.withType<KotlinCompile>().configureEach { kotlinOptions { jvmTarget = "1.8" } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.enableJava8(project: Project) { compileOptions {
isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } project.tasks.withType<KotlinCompile>().configureEach { kotlinOptions { jvmTarget = "1.8" } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.enableJava8(project: Project) { compileOptions {
isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } project.tasks.withType<KotlinCompile>().configureEach { kotlinOptions { jvmTarget = "1.8" } } } Java 8 core library desugaring Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files • Enable Java 8 features • Declare dependencies • Configure Jacoco and custom extensions What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. private fun BaseExtension.enableJava8(project: Project) { compileOptions {
isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } project.dependencies { add("coreLibraryDesugaring", "com.android.tools:desugar_jdk_libs:1.0.9") } ... } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.enableJava8(project: Project) { compileOptions {
isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } project.dependencies { add("coreLibraryDesugaring", "com.android.tools:desugar_jdk_libs:1.0.9") } ... } Configuration name Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. project.dependencies { add("implementation", "androidx.core:core-ktx:1.2.0") add("testImplementation", "junit:junit:4.12") add("androidTestImplementation",
"androidx.test.ext:junit:1.1.1") } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. • Apply other Gradle plugins • Set
common build parameters • Specify default proguard files • Enable Java 8 features • Declare dependencies • Configure Jacoco and custom extensions What will the plugin do? Gradle Plugin -
©2020 Wantedly, Inc. plugins { id("com.android.library") // or .application id("my-custom-plugin-id")
} android { buildTypes { getByName("debug") { isTestCoverageEnabled = true } } } myPluginOptions { jacoco { isEnabled = true } } dependencies { … } my-lib/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { id("com.android.library") // or .application id("my-custom-plugin-id")
} android { buildTypes { getByName("debug") { isTestCoverageEnabled = true } } } myPluginOptions { jacoco { isEnabled = true } } dependencies { … } my-lib/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. override fun apply(project: Project) { project.extensions.create<MyPluginOptionExtension>("myPluginOptions") …
if (androidExtension is BaseExtension) { … androidExtension.configureJacoco(project) } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { project.extensions.create<MyPluginOptionExtension>("myPluginOptions") …
if (androidExtension is BaseExtension) { … androidExtension.configureJacoco(project) } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { project.extensions.create<MyPluginOptionExtension>("myPluginOptions") …
if (androidExtension is BaseExtension) { … androidExtension.configureJacoco(project) } } Extension class Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { project.extensions.create<MyPluginOptionExtension>("myPluginOptions") …
if (androidExtension is BaseExtension) { … androidExtension.configureJacoco(project) } } Extension class // build.gradle.kts myPluginOptions { jacoco { isEnabled = true } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. open class MyPluginOptionExtension { val jacoco: JacocoOptions
= JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. open class MyPluginOptionExtension { val jacoco: JacocoOptions
= JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. open class MyPluginOptionExtension { val jacoco: JacocoOptions
= JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. open class MyPluginOptionExtension { val jacoco: JacocoOptions
= JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. open class MyPluginOptionExtension { val jacoco: JacocoOptions
= JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. open class MyPluginOptionExtension { val jacoco: JacocoOptions
= JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. // build.gradle.kts myPluginOptions { jacoco { isEnabled
= true } } open class MyPluginOptionExtension { val jacoco: JacocoOptions = JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } // build.gradle myPluginOptions { jacoco { enabled true } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. open class MyPluginOptionExtension { val jacoco: JacocoOptions
= JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } // build.gradle.kts myPluginOptions { jacoco { isEnabled = true } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. open class MyPluginOptionExtension { val jacoco: JacocoOptions
= JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } // build.gradle.kts myPluginOptions { jacoco { isEnabled = true } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. open class MyPluginOptionExtension { val jacoco: JacocoOptions
= JacocoOptions() fun jacoco(action: Action<JacocoOptions>) { action.execute(jacoco) } } class JacocoOptions { var isEnabled: Boolean = true } // build.gradle.kts myPluginOptions { jacoco { isEnabled = true } } https://docs.gradle.org/current/userguide/custom_gradle_types.html https://docs.gradle.org/current/userguide/lazy_configuration.html#lazy_configuration Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyPluginOptionExtension.kt -
©2020 Wantedly, Inc. override fun apply(project: Project) { project.extensions.create<MyPluginOptionExtension>("myPluginOptions") …
if (androidExtension is BaseExtension) { … androidExtension.configureJacoco(project) } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } // build.gradle.kts myPluginOptions { jacoco { isEnabled = true } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } "debug" "release" Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun BaseExtension.configureJacoco(project: Project) { project.afterEvaluate {
val jacocoOptions = project.extensions.getByType<MyPluginOptionExtension>() .jacoco if (jacocoOptions.isEnabled) { project.plugins.apply("jacoco") when (this@configureJacoco) { is LibraryExtension -> configureJacocoTasks(project, libraryVariants) is AppExtension -> configureJacocoTasks(project, applicationVariants) } } } } private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out BaseVariant> ) { ... } "debug" "release" "debug" "release" "flavorDebug" "flavorRelease" Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } Skip non-debuggable builds Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } "debug" "release" "flavorDebug" "flavorRelease" Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } "debug" "release" "flavorDebug" "flavorRelease" Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } ./gradlew :lib:jacocoDebugReport ./gradlew :app:jacocoFlavorDebugReport "debug" "release" "flavorDebug" "flavorRelease" Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. private fun configureJacocoTasks( project: Project, variants: DomainObjectSet<out
BaseVariant> ) { variants.all { val variantName = name val isDebuggable = buildType.isDebuggable if (!isDebuggable) return@all project.tasks.register<JacocoReport>("jacoco${variantName.capitalize()}Report") { // Set up the rest of the Jacoco tasks dependency, exec files, etc. } } } Gradle Plugin buildSrc/src/main/kotlin/com/mypackage/MyCustomPlugin.kt -
©2020 Wantedly, Inc. plugins { ... } gradlePlugin { plugins
{ register("my-custom-plugin") { id = "my-custom-plugin-id" implementationClass = "com.mypackage.MyCustomPlugin" } } } repositories { ... } dependencies { ... } buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { ... } gradlePlugin { plugins
{ register("my-custom-plugin") { id = "my-custom-plugin-id" implementationClass = "com.mypackage.MyCustomPlugin" } } } repositories { ... } dependencies { ... } buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { ... } gradlePlugin { plugins
{ register("my-custom-plugin") { id = "my-custom-plugin-id" implementationClass = "com.mypackage.MyCustomPlugin" } } } repositories { ... } dependencies { ... } buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { ... } gradlePlugin { plugins
{ register("my-custom-plugin") { id = "my-custom-plugin-id" implementationClass = "com.mypackage.MyCustomPlugin" } } } repositories { ... } dependencies { ... } // lib/build.gradle.kts plugins { id("com.android.library") id("my-custom-plugin-id") } buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. plugins { ... } gradlePlugin { plugins
{ register("my-custom-plugin") { id = "my-custom-plugin-id" implementationClass = "com.mypackage.MyCustomPlugin" } } } repositories { ... } dependencies { ... } // lib/build.gradle.kts plugins { id("com.android.library") id("my-custom-plugin-id") } class MyCustomPlugin : Plugin<Project> { ... } buildSrc/src/build.gradle.kts Gradle Plugin -
©2020 Wantedly, Inc. Benefits • Share build logic across modules
• Reduce maintenance cost when updating build scripts Gradle Plugin -
©2020 Wantedly, Inc. Benefits • Share build logic across modules
• Reduce maintenance cost when updating build scripts • Higher degree of modularization • Better organization and comprehensibility Gradle Plugin -
©2020 Wantedly, Inc. Benefits • Share build logic across modules
• Reduce maintenance cost when updating build scripts • Higher degree of modularization • Better organization and comprehensibility • Encapsulates logic • Declarative build scripts • Automatically configures tasks and its dependencies Gradle Plugin -
©2020 Wantedly, Inc. • Helped migration to build.gradle.kts • Make
use of Gradle API • Apply Gradle plugin to build.gradle files written in Groovy Our experience Gradle Plugin -
©2020 Wantedly, Inc. • Helped migration to build.gradle.kts • Make
use of Gradle API • Apply Gradle plugin to build.gradle files written in Groovy • Gradually migrate to Kotlin build.gradle.kts files Our experience Gradle Plugin -
©2020 Wantedly, Inc. plugins { id 'com.android.library' id 'kotlin-android' }
android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android.material:material:1.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } Our experience Gradle Plugin -
©2020 Wantedly, Inc. plugins { id 'com.android.library' id 'kotlin-android' }
android { compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 23 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android.material:material:1.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } // build.gradle plugin { id 'com.android.library' id 'my-custom-plugin-id' } myPluginOptions { jacoco { enabled true } } Our experience Gradle Plugin -
©2020 Wantedly, Inc. // build.gradle plugin { id 'com.android.library' id
'my-custom-plugin-id' } myPluginOptions { jacoco { enabled true } } Our experience Gradle Plugin -
©2020 Wantedly, Inc. // build.gradle plugin { id 'com.android.library' id
'my-custom-plugin-id' } myPluginOptions { jacoco { enabled true } } // build.gradle.kts plugin { id("com.android.library") id("my-custom-plugin-id") } myPluginOptions { jacoco { isEnabled = true } } Our experience Gradle Plugin -
©2020 Wantedly, Inc. • buildSrc vs standalone plugin • Plugin
is very specific to each project Our experience Gradle Plugin -
©2020 Wantedly, Inc. • buildSrc vs standalone plugin • Plugin
is very specific to each project • But, split the plugins when necessary depending on its purpose • e.g., Jacoco as its own plugin Our experience Gradle Plugin -
©2020 Wantedly, Inc. Summary • Maintaining build.gradle files can be
tedious Gradle Plugin -
©2020 Wantedly, Inc. Summary • Maintaining build.gradle files can be
tedious • Gradle plugin can simplify the maintenance process Gradle Plugin -
©2020 Wantedly, Inc. Summary • Maintaining build.gradle files can be
tedious • Gradle plugin can simplify the maintenance process • Make Gradle plugin configurable using extension Gradle Plugin