Skip to content

Commit 3c16ad9

Browse files
committed
update: done, with a couple of todos left up to discussion
1 parent 5d2083e commit 3c16ad9

File tree

1 file changed

+64
-38
lines changed

1 file changed

+64
-38
lines changed

topics/development/multiplatform-project-agp-9-migration.md

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ new [Android Gradle Library plugin](https://developer.android.com/kotlin/multipl
1111
In 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-
2730
of 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

3236
The example consists of a single Gradle module (`composeApp`) that contains all the shared code and all of the KMP entry
3337
points.
@@ -60,6 +64,11 @@ location and time zone.
6064
The `Country` data class, for example, relies on `DrawableResource` from Compose Multiplatform and can't be separated
6165
from 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+
6372
Isolate the corresponding code in a `sharedLogic` module:
6473

6574
1. 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.
313321
5. Create a new `commonMain/kotlin` directory inside `sharedUi/src`.
314322
6. 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:
429437
6. Rename the `androidApp/src/androidMain` directory into `main`.
430438
7. 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.
521530
7. 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.
604614
6. 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
618629
1. Move the `composeApp/src/iosMain` directory into the `sharedUi/src` directory.
619630
2. 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

Comments
 (0)