@@ -11,7 +11,10 @@ new [Android Gradle Library plugin](https://developer.android.com/kotlin/multipl
1111In the following guide, we highlight changes related to this as well.
1212
1313> To make your project work with AGP 9.0 in the short term, you can manually enable the hidden APIs.
14- > TODO: explain how to do that.
14+ > To do that, in the ` gradle.properties ` file of your project add this property:
15+ > ` android.enableLegacyVariantApi=true ` .
16+ >
17+ > The legacy API is going to be removed completely in AGP 10, make sure you finish the migration before that!
1518>
1619 {style="note"}
1720
@@ -27,7 +30,8 @@ the [update_october_2025 branch](https://github.com/kotlin-hands-on/get-started-
2730of the sample project.
2831
2932<!-- TODO this branch doesn't work, need something else here — I just followed the tutorial with the current plugin version
30- and migrated the result -->
33+ and migrated the result
34+ in the meantime, the best approach is to follow the tutorial :)-->
3135
3236The example consists of a single Gradle module (` composeApp ` ) that contains all the shared code and all of the KMP entry
3337points.
@@ -60,6 +64,11 @@ location and time zone.
6064The ` Country ` data class, for example, relies on ` DrawableResource ` from Compose Multiplatform and can't be separated
6165from UI code.
6266
67+ > If your project already has a ` shared ` module, for example, because you don't share the entirety of UI code,
68+ > then you can use this module in place of ` sharedLogic ` — or rename it to better differentiate between shared logic and UI.
69+ >
70+ {style="note"}
71+
6372Isolate the corresponding code in a ` sharedLogic ` module:
6473
65741 . Create the ` sharedLogic ` directory at the root of the project.
@@ -198,7 +207,7 @@ Isolate shared code implementing common UI elements in the `sharedUi` module:
198207 ```kotlin
199208 include(" :sharedUi" )
200209 ```
201- 4 . Configure the Gradle build script for the new module.
210+ 4 . Configure the Gradle build script for the new module:
202211
203212 1 . If you haven' t done this for the `sharedLogic` module, in `gradle/libs.versions.toml`,
204213 add the Android Gradle Library plugin to your version catalog:
@@ -309,7 +318,6 @@ Isolate shared code implementing common UI elements in the `sharedUi` module:
309318 ```
310319 7 . Select ** Build | Sync Project with Gradle Files ** in the main menu, or click the Gradle refresh button in the
311320 editor.
312- 5 . TODO Maybe notable changes to the build script should be summarized in the beginning.
3133215 . Create a new `commonMain/ kotlin` directory inside `sharedUi/ src`.
3143226 . Move resource files to the `sharedUi` module: the entire directory of `composeApp/ commonMain/ composeResources` should
315323 be relocated to `sharedUi/ commonMain/ composeResources`.
@@ -429,14 +437,15 @@ Create and configure a new entry point module for the Android app:
4294376 . Rename the `androidApp/ src/ androidMain` directory into `main`.
4304387 . If everything is configured correctly, the imports in the `androidApp/ src/ main/ .. ./ MainActivity .kt` file are working
431439 and the code is compiling.
432- 8 . Run the Android app from the gutter in the `androidApp/ src/ main/ .. ./ MainActivity .kt` file: click the green arrow
433- in the `class MainActivity ` line and select **Run 'MainActivity '**.
434- 9 . If everything works correctly:
435- * Remove the `composeApp/ src/ androidMain` directory.
436- * In the `composeApp/ build.gradle.kts` file, remove the desktop- related code:
437- * the `android {}` block,
438- * the `androidMain.dependencies {}`,
439- * the `androidTarget {}` block inside the `kotlin {}` block.
440+ 8 . To run your Android app, change and rename the ** composeApp** Android run configuration or add a similar one.
441+ In the ** General | Module ** field, change `demo.composeApp` to `demo.androidApp`.
442+ 9 . Start the run configuration to make sure that the app runs as expected.
443+ 10 . If everything works correctly:
444+ * Remove the `composeApp/ src/ androidMain` directory.
445+ * In the `composeApp/ build.gradle.kts` file, remove the desktop- related code:
446+ * the `android {}` block,
447+ * the `androidMain.dependencies {}`,
448+ * the `androidTarget {}` block inside the `kotlin {}` block.
440449
441450#### Desktop JVM app
442451
@@ -520,14 +529,15 @@ Create and configure the JVM desktop app module:
520529 It ' s important that the package coordinates are aligned with the `compose.desktop {}` configuration.
5215307. If everything is configured correctly, the imports in the `desktopApp/src/main/.../main.kt` file are working
522531 and the code is compiling.
523- 8. Run your desktop app from the gutter in the `desktopApp/src/main/.../main.kt` file: click the green arrow next
524- to the `main()` function and select **Run ' Main .kt' **.
525- 9. If everything works correctly:
526- * Remove the `composeApp/src/jvmMain` directory.
527- * In the `composeApp/build.gradle.kts` file, remove the desktop-related code:
528- * the `compose.desktop {}` block,
529- * the `jvmMain.dependencies {}` block inside the Kotlin `sourceSets {}` block,
530- * the `jvm()` target declaration inside the `kotlin {}` block.
532+ 8. To run your desktop app, change and rename the **composeApp [jvm]** run configuration or add a similar one.
533+ In the **Gradle project** field, change `ComposeDemo:composeApp` to `ComposeDemo:desktopApp`.
534+ 9. Start the run configuration to make sure that the app runs as expected.
535+ 10. If everything works correctly:
536+ * Remove the `composeApp/src/jvmMain` directory.
537+ * In the `composeApp/build.gradle.kts` file, remove the desktop-related code:
538+ * the `compose.desktop {}` block,
539+ * the `jvmMain.dependencies {}` block inside the Kotlin `sourceSets {}` block,
540+ * the `jvm()` target declaration inside the `kotlin {}` block.
531541
532542#### Web app
533543
@@ -602,18 +612,19 @@ Create and configure the web app module:
602612 If everything is configured correctly, the imports in the `webApp/src/webMain/.../main.kt` file are working
603613 and the code is compiling.
6046146. In the `webApp/src/webMain/resources/index.html` file update the script name: from `composeApp.js` to `webApp.js`.
605- 7. Run your web app from the gutter in the `webApp/src/webMain/.../main.kt` file: click the green arrow next
606- to the `main()` function and select **Run ' webApp [wasmJs] ' ** .
607- 8. If everything works correctly:
608- * Remove the `composeApp/src/jvmMain` directory.
609- * In the `composeApp/build.gradle.kts` file, remove the desktop-related code:
610- * the `compose.desktop {}` block,
611- * the `jvmMain .dependencies {}` block inside the Kotlin `sourceSets {}` block,
612- * the `jvm()` target declaration inside the `kotlin {}` block.
615+ 7. Run your web app: change and rename the **composeApp [wasmJs]** and **composeApp [js]** run configurations or add similar ones.
616+ In the **Gradle project** field, change `ComposeDemo:composeApp` to `ComposeDemo:webApp` .
617+ 8. Start the run configurations to make sure that the app runs as expected.
618+ 9. If everything works correctly:
619+ * Remove the `composeApp/src/webMain` directory.
620+ * In the `composeApp/build.gradle.kts` file, remove the web-related code:
621+ * the `webMain .dependencies {}` block inside the Kotlin `sourceSets {}` block,
622+ * the `js {}` and `wasmJs {}` target declarations inside the `kotlin {}` block.
613623
614624### Update the iOS integration
615625
616- Since the iOS app is not a separate Gradle module, you can simply move the source set into the `sharedUi` directory:
626+ Since the iOS app entry point is not built as a separate Gradle module, you can embed the source code into any module.
627+ In this example, `sharedUi` makes most sense:
617628
6186291. Move the `composeApp/src/iosMain` directory into the `sharedUi/src` directory.
6196302. Configure the Xcode project to consume the framework produced by the `sharedUi` module:
@@ -622,24 +633,39 @@ Since the iOS app is not a separate Gradle module, you can simply move the sourc
622633 3. Find the **Compile Kotlin Framework** phase.
623634 4. Find the line starting with `./gradlew` and swap `composeApp` for `sharedUi`:
624635
625- ```text
626- ./gradlew :sharedUi:embedAndSignAppleFrameworkForXcode
627- ```
636+ ```text
637+ ./gradlew :sharedUi:embedAndSignAppleFrameworkForXcode
638+ ```
628639
629640 5. Note that the import in the `ContentView.swift` file will stay the same, because it matches the `baseName` parameter from
630641 Gradle configuration of the iOS target,
631642 not actual name of the module.
632643 If you change the framework name in the `sharedUi/build.gradle.kts` file, you need to change the import directive accordingly.
633644
634- 4. Run the app from Xcode or using the **iosApp** run configuration in IntelliJ IDEA
645+ 3. Run the app from Xcode or using the **iosApp** run configuration in IntelliJ IDEA
646+
647+ ### Remove `composeApp` and update the Android Gradle plugin version
635648
636- ### Remove composeApp and TODO create new run configurations?
649+ When all code is working from correct new modules:
637650
638- Now that me moved all code outside composeApp, check that there are no dependencies left. Then remove composeApp
639- entirely.
651+ 1. Remove the old module completely:
652+ 1. Remove the `composeApp` dependency from the `settings.gradle.kts` file (the line `include(":composeApp")`).
653+ 2. Remove the `composeApp` directory entirely.
654+ 3. If you followed all instructions, you have working run configurations for the new project structure.
655+ You can remove old run configurations associated with the `composeApp` module.
656+ 2. In the `gradle/libs.versions.toml` file, update the AGP version to a 9.* version, for example:
657+
658+ ```txt
659+ [versions]
660+ agp = "9.0.0"
661+ ```
662+ 3. Select **Build | Sync Project with Gradle Files** in the main menu, or click the Gradle refresh button in the
663+ build script editor.
640664
665+ 4. That your apps build and run with the new AGP.
641666
667+ Congratulations, you modernized and optimized the structure of your project!
642668
643- ## Anything else?
669+ ## What ' s next
644670
645- If you already have a `shared` module, then this will be the `sharedLogic` module TODO put this in the sharedLogic part .
671+ TODO up for suggestions here — the first thought is to link platform - specific guidance .
0 commit comments