Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Groovy to Kotlin in Buildscripts (Kotlin Night Berlin March 2018)

Groovy to Kotlin in Buildscripts (Kotlin Night Berlin March 2018)

Pros and cons of migrating build scripts from Groovy to Kotlin. Some examples and how the DSL works under the hood.

Talk recording:
https://www.youtube.com/watch?v=BAuP5Bfp-kk

Nelson Osacky

March 15, 2018
Tweet

More Decks by Nelson Osacky

Other Decks in Technology

Transcript

  1. Pros • Type safety • Auto complete • Kotlin Cons

    • Slower builds • Less examples • Pre-release state • Source digging
  2. Pros • type safety • better auto complete • kotlin

    Cons • slower builds • less examples • pre-release state • source digging
  3. apply plugin: 'java-library' apply plugin: 'kotlin' apply plugin: 'com.android.library' targetCompatibility

    = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8 dependencies { testCompile deps.junit compileOnly deps.support.annotations implementation deps.kotlin }
  4. plugins { `java-library` kotlin("jvm") id("com.android.library") }A java { targetCompatibility =

    JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8 }B dependencies { testImplementation(deps("junit")) compileOnly((deps("support") as Map<*, *>) ["annotations"].toString()) }C
  5. /** * Applies the given Kotlin plugin [module]. * *

    For example: `plugins { kotlin("jvm") version "1.2.21" }` * * @param module simple name of the Kotlin Gradle plugin module, for example "jvm", "android", "kapt", "plugin.allopen" etc... */ fun PluginDependenciesSpec.kotlin(module: String): PluginDependencySpec = id("org.jetbrains.kotlin.$module") org.gradle.kotlin.dsl.KotlinDependencyExtensions.kt
  6. """ /** * Applies the given Kotlin plugin [module]. *

    * For example: `plugins { kotlin("jvm") version "$embeddedKotlinVersion" }` * * Visit the [plugin portal](https://plugins.gradle.org/search? term=org.jetbrains.kotlin) to see the list of available plugins. * * @param module simple name of the Kotlin Gradle plugin module, for example "jvm", "android", "kapt", "plugin.allopen" etc... */ fun PluginDependenciesSpec.kotlin(module: String): PluginDependencySpec = id(“org.jetbrains.kotlin.${‘$’}module”) """ 
 buildSrc/src/main/kotlin/codegen/GenerateKotlinDependencyExtensions.kt
  7. val generateKotlinDependencyExtensions by task<GenerateKotlinDependencyExtensions> { val publishedPluginsVersion: String by rootProject.extra

    outputFile = File(apiExtensionsOutputDir, "org/gradle/kotlin/dsl/ KotlinDependencyExtensions.kt") embeddedKotlinVersion = kotlinVersion kotlinDslPluginsVersion = publishedPluginsVersion kotlinDslRepository = kotlinRepo } provider/build.gradle.kts
  8. /** * The builtin Gradle plugin implemented by [org.gradle.api.plugins.JavaLibraryPlugin]. */

    inline val PluginDependenciesSpec.`java-library`: PluginDependencySpec get() = id("org.gradle.java-library") BuiltInPluginExtensions.kt
  9. internal fun generateApiExtensionsJar(outputFile: File, gradleJars: Collection<File>, onProgress: () -> Unit)

    { ApiExtensionsJarGenerator(onProgress = onProgress).generate(outputFile, gradleJars) } org.gradle.kotlin.dsl.codegen.ApiExtensionsJar.kt
  10. apply plugin: 'java-library' apply plugin: 'kotlin' targetCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility

    = JavaVersion.VERSION_1_8 dependencies { testImplementation 'junit:junit:4.12' compileOnly 'com.android.support:support- annotations:27.1.0' }A
  11. plugins { `java-library` kotlin("jvm") } java { targetCompatibility = JavaVersion.VERSION_1_8

    sourceCompatibility = JavaVersion.VERSION_1_8 } dependencies { testImplementation("junit:junit:4.12") compileOnly("com.android.support:support- annotations:27.1.0") }A
  12. apply plugin: 'java-library' apply plugin: 'kotlin' targetCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility

    = JavaVersion.VERSION_1_8 dependencies { testImplementation 'junit:junit:4.12' compileOnly 'com.android.support:support- annotations:27.1.0' }A
  13. plugins { `java-library` kotlin("jvm") } java { targetCompatibility = JavaVersion.VERSION_1_8

    sourceCompatibility = JavaVersion.VERSION_1_8 } dependencies { testImplementation("junit:junit:4.12") compileOnly("com.android.support:support- annotations:27.1.0") }A
  14. ext.deps = [ 'junit' : "junit:junit:4.12", 'support' : [ 'annotations':

    "com.android.support:support-annotations:$ {versions.supportLibrary}", ], ]
  15. apply plugin: 'java-library' apply plugin: 'kotlin' targetCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility

    = JavaVersion.VERSION_1_8 dependencies { testImplementation deps.junit compileOnly deps.support.annotations implementation deps.kotlin }W
  16. dependencies { testImplementation deps.junit }Q 
 dependencies { testImplementation(deps("junit")) }W

    fun Project.deps(key: String): Any { return (rootProject.ext["deps"] as Map<*, *>)[key]!! }D
  17. fun Project.deps(key: String): Any { return (rootProject.ext["deps"] as Map<*, *>)[key]!!

    }D ext.deps = [ 'junit' : "junit:junit:4.12", 'support' : [ 'annotations': "com.android.support:support-annotations:$ {versions.supportLibrary}", ], ]
  18. plugins { `java-library` kotlin("jvm") } java { targetCompatibility = JavaVersion.VERSION_1_8

    sourceCompatibility = JavaVersion.VERSION_1_8 }A dependencies { testImplementation(deps("junit")) compileOnly((deps("support") as Map<*, *>)["annotations"].toString()) implementation(deps("kotlin")) }
  19. apply plugin: 'java-library' apply plugin: 'kotlin' targetCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility

    = JavaVersion.VERSION_1_8 dependencies { testImplementation deps.junit compileOnly deps.support.annotations implementation deps.kotlin }W
  20. plugins { `java-library` kotlin("jvm") } java { targetCompatibility = JavaVersion.VERSION_1_8

    sourceCompatibility = JavaVersion.VERSION_1_8 }A dependencies { testImplementation(deps("junit")) compileOnly((deps("support") as Map<*, *>)["annotations"].toString()) implementation(deps("kotlin")) }
  21. // Groovy if (isCi) { // Do stuff on CI

    }A // Kotlin if (isCi) { // Do stuff on CI }B
  22. // Groovy if (isCi) { // Do stuff on CI

    }A // Kotlin if (isCi()) { // Do stuff on CI }B val ExtensionAware.isCi : Boolean get() = extra.properties["isCi"].toString().toBoolean()
  23. • Experiments are fun • Build speeds are slower •

    Kotlin DSL is still pre-release • Everything is an extension function
  24. public void setSourceCompatibility(Object value) { setSourceCompatibility(JavaVersion.toVersion(value)); } public void setSourceCompatibility(JavaVersion

    value) { srcCompat = value; } public void setTargetCompatibility(Object value) { setTargetCompatibility(JavaVersion.toVersion(value)); } public void setTargetCompatibility(JavaVersion value) { targetCompat = value; } org.gradle.api.JavaPluginConvention.java
  25. /** * Retrieves the [java][org.gradle.api.plugins.JavaPluginConvention] project convention. */ val Project.`java`:

    org.gradle.api.plugins.JavaPluginConvention get() = convention.getPluginByName<org.gradle.api.plugins.JavaPluginConvention>("java") /** * Configures the [java][org.gradle.api.plugins.JavaPluginConvention] project convention. */ fun Project.`java`(configure: org.gradle.api.plugins.JavaPluginConvention.() -> Unit): Unit = configure(`java`) org.gradle.kotlin.dsl.accessors.kt
  26. java { sourceCompatibility = JavaVersion.VERSION_1_8 } withConvention(JavaPluginConvention::class, { sourceCompatibility =

    JavaVersion.VERSION_1_8 }) (this as HasConvention).convention.getPlugin(JavaPluginConvention::class).run { sourceCompatibility = JavaVersion.VERSION_1_8 }
  27. // Groovy // Ensure the no-op leakcanary dependency is always

    used in JVM tests. configurations.all { config -> if (config.name.contains("UnitTest")) { config.resolutionStrategy.eachDependency { details -> if (details.requested.group == "com.squareup.leakcanary" && details.requested.name == "leakcanary-android") { details.useTarget(group: details.requested.group, name: "leakcanary-android-no-op", version: details.requested.version) }A }B }C }D
  28. // Kotlin // Ensure the no-op leakcanary dependency is always

    used in JVM tests. configurations.all { if (name.contains("UnitTest")) { resolutionStrategy.eachDependency { if (requested.group == "com.squareup.leakcanary" && requested.name == “leakcanary-android") { useTarget(mapOf("group" to requested.group, "name" to "leakcanary-android-no-op", "version" to requested.version)) }A }B }C }D
  29. // Kotlin // Ensure the no-op leakcanary dependency is always

    used in JVM tests. configurations.all { if (name.contains("UnitTest")) { resolutionStrategy.eachDependency { if (requested.group == "com.squareup.leakcanary" && requested.name == “leakcanary-android") { useTarget(mapOf("group" to requested.group, "name" to "leakcanary-android-no-op", "version" to requested.version)) }A }B }C }D
  30. // Groovy // Ensure the no-op leakcanary dependency is always

    used in JVM tests. configurations.all { config -> if (config.name.contains("UnitTest")) { config.resolutionStrategy.eachDependency { details -> if (details.requested.group == "com.squareup.leakcanary" && details.requested.name == "leakcanary-android") { details.useTarget(group: details.requested.group, name: "leakcanary-android-no-op", version: details.requested.version) }A }B }C }D