Slide 1

Slide 1 text

Groovy to Kotlin in build scripts Nelson Osacky

Slide 2

Slide 2 text

•Some Pros and Cons •Examples •How it works under the hood

Slide 3

Slide 3 text

build.gradle -> build.gradle.kts

Slide 4

Slide 4 text

Motivations

Slide 5

Slide 5 text

Kotlin DSL v0.15.6

Slide 6

Slide 6 text

Experiment

Slide 7

Slide 7 text

Pros • Type safety • Auto complete • Kotlin Cons • Slower builds • Less examples • Pre-release state • Source digging

Slide 8

Slide 8 text

type safety

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

if (isCi) { foo }A

Slide 11

Slide 11 text

if (isCi) { foo }A

Slide 12

Slide 12 text

auto-complete

Slide 13

Slide 13 text

• autocompletion gif

Slide 14

Slide 14 text

Slower builds

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

Less docs https://github.com/gradle/kotlin-dsl/tree/master/samples

Slide 18

Slide 18 text

Must dig in source

Slide 19

Slide 19 text

Pros • type safety • better auto complete • kotlin Cons • slower builds • less examples • pre-release state • source digging

Slide 20

Slide 20 text

Examples

Slide 21

Slide 21 text

settings.gradle.kts

Slide 22

Slide 22 text

include ':app' include ':data' include ':service'

Slide 23

Slide 23 text

include( ":app", ":data", ":service" )

Slide 24

Slide 24 text

build.gradle.kts

Slide 25

Slide 25 text

plugins

Slide 26

Slide 26 text

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 }

Slide 27

Slide 27 text

apply plugin: 'java-library' apply plugin: 'kotlin' apply plugin: 'com.android.library'

Slide 28

Slide 28 text

plugins { `java-library` kotlin("jvm") id("com.android.library") }A

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

plugins { `java-library` kotlin("jvm") id("com.android.library") }A

Slide 31

Slide 31 text

plugins { `java-library` kotlin("jvm") id("com.android.library") }A

Slide 32

Slide 32 text

/** * 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

Slide 33

Slide 33 text

""" /** * 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

Slide 34

Slide 34 text

val generateKotlinDependencyExtensions by task { 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

Slide 35

Slide 35 text

plugins { `java-library` kotlin("jvm") id("com.android.library") }A

Slide 36

Slide 36 text

plugins { `java-library` kotlin("jvm") id("com.android.library") }A

Slide 37

Slide 37 text

/** * 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

Slide 38

Slide 38 text

internal fun generateApiExtensionsJar(outputFile: File, gradleJars: Collection, onProgress: () -> Unit) { ApiExtensionsJarGenerator(onProgress = onProgress).generate(outputFile, gradleJars) } org.gradle.kotlin.dsl.codegen.ApiExtensionsJar.kt

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

dependencies { testImplementation 'junit:junit:4.12' }A

Slide 41

Slide 41 text

dependencies { testImplementation("junit:junit:4.12") }A

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

ext block

Slide 46

Slide 46 text

ext.deps = [ 'junit' : "junit:junit:4.12", 'support' : [ 'annotations': "com.android.support:support-annotations:$ {versions.supportLibrary}", ], ]

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

dependencies { testImplementation deps.junit compileOnly deps.support.annotations }W

Slide 49

Slide 49 text

dependencies { testImplementation deps.junit }W

Slide 50

Slide 50 text

dependencies { testImplementation(deps("junit")) }W

Slide 51

Slide 51 text

dependencies { testImplementation deps.junit }Q 
 dependencies { testImplementation(deps("junit")) }W

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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}", ], ]

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

dependencies { testImplementation(deps(“junit")) compileOnly((deps("support") as Map<*, *>)["annotations"].toString()) }A fun Project.deps(key: String): Any { return (rootProject.ext["deps"] as Map<*, *>)[key]!! }D

Slide 57

Slide 57 text

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")) }

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

targetCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8

Slide 60

Slide 60 text

java { targetCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8 }A

Slide 61

Slide 61 text

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")) }

Slide 62

Slide 62 text

// Groovy ext.isCi = System.getenv("CI") == "true"

Slide 63

Slide 63 text

// Kotlin extra.set("isCi", System.getenv("CI") == "true")

Slide 64

Slide 64 text

// Groovy ext.isCi = System.getenv("CI") == “true" // Kotlin extra.set("isCi", System.getenv("CI") == "true")

Slide 65

Slide 65 text

val ExtensionAware.isCi : Boolean get() = extra.properties["isCi"].toString().toBoolean()

Slide 66

Slide 66 text

// Groovy if (isCi) { // Do stuff on CI }B

Slide 67

Slide 67 text

// Kotlin if (isCi) { // Do stuff on CI }B

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

// 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()

Slide 70

Slide 70 text

• Experiments are fun • Build speeds are slower • Kotlin DSL is still pre-release • Everything is an extension function

Slide 71

Slide 71 text

Thanks [email protected]
 https://www.zenjob.de/careers/ Questions? https://github.com/gradle/kotlin-dsl/tree/master/samples

Slide 72

Slide 72 text

targetCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8

Slide 73

Slide 73 text

java { targetCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8 }A

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

public void apply(ProjectInternal project) { project.getPluginManager().apply(JavaBasePlugin.class); JavaPluginConvention javaConvention = project.getConvention() .getPlugin(JavaPluginConvention.class); } org.gradle.api.plugins.JavaPlugin.java

Slide 76

Slide 76 text

/** * Retrieves the [java][org.gradle.api.plugins.JavaPluginConvention] project convention. */ val Project.`java`: org.gradle.api.plugins.JavaPluginConvention get() = convention.getPluginByName("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

Slide 77

Slide 77 text

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 }

Slide 78

Slide 78 text

// 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

Slide 79

Slide 79 text

// 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

Slide 80

Slide 80 text

// 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

Slide 81

Slide 81 text

// 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