10

I have a project with multiple subprojects that use the kotlin-multiplatform plugin or the kotlin-js plugin and I want to use the experimental unsigned types in all of them.

So far I've tried this, which doesn't work:

subprojects {
    tasks.withType<KotlinCompile>().all {
        kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.ExperimentalUnsignedTypes"
    }

    extensions.findByType<KotlinMultiplatformExtension>()?.sourceSets {
        all {
            languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
        }
    }
}

Is there a way to add the kotlin compiler arg -Xopt-in=kotlin.ExperimentalUnsignedTypes to all subprojects in Gradle?

shadowsheep
  • 14,048
  • 3
  • 67
  • 77
Daan
  • 1,516
  • 12
  • 20

2 Answers2

8

I've reached this point with trial and error, so I'm not sure this is the right approach.

I had a multiproject build with some multiplatform, JVM, and JS subprojects, and I wanted to enable the kotlin.RequiresOptIn annotation. So I ended up setting this compiler argument for all kinds of kotlin compilation tasks:

subprojects {
    val compilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn")
    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
        kotlinOptions.jvmTarget = "1.8"
        kotlinOptions.freeCompilerArgs += compilerArgs
    }

    tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile> {
        kotlinOptions.freeCompilerArgs = compilerArgs
    }

    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon> {
        kotlinOptions.freeCompilerArgs = compilerArgs
    }
}

I guess the same approach could work for ExperimentalUnsignedTypes.

Joffrey
  • 32,348
  • 6
  • 68
  • 100
  • This works for the Kotlin JS (and probably Java and common) projects but not the multiplatform projects. Thanks for the first part of the solution though! – Daan Oct 04 '20 at 11:22
  • This is most likely because my own multiplatform subprojects only support JS and JVM targets at the moment. For native there might be other compile tasks. I would hope for a more general approach though, this is kind of hacky. – Joffrey Oct 04 '20 at 11:51
  • 1
    This simply doesn't work for multiplatform projects with `languageSettings.useExperimentalAnnotation` (my own projects only have common and js code atm) – Daan Oct 05 '20 at 14:08
  • 2
    There is a common supertype for all these tasks. Maybe this will do the thing: `tasks.withType>().configureEach { kotlinOptions.freeCompilerArgs += compilerArgs }`? – Михаил Нафталь Oct 05 '20 at 15:39
  • org.jetbrains.kotlin.gradle.dsl.KotlinCompile did the job thank you – Dmitry Kolesnikovich Oct 02 '22 at 21:52
4

The recommended way to share configuration is via a convention plugin.

I.e. create a file in buildSrc/src/main/kotlin/package/name/kotlin-mpp-conventions.kts with the contents:

plugins {
    kotlin("jvm")
}

kotlin {
    sourceSets {
        all {
            languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
        }
    }
}

Then depend on this plugin from your Kotlin MPP subprojects by adding a reference to it in the plugins block: id("package.name.kotlin-mpp-conventions").

Add more plugins for e.g. Kotlin JS projects. If there's some configuration you want to share between all types of projects you can create a common plugin that the other plugins depend on. You can also share data structures between plugins by simply putting them in a separate file and referencing them from the plugin files (like you would with normal code), I use this mechanism to share the list of Kotlin experimental annotations I want to allow in all plugins.

Be sure to set up buildSrc/build.gradle.kts for plugins:

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21")
}
Daan
  • 1,516
  • 12
  • 20