10

I'm looking for a way to configure Kotlin compiler arguments in the build.gradle file of my Android Application project.

I've seen on the Kotlin official documentation that it is possible to configure compiler arguments for each build flavor (such as debug, release).

Project-level build.gradle

buildscript {
    ext.kotlin_version = '1.1.51'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-rc1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

App-level build.gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.2"
    defaultConfig {
        applicationId "com.myapp.myapplication"
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

// The interesting part : configure the compileReleaseKotlin task
// to include compiler arguments when building releases
compileReleaseKotlin {
    kotlinOptions {
        freeCompilerArgs = [
                'Xno-param-assertions',
                'Xno-call-assertions',
                'Xno-receiver-assertions'
        ]
    }
}

dependencies {
    // The usual Android dependencies, omitted for brievety
}

When building the project, I get the following error :

Could not find method compileReleaseKotlin() for arguments [build_7b4e2sfm3830f9z4br95gfme2$_run_closure2@7ed96f28] on project ':app' of type org.gradle.api.Project.

Is the compileReleaseKotlin block misplaced, or mispelled ? Android Studio suggests me this method, though.

Opal
  • 81,889
  • 28
  • 189
  • 210
Thibault Seisel
  • 1,197
  • 11
  • 23
  • It does not necessarily mean that the method is undefined at all. It may also mean that there's something wrong with the arguments. Also you may have invoked this method too early - before an appropriate task was created. – Opal Oct 19 '17 at 06:52
  • I've filed an issue to [Google](https://issuetracker.google.com/issues/168373989) and [JetBrains](https://youtrack.jetbrains.com/issue/KT-37206) – gmk57 Sep 13 '20 at 11:58

3 Answers3

29

Edit 2022

A lot have changed for Android and Kotlin since I posted this answer. Kotlin Gradle Scripts are now a safer way of configuring Gradle builds. Here is the equivalent *.gradle.kts for the below snippet, with additional fixes because it's been wrong for the whole time!

android {
    // Options are applied to all build types
    kotlinOptions {
        freeCompilerArgs += listOf(
            "-Xno-param-assertions",
            "-Xno-call-assertions",
            "-Xno-receiver-assertions",
        )
    }
}

A pointed out by @gmk57, you can't configure specific compiler arguments specific to a given build type from within the buildTypes block. kotlinOptions should be defined directly within the android block, and is applied for all build types.

At the time of writing, the only way to have a build-type-specific configuration is to configure the compileReleaseKotlin task (and flavor variants, if any) in afterEvaluate:

afterEvaluate {
    tasks.compileReleaseKotlin {
        kotlinOptions {
            freeCompilerArgs += listOf(
                "-Xno-param-assertions",
                "-Xno-call-assertions",
                "-Xno-receiver-assertions",
            )
        }
    }
    
    // For flavor dimension full + release
    tasks.named<KotlinCompile>("compileFullReleaseKotlin") {
        kotlinOptions {
            // Same options as above, omitted for brevity
        }
    }
}

Note that the as of Android Gradle Plugin 7.0.0, there are interesting new extensions points allowing to configure build variants at the time of their creation by the plugin. DslExtension may allow the Kotlin Android plugin to seamlessly integrate with build types.


Original answer

After a few days of search and experimentation, I finally found a way to configure the compiler based on the build variant.

Here is what worked for me :

buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            // Configure Kotlin compiler optimisations for releases
            kotlinOptions {
                freeCompilerArgs += [
                        '-Xno-param-assertions',
                        '-Xno-call-assertions',
                        '-Xno-receiver-assertions'
                ]
            }
        }
    }
}

It seems like the documentation for the Gradle Kotlin Android plugin is not correct: while it says that the compiler can be configured by adding, for instance, the compileReleaseKotlin closure for release builds, for Android you have to put a kotlinOptions block in release, as shown above.

Note that for a regular Kotlin project (without Android), the compileKotlin block described in the documentation works as intented.

Hope it helps !

Edit Added - prefix for arguments, as the compiler would silently ignore them otherwise.

Edit 2 Changed = to += to avoid overwriting compiler options from other configurations.

Thibault Seisel
  • 1,197
  • 11
  • 23
  • 1
    Please be aware that this doesn't work as intended: specified options are applied to **all** build types. – gmk57 Sep 13 '20 at 11:26
12

For anyone looking for quick info in 2020 on how to add a compiler arg to a Kotlin Android project (I needed it to enable the experimental serialization API), this is how I did it:

(app build.gradle file)

android {
    ...
    compileOptions {
        ...
        kotlin {
            kotlinOptions {
                freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
            }
        }
    }
}

Android Studio doesn't provide those as suggestions.

Ruslan
  • 2,691
  • 1
  • 19
  • 29
6

Kotlin compiler options for all build types should be specified in the android closure. This is where Android Studio 4.1 places kotlinOptions { jvmTarget = '1.8' } by default:

android {
    ...
    kotlinOptions {
        jvmTarget = '1.8'
        freeCompilerArgs += ['-Xno-param-assertions']
    }
}

Compiler options for specific build type should be configured at the root level, wrapped in afterEvaluate, because the task is only registered once the Android Gradle plugin creates specific build variant, which is only done at the afterEvaluate phase:

afterEvaluate {
    compileReleaseKotlin {
        kotlinOptions {
            freeCompilerArgs += ['-Xno-param-assertions']
        }
    }
}
gmk57
  • 839
  • 11
  • 20