diff --git a/docs/topics/multiplatform/multiplatform-compatibility-guide.md b/docs/topics/multiplatform/multiplatform-compatibility-guide.md index 2f6cd353c49..2219f797860 100644 --- a/docs/topics/multiplatform/multiplatform-compatibility-guide.md +++ b/docs/topics/multiplatform/multiplatform-compatibility-guide.md @@ -1,17 +1,22 @@ [//]: # (title: Compatibility guide for Kotlin Multiplatform) + + This guide summarizes [incompatible changes](kotlin-evolution-principles.md#incompatible-changes) you might encounter while developing projects with Kotlin Multiplatform. -> Mind the deprecation cycle of a specific change in relation to the Kotlin version you have in your projects. The current -> Stable version of Kotlin is %kotlinVersion%. -> -{style="note"} +The current Stable version of Kotlin is %kotlinVersion%. Mind the deprecation cycle of a specific change in relation to +the Kotlin version you have in your projects, for example: + +* When upgrading from Kotlin 1.7.0 to Kotlin 1.9.0, check incompatible changes that came into effect both in + [Kotlin 1.9.0](#kotlin-1-9-0-1-9-25) and in [Kotlin 1.7.0−1.8.22](#kotlin-1-7-0-1-8-22). +* When upgrading from Kotlin 1.9.0 to Kotlin 2.0.0, check incompatible changes that came into effect both in + [Kotlin 2.0.0](#kotlin-2-0-0-and-later) and in [Kotlin 1.9.0−1.9.25](#kotlin-1-9-0-1-9-25). ## Version compatibility -When configuring your project, check the compatibility of a particular version of the Kotlin Multiplatform Gradle plugin (same as the Kotlin version in your project) -with available Gradle, Xcode, and Android Gradle plugin versions: +When configuring your project, check the compatibility of a particular version of the Kotlin Multiplatform Gradle plugin +(same as the Kotlin version in your project) with Gradle, Xcode, and Android Gradle plugin versions: | Kotlin Multiplatform plugin version | Gradle | Android Gradle plugin | Xcode | |-------------------------------------|----------------------------------------|---------------------------------|---------| @@ -28,308 +33,206 @@ with available Gradle, Xcode, and Android Gradle plugin versions: > {style="warning"} -## Deprecated compatibility with Kotlin Multiplatform Gradle plugin and Gradle Java plugins - -**What's changed?** - -Due to compatibility issues between the Kotlin Multiplatform Gradle plugin and the Gradle plugins -[Java](https://docs.gradle.org/current/userguide/java_plugin.html), -[Java Library](https://docs.gradle.org/current/userguide/java_library_plugin.html), -and [Application](https://docs.gradle.org/current/userguide/application_plugin.html), -there is now a deprecation warning when you apply these plugins to the same project. The warning also appears when another -Gradle plugin in your multiplatform project applies a Gradle Java plugin. For example, the [Spring Boot Gradle Plugin](https://docs.spring.io/spring-boot/gradle-plugin/index.html) -automatically applies the Application plugin. -In future Kotlin releases, the warning will be increased to an error. +## Kotlin 2.0.0 and later -We've added this deprecation warning due to fundamental compatibility issues between Kotlin Multiplatform's project model -and Gradle's Java ecosystem plugins. Gradle's Java ecosystem plugins currently don't take into account that other plugins may: +This section covers incompatible changes that end their deprecation cycle and come into effect in Kotlin 2.0.0−%kotlinVersion%. -* Also publish or compile for the JVM target in a different way than the Java ecosystem plugins. -* Have two different JVM targets in the same project, such as JVM and Android. -* Have a complex multiplatform project structure with potentially multiple non-JVM targets. + +### Rename of `android` target to `androidTarget` -Unfortunately, Gradle doesn't currently provide any API to address these issues. +**What's changed?** -We previously used some workarounds in Kotlin Multiplatform to help with the integration of Java ecosystem plugins. -However, these workarounds never truly solved the compatibility issues, and since the release of Gradle 8.8, these workarounds -are no longer possible. For more information, see our [YouTrack issue](https://youtrack.jetbrains.com/issue/KT-66542/Gradle-JVM-target-with-withJava-produces-a-deprecation-warning). +We continue our efforts to make Kotlin Multiplatform more stable. An essential step in this direction is to provide first-class +support for the Android target. In the future, this support will be provided via a separate plugin, developed by the +Android team from Google. -While we don't yet know exactly how to resolve this compatibility problem, we are committed to continuing support for -some form of Java source compilation in your Kotlin Multiplatform projects. At a minimum, we will support the compilation -of Java sources and using Gradle's [`java-base`](https://docs.gradle.org/current/javadoc/org/gradle/api/plugins/JavaBasePlugin.html) plugin within your multiplatform projects. +To open the way for the new solution, we're renaming the `android` block to `androidTarget` in the current +Kotlin DSL. This is a temporary change that is necessary to free the short `android` name for the upcoming DSL +from Google. **What's the best practice now?** -If you see this deprecation warning in your multiplatform project, we recommend that you: -1. Determine whether you actually need the Gradle Java plugin in your project. If not, consider removing it. -2. Check if the Gradle Java plugin is only used for a single task. If so, you might be able to remove the plugin without - much effort. For example, if the task uses a Gradle Java plugin to create a Javadoc JAR file, you can define the Javadoc - task manually instead. - -Otherwise, if you want to use both the Kotlin Multiplatform Gradle plugin and these Gradle plugins for Java in your multiplatform -project, we recommend that you: - -1. Create a separate subproject in your multiplatform project. -2. In the separate subproject, apply the Gradle plugin for Java. -3. In the separate subproject, add a dependency on your parent multiplatform project. +Rename all the occurrences of the `android` block to `androidTarget`. When the new plugin for the Android target support +is available, migrate to the DSL from Google. It will be the preferred option to work with Android in Kotlin Multiplatform +projects. -> The separate subproject must **not** be a multiplatform project, and you must only use it to set up a dependency on your multiplatform project. -> -{style="warning"} +**When do the changes take effect?** -For example, you have a multiplatform project called `my-main-project` and you want -to use the [Application](https://docs.gradle.org/current/userguide/application_plugin.html) Gradle plugin to run a JVM application. +Here's the planned deprecation cycle: -Once you've created a subproject, let's call it `subproject-A`, your parent project structure should look like this: +* 1.9.0: introduce a deprecation warning when the `android` name is used in Kotlin Multiplatform projects +* 2.1.0: raise this warning to an error +* 2.2.0: remove the `android` target DSL from the Kotlin Multiplatform Gradle plugin -```text -. -├── build.gradle -├── settings.gradle.kts -├── subproject-A - └── build.gradle.kts - └── src - └── Main.java -``` + +### Declaring several similar targets -In your subproject's `build.gradle.kts` file, apply the Application plugin in the `plugins {}` block: +**What's changed?** - - +We discourage declaring several similar targets in a single Gradle project. For example: ```kotlin -plugins { - id("application") -} -``` - - - - -```groovy -plugins { - id('application') +kotlin { + jvm("jvmKtor") + jvm("jvmOkHttp") // Not recommended and produces a deprecation warning } ``` - - - -In your subproject's `build.gradle.kts` file, add a dependency on your parent multiplatform project: - - - +One popular case is having two related pieces of code together. For example, you might want to use +`jvm("jvmKtor")` and `jvm("jvmOkHttp")` in your `:shared` Gradle project to implement networking using the Ktor +or OkHttp libraries: ```kotlin -dependencies { - implementation(project(":my-main-project")) // The name of your parent multiplatform project -} -``` - - - +// shared/build.gradle.kts: +kotlin { + jvm("jvmKtor") { + attributes.attribute(/* ... */) + } + jvm("jvmOkHttp") { + attributes.attribute(/* ... */) + } -```groovy -dependencies { - implementation project(':my-main-project') // The name of your parent multiplatform project + sourceSets { + val commonMain by getting + val commonJvmMain by sourceSets.creating { + dependsOn(commonMain) + dependencies { + // Shared dependencies + } + } + val jvmKtorMain by getting { + dependsOn(commonJvmMain) + dependencies { + // Ktor dependencies + } + } + val jvmOkHttpMain by getting { + dependsOn(commonJvmMain) + dependencies { + // OkHttp dependencies + } + } + } } ``` - - - +The implementation comes with non-trivial configuration complexity: -Your parent project is now set up to work with both plugins. +* You have to set up Gradle attributes on the `:shared` side and each consumer's side. Otherwise, Gradle can't + resolve dependencies in such projects because without additional information it's not clear whether the consumer + should receive the Ktor-based or the OkHttp-based implementation. +* You have to set up the `commonJvmMain` source set manually. +* The configuration involves a handful of low-level Gradle and Kotlin Gradle plugin abstractions and APIs. -## New approach to auto-generated targets +**What's the best practice now?** -**What's changed?** +The configuration is complex because Ktor-based and OkHttp-based implementations are +_in the same Gradle project_. In many cases, it's possible to extract those parts into separate Gradle projects. +Here's a general outline of such as a refactoring: -Target accessors auto-generated by Gradle are no longer available inside the `kotlin.targets {}` block. Use -the `findByName("targetName")` method instead. +1. Replace two duplicated targets from the original project with a single target. If you had a shared source set between + these targets, move its sources and configuration to the default source set of the newly created target: -Note that such accessors are still available in the `kotlin.targets {}` case, for example, `kotlin.targets.linuxX64`. + ```kotlin + // shared/build.gradle.kts: + kotlin { + jvm() + + sourceSets { + jvmMain { + // Copy the configuration of jvmCommonMain here + } + } + } + ``` -**What's the best practice now?** +2. Add two new Gradle projects, usually by calling `include` in your `settings.gradle.kts` file. For example: - - - - - - - - - -
BeforeNow
+ ```kotlin + include(":okhttp-impl") + include(":ktor-impl") + ``` -```kotlin -kotlin { - targets { - configure(['windows', - 'linux']) { - } - } -} -``` +3. Configure each new Gradle project: - + * Most likely, you don't need to apply the `kotlin("multiplatform")` plugin, as these projects compile only to one + target. In this example, you can apply `kotlin("jvm")`. + * Move the content of original target-specific source sets to their respective projects, for example, + from `jvmKtorMain` to `ktor-impl/src`. + * Copy the configuration of source sets: dependencies, compiler options, and so on. + * Add a dependency from the new Gradle project to the original project. -```kotlin -kotlin { - targets { - configure([findByName('windows'), - findByName('linux')]) { + ```kotlin + // ktor-impl/build.gradle.kts: + plugins { + kotlin("jvm") + } + + dependencies { + project(":shared") // Add dependency on the original project + // Copy dependencies of jvmKtorMain here + } + + kotlin { + compilerOptions { + // Copy compiler options of jvmKtorMain here } } -} -``` + ``` -
+While this approach requires more work on the initial setup, it doesn't use any low-level entities of Gradle and +the Kotlin Gradle plugin, making it easier to use and maintain the resulting build. + +> Unfortunately, we can't provide detailed migration steps for each case. If the instructions above don't work +> for you, describe your use case in this [YouTrack issue](https://youtrack.jetbrains.com/issue/KT-59316). +> +{style="tip"} **When do the changes take effect?** -In Kotlin 1.7.20, an error is introduced when using target accessors in the `kotlin.targets {}` block. +Here's the planned deprecation cycle: -For more information, see the [corresponding issue in YouTrack](https://youtrack.jetbrains.com/issue/KT-47047). +* 1.9.20: introduce a deprecation warning when multiple similar targets are used in Kotlin Multiplatform projects +* 2.1.0: report an error in such cases, except for Kotlin/JS targets; to learn more about this exception, see the issue in [YouTrack](https://youtrack.jetbrains.com/issue/KT-47038/KJS-MPP-Split-JS-target-into-JsBrowser-and-JsNode) -## Changes in Gradle input and output compile tasks + +### Deprecated support of multiplatform libraries published in the legacy mode **What's changed?** -Kotlin compile tasks no longer inherit the Gradle `AbstractCompile` task that has the `sourceCompatibility` and -`targetCompatibility` inputs, making them unavailable in Kotlin users' scripts. +Previously, we [have deprecated +the legacy mode](#deprecated-gradle-properties-for-hierarchical-structure-support) in Kotlin Multiplatform projects +preventing the publication of "legacy" binaries and encouraged you to migrate your projects to the [hierarchical structure](multiplatform-hierarchy.md). -Other breaking changes in compile tasks: +To continue phasing out "legacy" binaries from the ecosystem, starting with Kotlin 1.9.0, the use of legacy libraries +is also discouraged. If your project uses dependencies on legacy libraries, you'll see the following warning: + +```none +The dependency group:artifact:1.0 was published in the legacy mode. Support for such dependencies will be removed in the future +``` **What's the best practice now?** -| Before | Now | -|---------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------| -| The `SourceTask.stableSources` input is no longer available. | Use the `sources` input instead. Also, the `setSource()` methods are still available. | -| The `sourceFilesExtensions` input was removed. | Compile tasks still implement the `PatternFilterable` interface. Use its methods for filtering Kotlin sources. | -| The `Gradle destinationDir: File` output was deprecated. | Use the `destinationDirectory: DirectoryProperty` output instead. | -| The `classpath` property of the `KotlinCompile` task is deprecated. | All compile tasks now use the `libraries` input for a list of libraries required for compilation. | +_If you use multiplatform libraries_, most of them have already migrated to the "hierarchical structure" mode, +so you only need to update the library version. See the documentation of the respective libraries for details. -**When do the changes take effect?** +If the library doesn't support non-legacy binaries yet, you can contact the maintainers and tell them about this +compatibility issue. -In Kotlin 1.7.20, inputs are not available, the output is replaced, and the `classpath` property is deprecated. +_If you're a library author_, update the Kotlin Gradle plugin to the latest version and ensure you've fixed the [deprecated Gradle properties](#deprecated-gradle-properties-for-hierarchical-structure-support). -For more information, see the [corresponding issue in YouTrack](https://youtrack.jetbrains.com/issue/KT-32805). - -## New configuration names for dependencies on the compilation - -**What's changed?** - -Compilation configurations created by the Kotlin Multiplatform Gradle Plugin received new names. - -A target in the Kotlin Multiplatform project has two default compilations, `main` and `test`. Each of these compilations -has its own default source set, for example, `jvmMain` and `jvmTest`. Previously the configuration names for the test -compilation and its default source set were the same, which might lead to a name clash resulting in issues when a -configuration marked with platform-specific attributes is included in another configuration. - -Now compilation configurations have an extra `Compilation` postfix, while projects and plugins that use old hard-coded -configuration names no longer compile. - -Configuration names for dependencies on the corresponding source set stay the same. - -**What's the best practice now?** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BeforeNow
Dependencies of the jvmMain compilation - -```kotlin -jvm -``` - - - -```kotlin -jvmCompilation -``` - -
- -```kotlin -dependencies { - add("jvmImplementation", - "foo.bar.baz:1.2.3") -} -``` - - - -```kotlin -dependencies { - add("jvmCompilationImplementation", - "foo.bar.baz:1.2.3") -} -``` - -
Dependencies of the jvmMain source set - -```kotlin -jvmMain -``` - -
Dependencies of the jvmTest compilation - -```kotlin -jvmTest -``` - - - -```kotlin -jvmTestCompilation -``` - -
Dependencies of the jvmTest source set - -```kotlin -jvmTest -``` - -
- -The available scopes are `Api`, `Implementation`, `CompileOnly`, and `RuntimeOnly`. +The Kotlin team is eager to help the ecosystem migrate, so if you face any issues, don't hesitate to create an [issue in YouTrack](https://kotl.in/issue). **When do the changes take effect?** -In Kotlin 1.8.0, an error is introduced when using old configuration names in hard-coded strings. +Here's the planned deprecation cycle: -For more information, see the [corresponding issue in YouTrack](https://youtrack.jetbrains.com/issue/KT-35916/). +* 1.9: introduce a deprecation warning for dependencies on legacy libraries +* 2.0: raise the warning for dependencies on legacy libraries to an error +* >2.0: remove support for dependencies on legacy libraries; using such dependencies can cause build failures - -## Deprecated Gradle properties for hierarchical structure support +### Deprecated Gradle properties for hierarchical structure support **What's changed?** @@ -374,44 +277,137 @@ Here's the planned deprecation cycle: In the unlikely case you face some problems after removing these properties, create an [issue in YouTrack](https://kotl.in/issue). - -## Deprecated support of multiplatform libraries published in the legacy mode + +### Deprecated target presets API **What's changed?** -Previously, we [have deprecated -the legacy mode](#deprecated-gradle-properties-for-hierarchical-structure-support) in Kotlin Multiplatform projects -preventing the publication of "legacy" binaries and encouraged you to migrate your projects to the [hierarchical structure](multiplatform-hierarchy.md). +In the very early development stages, Kotlin Multiplatform introduced an API for working with so-called _target presets_. +Each target preset essentially represented a factory for Kotlin Multiplatform targets. This API turned out to be largely +redundant, as DSL functions like `jvm()` or `iosSimulatorArm64()` cover the same use cases while being much more +straightforward and concise. -To continue phasing out "legacy" binaries from the ecosystem, starting with Kotlin 1.9.0, the use of legacy libraries -is also discouraged. If your project uses dependencies on legacy libraries, you'll see the following warning: +To reduce the confusion and provide clearer guidelines, all presets-related APIs are now deprecated and will be +removed from the public API of the Kotlin Gradle plugin in future releases. This includes: -```none -The dependency group:artifact:1.0 was published in the legacy mode. Support for such dependencies will be removed in the future +* The `presets` property in `org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension` +* The `org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset` interface and all its inheritors +* The `fromPreset` overloads + +**What's the best practice now?** + +Use respective [Kotlin targets](multiplatform-dsl-reference.md#targets) instead, for example: + + + + + + + + + + +
BeforeNow
+ +```kotlin +kotlin { + targets { + fromPreset(presets.iosArm64, 'ios') + } +} +``` + + + +```kotlin +kotlin { + iosArm64() +} ``` +
+ +**When do the changes take effect?** + +Here's the planned deprecation cycle: + +* 1.9.20: report a warning on any usages of the presets-related API +* 2.0: raise this warning to an error +* >2.0: remove the presets-related API from the public API of the Kotlin Gradle plugin; sources that still use it fail + with "unresolved reference" errors, and binaries (for example, Gradle plugins) might fail with linkage errors + unless recompiled against the latest versions of the Kotlin Gradle plugin + + +### Deprecated Apple target shortcuts + +**What's changed?** + +We're deprecating `ios()`, `watchos()`, and `tvos()` target shortcuts in Kotlin Multiplatform DSL. They were designed to +partially create a source set hierarchy for Apple targets. However, they proved to be difficult to expand and sometimes confusing. + +For example, the `ios()` shortcut created both the `iosArm64` and `iosX64` targets but didn't include the `iosSimulatorArm64` +target, which is necessary when working on hosts with Apple M chips. However, changing this shortcut was hard to implement +and could cause issues in existing user projects. + **What's the best practice now?** -_If you use multiplatform libraries_, most of them have already migrated to the "hierarchical structure" mode, -so you only need to update the library version. See the documentation of the respective libraries for details. +The Kotlin Gradle plugin now provides a built-in hierarchy template. Since Kotlin 1.9.20, it's enabled by default +and contains predefined intermediate source sets for popular use cases. -If the library doesn't support non-legacy binaries yet, you can contact the maintainers and tell them about this -compatibility issue. +Instead of shortcuts, you should specify the list of targets, and then the plugin automatically sets up intermediate +source sets based on this list. -_If you're a library author_, update the Kotlin Gradle plugin to the latest version and ensure you've fixed the [deprecated Gradle properties](#deprecated-gradle-properties-for-hierarchical-structure-support). +For example, if you have `iosArm64` and `iosSimulatorArm64` targets in your project, the plugin automatically creates +the `iosMain` and `iosTest` intermediate source sets. If you have `iosArm64` and `macosArm64` targets, the `appleMain` and +`appleTest` source sets are created. -The Kotlin team is eager to help the ecosystem migrate, so if you face any issues, don't hesitate to create an [issue in YouTrack](https://kotl.in/issue). +For more information, see [Hierarchical project structure](multiplatform-hierarchy.md) **When do the changes take effect?** Here's the planned deprecation cycle: -* 1.9: introduce a deprecation warning for dependencies on legacy libraries -* 2.0: raise the warning for dependencies on legacy libraries to an error -* >2.0: remove support for dependencies on legacy libraries; using such dependencies can cause build failures +* 1.9.20: report a warning when `ios()`, `watchos()`, and `tvos()` target shortcuts are used; + the default hierarchy template is enabled by default instead +* 2.1.0: report an error when target shortcuts are used +* 2.2.0: remove target shortcut DSL from the Kotlin Multiplatform Gradle plugin + +### Incorrect version of iOS framework after Kotlin upgrade + +**What's the issue?** + +Changes in Kotlin code might not be reflected in the iOS app in Xcode when direct integration +is used. The direct integration is set up with the `embedAndSignAppleFrameworkForXcode` task, which connects the iOS +framework from your multiplatform project to the iOS app in Xcode. + +This can happen when you upgrade the Kotlin version from 1.9.2x to 2.0.0 in your multiplatform project (or downgrade it +from 2.0.0 to 1.9.2x), then make changes in Kotlin files and try building the app, Xcode may incorrectly use the previous +version of the iOS framework. So, the changes won't be visible in the iOS app in Xcode. + +**What's the workaround?** + +1. In Xcode, clean build directories using **Product** | **Clean Build Folder**. +2. In the terminal, run the following command: + + ```none + ./gradlew clean + ``` + +3. Build the app again to ensure that the new version of the iOS framework is used. + +**When will the issue be fixed?** + +We're planning to fix this issue in Kotlin 2.0.10. You can check if any preview versions of +Kotlin 2.0.10 are already available in the [Participate in the Kotlin Early Access Preview](eap.md) section. + +For more information, see the [corresponding issue in YouTrack](https://youtrack.jetbrains.com/issue/KT-68257). + +## Kotlin 1.9.0−1.9.25 + +This section covers incompatible changes that end their deprecation cycle and come into effect in Kotlin 1.9.0−1.9.25. -## Deprecated API for adding Kotlin source sets directly to the Kotlin compilation +### Deprecated API for adding Kotlin source sets directly to the Kotlin compilation {initial-collapse-state="collapsed" collapsible="true"} **What's changed?** @@ -480,7 +476,7 @@ Here's the planned deprecation cycle: reference" errors during the buildscript compilation -## Migration from kotlin-js Gradle plugin to kotlin-multiplatform Gradle plugin +### Migration from `kotlin-js` Gradle plugin to `kotlin-multiplatform` Gradle plugin {initial-collapse-state="collapsed" collapsible="true"} **What's changed?** @@ -591,7 +587,7 @@ load on the Kotlin team. We encourage you to migrate to the `kotlin-multiplatfor // No need for the js prefix here, you can just copy and paste it from the top-level block implementation("org.jetbrains.kotlinx:kotlinx-html:0.8.0") } - } + } } } @@ -612,272 +608,286 @@ load on the Kotlin team. We encourage you to migrate to the `kotlin-multiplatfor In 1.9.0, the use of the `kotlin-js` Gradle plugin produces a deprecation warning. - -## Rename of android target to androidTarget + +### Deprecated `jvmWithJava` preset {initial-collapse-state="collapsed" collapsible="true"} **What's changed?** -We continue our efforts to stabilize Kotlin Multiplatform. An essential step in this way is to provide first-class -support for the Android target. In the future, this support will be provided via a separate plugin, developed by the -Android team from Google. - -To open the way for the new solution from Google, we're renaming the `android` block to `androidTarget` in the current -Kotlin DSL. This is a temporary change that is necessary to free the short `android` name for the upcoming DSL -from Google. +`targetPresets.jvmWithJava` is deprecated, and its usage is discouraged. **What's the best practice now?** -Rename all the occurrences of the `android` block to `androidTarget`. When the new plugin for the Android target support -is available, migrate to the DSL from Google. It will be the preferred option to work with Android in Kotlin Multiplatform -projects. +Use `jvm { withJava() }` target instead. Note that after switching to `jvm { withJava() }`, you'll need to adjust +the paths to source directories with `.java` sources. + +For example, if you use a `jvm` target with the default name "jvm": + +| Before | Now | +|-----------------|--------------------| +| `src/main/java` | `src/jvmMain/java` | +| `src/test/java` | `src/jvmTest/java` | **When do the changes take effect?** Here's the planned deprecation cycle: -* 1.9.0: introduce a deprecation warning when the `android` name is used in Kotlin Multiplatform projects -* 2.1.0: raise this warning to an error -* 2.2.0: remove the `android` target DSL from the Kotlin Multiplatform Gradle plugin +* 1.3.40: introduce a warning when `targetPresets.jvmWithJava` is used +* 1.9.20: raise this warning to an error +* >1.9.20: remove `targetPresets.jvmWithJava` API; attempts to use it lead to the buildscript compilation failure - -## Declaring several similar targets +> Even though the whole `targetPresets` API is deprecated, the `jvmWithJava` preset has a different deprecation timeline. +> +{style="note"} + + +### Deprecated legacy Android source set layout {initial-collapse-state="collapsed" collapsible="true"} **What's changed?** -We discourage declaring several similar targets in a single Gradle project. For example: +The [new Android source set layout](multiplatform-android-layout.md) is used by default since Kotlin 1.9.0. +Support for the legacy layout is deprecated, and the use of the `kotlin.mpp.androidSourceSetLayoutVersion` Gradle property +now triggers a deprecation diagnostic. -```kotlin -kotlin { - jvm("jvmKtor") - jvm("jvmOkHttp") // Not recommended and produces a deprecation warning -} -``` +**When do the changes take effect?** -One popular case is having two related pieces of code together. For example, you might want to use -`jvm("jvmKtor")` and `jvm("jvmOkHttp")` in your `:shared` Gradle project to implement networking using the Ktor -or OkHttp libraries: +Here's the planned deprecation cycle: -```kotlin -// shared/build.gradle.kts: -kotlin { - jvm("jvmKtor") { - attributes.attribute(/* ... */) - } - jvm("jvmOkHttp") { - attributes.attribute(/* ... */) - } +* <=1.9.0: report a warning when `kotlin.mpp.androidSourceSetLayoutVersion=1` is used; the warning can be suppressed with + `kotlin.mpp.androidSourceSetLayoutVersion1.nowarn=true` Gradle property +* 1.9.20: raise this warning to an error; the error **cannot** be suppressed +* >1.9.20: remove support for `kotlin.mpp.androidSourceSetLayoutVersion=1`; the Kotlin Gradle plugin ignores the property - sourceSets { - val commonMain by getting - val commonJvmMain by sourceSets.creating { - dependsOn(commonMain) - dependencies { - // Shared dependencies - } - } - val jvmKtorMain by getting { - dependsOn(commonJvmMain) - dependencies { - // Ktor dependencies - } - } - val jvmOkHttpMain by getting { - dependsOn(commonJvmMain) - dependencies { - // OkHttp dependencies - } - } - } -} -``` + +### Deprecated `commonMain` and `commonTest` with custom `dependsOn` {initial-collapse-state="collapsed" collapsible="true"} -The implementation comes with non-trivial configuration complexity: +**What's changed?** -* You have to set up Gradle attributes on the `:shared` side and each consumer's side. Otherwise, Gradle can't - resolve dependencies in such projects because without additional information it's not clear whether the consumer - should receive the Ktor-based or the OkHttp-based implementation. -* You have to set up the `commonJvmMain` source set manually. -* The configuration involves a handful of low-level Gradle and Kotlin Gradle plugin abstractions and APIs. +The `commonMain` and `commonTest` source sets usually represent the roots of the `main` and `test` source set hierarchies, +respectively. However, it was possible to override that by manually configuring `dependsOn` relations of these source sets. + +Maintaining such configuration requires extra effort and knowledge about multiplatform build internals. Additionally, +it decreases code readability and reusability of the code because you need to read the particular buildscript +to be sure whether `commonMain` is the root of the `main` source set hierarchy. + +Therefore, accessing `dependsOn` on `commonMain` and `commonTest` is now deprecated. **What's the best practice now?** -The configuration is complex because Ktor-based and OkHttp-based implementations are -_in the same Gradle project_. In many cases, it's possible to extract those parts into separate Gradle projects. -Here's a general outline of such as a refactoring: +Suppose you need to migrate to 1.9.20 the `customCommonMain` source set that uses `commonMain.dependsOn(customCommonMain)`. +In most cases, `customCommonMain` participates in the same compilations as `commonMain`, so you can merge +`customCommonMain` into `commonMain`: -1. Replace two duplicated targets from the original project with a single target. If you had a shared source set between - these targets, move its sources and configuration to the default source set of the newly created target: +1. Copy sources of `customCommonMain` into `commonMain`. +2. Add all dependencies of `customCommonMain` to `commonMain`. +3. Add all compiler option settings of `customCommonMain` to `commonMain`. - ```kotlin - // shared/build.gradle.kts: - kotlin { - jvm() - - sourceSets { - jvmMain { - // Copy the configuration of jvmCommonMain here - } - } - } - ``` +In rare cases, `customCommonMain` might be participating in more compilations than `commonMain`. +Such a configuration requires additional low-level configuration of the build script. If you're not sure if that's your +use case, it most likely isn't. -2. Add two new Gradle projects, usually by calling `include` in your `settings.gradle.kts` file. For example: +If it is your use case, "swap" these two source sets by moving the sources and settings of `customCommonMain` +to `commonMain` and vice versa. - ```kotlin - include(":okhttp-impl") - include(":ktor-impl") - ``` +**When do the changes take effect?** -3. Configure each new Gradle project: +Here's the planned deprecation cycle: - * Most likely, you don't need to apply the `kotlin("multiplatform")` plugin, as these projects compile only to one - target. In this example, you can apply `kotlin("jvm")`. - * Move the content of original target-specific source sets to their respective projects, for example, - from `jvmKtorMain` to `ktor-impl/src`. - * Copy the configuration of source sets: dependencies, compiler options, and so on. - * Add a dependency from the new Gradle project to the original project. +* 1.9.0: report a warning when `dependsOn` is used in `commonMain` +* >=1.9.20: report an error when `dependsOn` is used in `commonMain` or `commonTest` - ```kotlin - // ktor-impl/build.gradle.kts: - plugins { - kotlin("jvm") - } - - dependencies { - project(":shared") // Add dependency on the original project - // Copy dependencies of jvmKtorMain here - } - - kotlin { - compilerOptions { - // Copy compiler options of jvmKtorMain here - } - } - ``` +### New approach to forward declarations {initial-collapse-state="collapsed" collapsible="true"} -While this approach requires more work on the initial setup, it doesn't use any low-level entities of Gradle and -the Kotlin Gradle plugin, making it easier to use and maintain the resulting build. +**What's changed?** -> Unfortunately, we can't provide detailed migration steps for each case. If the instructions above don't work -> for you, describe your use case in this [YouTrack issue](https://youtrack.jetbrains.com/issue/KT-59316). -> -{style="tip"} +The JetBrains team has revamped the approach to forward declarations in Kotlin to make their behavior more predictable: -**When do the changes take effect?** +* You can only import forward declarations using the `cnames` or ` objcnames` packages. +* You need to explicitly make a cast to and from the corresponding C and Objective-C forward declaration. -Here's the planned deprecation cycle: +**What's the best practice now?** -* 1.9.20: introduce a deprecation warning when multiple similar targets are used in Kotlin Multiplatform projects -* 2.1.0: report an error in such cases, except for Kotlin/JS targets; to learn more about this exception, see the issue in [YouTrack](https://youtrack.jetbrains.com/issue/KT-47038/KJS-MPP-Split-JS-target-into-JsBrowser-and-JsNode) +* Consider a C library with a `library.package` that declares a `cstructName` forward declaration. + Previously, it was possible to import it directly from the library with `import library.package.cstructName`. + Now, you can only use a special forward declaration package for that: `import cnames.structs.cstructName`. + The same is true for `objcnames`. - -## Deprecated jvmWithJava preset +* Consider two objcinterop libraries: one that uses `objcnames.protocols.ForwardDeclaredProtocolProtocol` and another + that has an actual definition: -**What's changed?** + ```ObjC + // First objcinterop library + #import + + @protocol ForwardDeclaredProtocol; + + NSString* consumeProtocol(id s) { + return [NSString stringWithUTF8String:"Protocol"]; + } + ``` -`targetPresets.jvmWithJava` is deprecated, and its usage is discouraged. + ```ObjC + // Second objcinterop library + // Header: + #import + @protocol ForwardDeclaredProtocol + @end + // Implementation: + @interface ForwardDeclaredProtocolImpl : NSObject + @end -**What's the best practice now?** + id produceProtocol() { + return [ForwardDeclaredProtocolImpl new]; + } + ``` -Use `jvm { withJava() }` target instead. Note that after switching to `jvm { withJava() }`, you'll need to adjust -the paths to source directories with `.java` sources. + Previously, it was possible to transfer objects between them seamlessly. Now, an explicit `as` cast is required + for the forward declaration: -For example, if you use a `jvm` target with the default name "jvm": + ```kotlin + // Kotlin code: + fun test() { + consumeProtocol(produceProtocol() as objcnames.protocols.ForwardDeclaredProtocolProtocol) + } + ``` -| Before | Now | -|-----------------|--------------------| -| `src/main/java` | `src/jvmMain/java` | -| `src/test/java` | `src/jvmTest/java` | + > You can only cast to `objcnames.protocols.ForwardDeclaredProtocolProtocol` from the corresponding real class. + > Otherwise, you'll get an error. + > + {style="note"} **When do the changes take effect?** -Here's the planned deprecation cycle: +Starting with Kotlin 1.9.20, you need to explicitly make a cast to and from the corresponding C and Objective-C forward +declarations. Also, it's now only possible to import forward declarations by using special packages. -* 1.3.40: introduce a warning when `targetPresets.jvmWithJava` is used -* 1.9.20: raise this warning to an error -* >1.9.20: remove `targetPresets.jvmWithJava` API; attempts to use it lead to the buildscript compilation failure +## Kotlin 1.7.0−1.8.22 -> Even though the whole `targetPresets` API is deprecated, the `jvmWithJava` preset has a different deprecation timeline. -> -{style="note"} +This section covers incompatible changes that end their deprecation cycle and come into effect in Kotlin 1.7.0−1.8.22. - -## Deprecated legacy Android source set layout +### Deprecated compatibility with Kotlin Multiplatform Gradle plugin and Gradle Java plugins {initial-collapse-state="collapsed" collapsible="true"} **What's changed?** -The [new Android source set layout](multiplatform-android-layout.md) is used by default since Kotlin 1.9.0. -Support for the legacy layout is deprecated, and the use of the `kotlin.mpp.androidSourceSetLayoutVersion` Gradle property -now triggers a deprecation diagnostic. +Due to compatibility issues between the Kotlin Multiplatform Gradle plugin and the Gradle plugins +[Java](https://docs.gradle.org/current/userguide/java_plugin.html), +[Java Library](https://docs.gradle.org/current/userguide/java_library_plugin.html), +and [Application](https://docs.gradle.org/current/userguide/application_plugin.html), +there is now a deprecation warning when you apply these plugins to the same project. The warning also appears when another +Gradle plugin in your multiplatform project applies a Gradle Java plugin. For example, the [Spring Boot Gradle Plugin](https://docs.spring.io/spring-boot/gradle-plugin/index.html) +automatically applies the Application plugin. +In future Kotlin releases, the warning will be increased to an error. -**When do the changes take effect?** +We've added this deprecation warning due to fundamental compatibility issues between Kotlin Multiplatform's project model +and Gradle's Java ecosystem plugins. Gradle's Java ecosystem plugins currently don't take into account that other plugins may: -Here's the planned deprecation cycle: +* Also publish or compile for the JVM target in a different way than the Java ecosystem plugins. +* Have two different JVM targets in the same project, such as JVM and Android. +* Have a complex multiplatform project structure with potentially multiple non-JVM targets. -* <=1.9.0: report a warning when `kotlin.mpp.androidSourceSetLayoutVersion=1` is used; the warning can be suppressed with - `kotlin.mpp.androidSourceSetLayoutVersion1.nowarn=true` Gradle property -* 1.9.20: raise this warning to an error; the error **cannot** be suppressed -* >1.9.20: remove support for `kotlin.mpp.androidSourceSetLayoutVersion=1`; the Kotlin Gradle plugin ignores the property +Unfortunately, Gradle doesn't currently provide any API to address these issues. - -## Deprecated commonMain and commonTest with custom dependsOn +We previously used some workarounds in Kotlin Multiplatform to help with the integration of Java ecosystem plugins. +However, these workarounds never truly solved the compatibility issues, and since the release of Gradle 8.8, these workarounds +are no longer possible. For more information, see our [YouTrack issue](https://youtrack.jetbrains.com/issue/KT-66542/Gradle-JVM-target-with-withJava-produces-a-deprecation-warning). -**What's changed?** +While we don't yet know exactly how to resolve this compatibility problem, we are committed to continuing support for +some form of Java source compilation in your Kotlin Multiplatform projects. At a minimum, we will support the compilation +of Java sources and using Gradle's [`java-base`](https://docs.gradle.org/current/javadoc/org/gradle/api/plugins/JavaBasePlugin.html) plugin within your multiplatform projects. -The `commonMain` and `commonTest` source sets usually represent the roots of the `main` and `test` source set hierarchies, -respectively. However, it was possible to override that by manually configuring `dependsOn` relations of these source sets. +**What's the best practice now?** -Maintaining such configuration requires extra effort and knowledge about multiplatform build internals. Additionally, -it decreases code readability and reusability of the code because you need to read the particular buildscript -to be sure whether `commonMain` is the root of the `main` source set hierarchy. +If you see this deprecation warning in your multiplatform project, we recommend that you: +1. Determine whether you actually need the Gradle Java plugin in your project. If not, consider removing it. +2. Check if the Gradle Java plugin is only used for a single task. If so, you might be able to remove the plugin without + much effort. For example, if the task uses a Gradle Java plugin to create a Javadoc JAR file, you can define the Javadoc + task manually instead. + +Otherwise, if you want to use both the Kotlin Multiplatform Gradle plugin and these Gradle plugins for Java in your multiplatform +project, we recommend that you: + +1. Create a separate subproject in your multiplatform project. +2. In the separate subproject, apply the Gradle plugin for Java. +3. In the separate subproject, add a dependency on your parent multiplatform project. + +> The separate subproject must **not** be a multiplatform project, and you must only use it to set up a dependency on your multiplatform project. +> +{style="warning"} + +For example, you have a multiplatform project called `my-main-project` and you want +to use the [Application](https://docs.gradle.org/current/userguide/application_plugin.html) Gradle plugin to run a JVM application. + +Once you've created a subproject, let's call it `subproject-A`, your parent project structure should look like this: + +```text +. +├── build.gradle +├── settings.gradle.kts +├── subproject-A + └── build.gradle.kts + └── src + └── Main.java +``` + +In your subproject's `build.gradle.kts` file, apply the Application plugin in the `plugins {}` block: + + + + +```kotlin +plugins { + id("application") +} +``` + + + + +```groovy +plugins { + id('application') +} +``` -Therefore, accessing `dependsOn` on `commonMain` and `commonTest` is now deprecated. + + -**What's the best practice now?** +In your subproject's `build.gradle.kts` file, add a dependency on your parent multiplatform project: -Suppose you need to migrate to 1.9.20 the `customCommonMain` source set that uses `commonMain.dependsOn(customCommonMain)`. -In most cases, `customCommonMain` participates in the same compilations as `commonMain`, so you can merge -`customCommonMain` into `commonMain`: + + -1. Copy sources of `customCommonMain` into `commonMain`. -2. Add all dependencies of `customCommonMain` to `commonMain`. -3. Add all compiler option settings of `customCommonMain` to `commonMain`. +```kotlin +dependencies { + implementation(project(":my-main-project")) // The name of your parent multiplatform project +} +``` -In rare cases, `customCommonMain` might be participating in more compilations than `commonMain`. -Such a configuration requires additional low-level configuration of the build script. If you're not sure if that's your -use case, it most likely isn't. + + -If it is your use case, "swap" these two source sets by moving the sources and settings of `customCommonMain` -to `commonMain` and vice versa. +```groovy +dependencies { + implementation project(':my-main-project') // The name of your parent multiplatform project +} +``` -**When do the changes take effect?** + + -Here's the planned deprecation cycle: -* 1.9.0: report a warning when `dependsOn` is used in `commonMain` -* >=1.9.20: report an error when `dependsOn` is used in `commonMain` or `commonTest` +Your parent project is now set up to work with both plugins. - -## Deprecated target presets API +### New approach to auto-generated targets {initial-collapse-state="collapsed" collapsible="true"} **What's changed?** -In the very early development stages, Kotlin Multiplatform introduced an API for working with so-called _target presets_. -Each target preset essentially represented a factory for Kotlin Multiplatform targets. This API turned out to be largely -redundant, as DSL functions like `jvm()` or `iosSimulatorArm64()` cover the same use cases while being much more -straightforward and concise. - -To reduce the confusion and provide clearer guidelines, all presets-related APIs are now deprecated and will be -removed from the public API of the Kotlin Gradle plugin in future releases. This includes: +Target accessors auto-generated by Gradle are no longer available inside the `kotlin.targets {}` block. Use +the `findByName("targetName")` method instead. -* The `presets` property in `org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension` -* The `org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset` interface and all its inheritors -* The `fromPreset` overloads +Note that such accessors are still available in the `kotlin.targets {}` case, for example, `kotlin.targets.linuxX64`. **What's the best practice now?** -Use respective [Kotlin targets](multiplatform-dsl-reference.md#targets) instead, for example: - @@ -889,7 +899,9 @@ Use respective [Kotlin targets](multiplatform-dsl-reference.md#targets) instead, ```kotlin kotlin { targets { - fromPreset(presets.iosArm64, 'ios') + configure(['windows', + 'linux']) { + } } } ``` @@ -899,150 +911,154 @@ kotlin { ```kotlin kotlin { - iosArm64() + targets { + configure([findByName('windows'), + findByName('linux')]) { + } + } } ``` - +
Before
**When do the changes take effect?** -Here's the planned deprecation cycle: +In Kotlin 1.7.20, an error is introduced when using target accessors in the `kotlin.targets {}` block. -* 1.9.20: report a warning on any usages of the presets-related API -* 2.0: raise this warning to an error -* >2.0: remove the presets-related API from the public API of the Kotlin Gradle plugin; sources that still use it fail - with "unresolved reference" errors, and binaries (for example, Gradle plugins) might fail with linkage errors - unless recompiled against the latest versions of the Kotlin Gradle plugin +For more information, see the [corresponding issue in YouTrack](https://youtrack.jetbrains.com/issue/KT-47047). - -## Deprecated Apple target shortcuts +### Changes in Gradle input and output compile tasks {initial-collapse-state="collapsed" collapsible="true"} **What's changed?** -We're deprecating `ios()`, `watchos()`, and `tvos()` target shortcuts in Kotlin Multiplatform DSL. They were designed to -partially create a source set hierarchy for Apple targets. However, they proved to be difficult to expand and sometimes confusing. +Kotlin compile tasks no longer inherit the Gradle `AbstractCompile` task that has the `sourceCompatibility` and +`targetCompatibility` inputs, making them unavailable in Kotlin users' scripts. -For example, the `ios()` shortcut created both the `iosArm64` and `iosX64` targets but didn't include the `iosSimulatorArm64` -target, which is necessary when working on hosts with Apple M chips. However, changing this shortcut was hard to implement -and could cause issues in existing user projects. +Other breaking changes in compile tasks: **What's the best practice now?** -The Kotlin Gradle plugin now provides a built-in hierarchy template. Since Kotlin 1.9.20, it's enabled by default -and contains predefined intermediate source sets for popular use cases. - -Instead of shortcuts, you should specify the list of targets, and then the plugin automatically sets up intermediate -source sets based on this list. - -For example, if you have `iosArm64` and `iosSimulatorArm64` targets in your project, the plugin automatically creates -the `iosMain` and `iosTest` intermediate source sets. If you have `iosArm64` and `macosArm64` targets, the `appleMain` and -`appleTest` source sets are created. - -For more information, see [Hierarchical project structure](multiplatform-hierarchy.md) +| Before | Now | +|---------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------| +| The `SourceTask.stableSources` input is no longer available. | Use the `sources` input instead. Also, the `setSource()` methods are still available. | +| The `sourceFilesExtensions` input was removed. | Compile tasks still implement the `PatternFilterable` interface. Use its methods for filtering Kotlin sources. | +| The `Gradle destinationDir: File` output was deprecated. | Use the `destinationDirectory: DirectoryProperty` output instead. | +| The `classpath` property of the `KotlinCompile` task is deprecated. | All compile tasks now use the `libraries` input for a list of libraries required for compilation. | **When do the changes take effect?** -Here's the planned deprecation cycle: +In Kotlin 1.7.20, inputs are not available, the output is replaced, and the `classpath` property is deprecated. -* 1.9.20: report a warning when `ios()`, `watchos()`, and `tvos()` target shortcuts are used; - the default hierarchy template is enabled by default instead -* 2.1.0: report an error when target shortcuts are used -* 2.2.0: remove target shortcut DSL from the Kotlin Multiplatform Gradle plugin +For more information, see the [corresponding issue in YouTrack](https://youtrack.jetbrains.com/issue/KT-32805). -## New approach to forward declarations +### New configuration names for dependencies on the compilation {initial-collapse-state="collapsed" collapsible="true"} **What's changed?** -The JetBrains team has revamped the approach to forward declarations in Kotlin to make their behavior more predictable: +Compilation configurations created by the Kotlin Multiplatform Gradle Plugin received new names. -* You can only import forward declarations using the `cnames` or ` objcnames` packages. -* You need to explicitly make a cast to and from the corresponding C and Objective-C forward declaration. +A target in the Kotlin Multiplatform project has two default compilations, `main` and `test`. Each of these compilations +has its own default source set, for example, `jvmMain` and `jvmTest`. Previously the configuration names for the test +compilation and its default source set were the same, which might lead to a name clash resulting in issues when a +configuration marked with platform-specific attributes is included in another configuration. + +Now compilation configurations have an extra `Compilation` postfix, while projects and plugins that use old hard-coded +configuration names no longer compile. + +Configuration names for dependencies on the corresponding source set stay the same. **What's the best practice now?** -* Consider a C library with a `library.package` that declares a `cstructName` forward declaration. - Previously, it was possible to import it directly from the library with `import library.package.cstructName`. - Now, you can only use a special forward declaration package for that: `import cnames.structs.cstructName`. - The same is true for `objcnames`. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BeforeNow
Dependencies of the jvmMain compilation -* Consider two objcinterop libraries: one that uses `objcnames.protocols.ForwardDeclaredProtocolProtocol` and another - that has an actual definition: +```kotlin +jvm +``` - ```ObjC - // First objcinterop library - #import - - @protocol ForwardDeclaredProtocol; - - NSString* consumeProtocol(id s) { - return [NSString stringWithUTF8String:"Protocol"]; - } - ``` + - ```ObjC - // Second objcinterop library - // Header: - #import - @protocol ForwardDeclaredProtocol - @end - // Implementation: - @interface ForwardDeclaredProtocolImpl : NSObject - @end +```kotlin +jvmCompilation +``` - id produceProtocol() { - return [ForwardDeclaredProtocolImpl new]; - } - ``` +
- Previously, it was possible to transfer objects between them seamlessly. Now, an explicit `as` cast is required - for the forward declaration: +```kotlin +dependencies { + add("jvmImplementation", + "foo.bar.baz:1.2.3") +} +``` - ```kotlin - // Kotlin code: - fun test() { - consumeProtocol(produceProtocol() as objcnames.protocols.ForwardDeclaredProtocolProtocol) - } - ``` + - > You can only cast to `objcnames.protocols.ForwardDeclaredProtocolProtocol` from the corresponding real class. - > Otherwise, you'll get an error. - > - {style="note"} +```kotlin +dependencies { + add("jvmCompilationImplementation", + "foo.bar.baz:1.2.3") +} +``` -**When do the changes take effect?** +
Dependencies of the jvmMain source set -Starting with Kotlin 1.9.20, you need to explicitly make a cast to and from the corresponding C and Objective-C forward -declarations. Also, it's now only possible to import forward declarations by using special packages. +```kotlin +jvmMain +``` -## Incorrect version of iOS framework after Kotlin upgrade +
Dependencies of the jvmTest compilation -**What's the issue?** +```kotlin +jvmTest +``` -Changes in Kotlin code might not be reflected in the iOS app in Xcode when direct integration -is used. The direct integration is set up with the `embedAndSignAppleFrameworkForXcode` task, which connects the iOS -framework from your multiplatform project to the iOS app in Xcode. + -This can happen when you upgrade the Kotlin version from 1.9.2x to 2.0.0 in your multiplatform project (or downgrade it -from 2.0.0 to 1.9.2x), then make changes in Kotlin files and try building the app, Xcode may incorrectly use the previous -version of the iOS framework. So, the changes won't be visible in the iOS app in Xcode. +```kotlin +jvmTestCompilation +``` -**What's the workaround?** +
Dependencies of the jvmTest source set -1. In Xcode, clean build directories using **Product** | **Clean Build Folder**. -2. In the terminal, run the following command: +```kotlin +jvmTest +``` - ```none - ./gradlew clean - ``` +
-3. Build the app again to ensure that the new version of the iOS framework is used. +The available scopes are `Api`, `Implementation`, `CompileOnly`, and `RuntimeOnly`. -**When will the issue be fixed?** +**When do the changes take effect?** -We're planning to fix this issue in Kotlin 2.0.10. You can check if any preview versions of -Kotlin 2.0.10 are already available in the [Participate in the Kotlin Early Access Preview](eap.md) section. +In Kotlin 1.8.0, an error is introduced when using old configuration names in hard-coded strings. -For more information, see the [corresponding issue in YouTrack](https://youtrack.jetbrains.com/issue/KT-68257). +For more information, see the [corresponding issue in YouTrack](https://youtrack.jetbrains.com/issue/KT-35916/).