Open ellet0 opened 4 weeks ago
I managed to get it working with a workaround that's far from perfect and shouldn't be used in real production app
implementation(compose.foundation) {
exclude("org.jetbrains.compose.material")
}
implementation(compose.material3) {
exclude("org.jetbrains.compose.material")
}
implementation(compose.ui) {
exclude("org.jetbrains.compose.material")
}
// ...
Or:
implementation(compose.desktop.currentOs) {
exclude("org.jetbrains.compose.material")
}
Create a new Proguard rules file and use it in the compose desktop module/source set
compose.desktop {
application {
// Your configurations
buildTypes.release.proguard {
configurationFiles.from(files("compose-desktop.pro"))
}
}
}
The name of the file is up to you, in my case, I created this project using (kmp.jetbrains.com), so I have to include this file in composeApp
module (not inside desktopMain
source set), the content will be something like
# TODO: Workaround to solve https://github.com/JetBrains/compose-multiplatform/issues/4883
-dontwarn androidx.compose.material.**
-keep class androidx.compose.material3.** { *; }
-ignorewarnings
This will keep all classes from Material 2 and ignore all the warnings from Material 2 and other warnings
runReleaseDistributable
, make sure to run it using your IDE as using ./gradlew runReleaseDistributable
might use Java version 21 or above if installed and configured in the system path, the app will compile but you will get a runtime error if you use anything from Material 3 that depends on Material 2 which might be another issue, the code snippet:
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@Composable fun App() { Button(onClick = {}) { Text(text = "Hi") } }
5. You should get the following error when launching the release version of the app:
![image](https://github.com/JetBrains/compose-multiplatform/assets/73608287/ed136f63-d9b2-432a-bf44-562ec8af627e)
This can be easily fixed by not excluding Material 2 from Material 3:
```kotlin
implementation(compose.material3)
or exclude Material 2 completely if used from Material 3 and only include the needed modules:
implementation(compose.material3) {
// Explicitly exclude Material 2 completely from Material 3 in case Material 3 or any of its modules depends on the Material 2 module or any of its modules
// At the moment, it seems to be only depending on material-ripple and material-icons-core modules
exclude("org.jetbrains.compose.material")
}
// TODO: A workaround to include the needed modules after excluding the Material 2 module from Material 3 (see https://github.com/JetBrains/compose-multiplatform/issues/4883#issuecomment-2142445581) for more details
implementation("org.jetbrains.compose.material:material-ripple:${libs.versions.compose.get()}")
implementation("org.jetbrains.compose.material:material-icons-core:${libs.versions.compose.get()}")
The app works now
Noticed that the default Kotlin icon included in Compose desktop is not included and you will get this instead
I didn't investigate further about this
Another unrelated issue is that Material 3 depends on some Material 2 modules like the ripple effect and icons core
This issue in https://github.com/JetBrains/compose-multiplatform-core which is not in this repository
Additional details:
The binary bundle size that's created with packageReleaseDmg
(requires Java installed)
after the workaround to use Material 3 with Proguard in the release version of the app
Before the workaround (Use Material 2)
The bundle size is around 6MB larger when using Material 3, I only used a Button
and Text
from Material 2 and Material 3, the size might not get much bigger when using more components from Material 3, this is another thing to look at but I'm not sure as I haven't looked into the source code in: https://github.com/JetBrains/compose-multiplatform-core
A better workaround, to use Material 3 (excluding Material 2), Kotlin 2.0.0, Proguard 7.5.0, and Compose 1.6.10:
kotlinx-serialization-core
:implementation(compose.material3)
implementation(compose.desktop.currentOs) {
exclude("org.jetbrains.compose.material")
}
// Explicitly include this is required to fix Proguard warnings coming from Kotlinx.DateTime
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.0")
compose.desktop {
application {
buildTypes.release.proguard {
version.set("7.5.0")
configurationFiles.from("proguard.pro")
}
}
}
proguard.pro
if doesn't exist, use the following rules:-keep class androidx.compose.runtime.** { *; }
-keep class androidx.collection.** { *; }
-keep class androidx.lifecycle.** { *; }
-keep class androidx.compose.ui.text.platform.ReflectionUtil { *; }
# We're excluding Material 2 from the project as we're using Material 3
-dontwarn androidx.compose.material.**
# Kotlinx coroutines rules seems to be outdated with the latest version of Kotlin and Proguard
-keep class kotlinx.coroutines.** { *; }
This doesn't have the icon issue as the previous workaround does.
The Uber JAR on macOS Apple silicon:
The native application binary created with packageReleaseDmg
Note that there are Proguard notes that need to be solved.
I'm facing this issue too, is it going to be addressed in the next release? I think it should be mentioned in release notes too
I'm facing this issue too, is it going to be addressed in the next release? I think it should be mentioned in release notes too
A workaround solution for now is to disable Proguard in the release or fix the issue with a workaround as mentioned above.
The workaround solution doesn't increase the size much. The difference is due to using Material 3
Describe the bug Starting from 1.2, Compose Desktop Plugin supports Proguard without any additional rules to get it working, but if you use Material 3 by using
implementation(compose.material3)
then it will cause failure with all the tasks that use Proguard likecreateReleaseDistributable
Affected platforms
Versions
To Reproduce Steps to reproduce the behavior:
2.0.0
and Compose1.6.10
./gradlew createReleaseDistributable
and see if there is an error, I didn't get any in my casebuild.gradle.kts
of the desktop source set in thecomposeApp
Gradle module (if you used the kmp.jetbrains.com) and replaceimplementation(compose.material)
withimplementation(compose.material3)
, remove any usages to Material module (Material 2) and use anything from Material 3 moduleimport androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable
@Composable fun App() { Button(onClick = {}) { Text(text = "Hi") } }
The Proguard version that's used in the Compose desktop Gradle plugin is
7.2.2
and the one that supports Kotlin 2.0.0 and versions of Java 21 or higher is7.5.0
More details: https://github.com/Guardsquare/proguard/issues/376 and https://github.com/Guardsquare/proguard/issues/387I was able to run the example application using
7.2.2
with no issuesWith Material 2 (the module name is called Material)
The file
KotlinProject/composeApp/build/compose/logs/proguardReleaseJars/java-2024-05-28-05-06-55-err.txt
is empty, theKotlinProject/composeApp/build/compose/logs/proguardReleaseJars/java-2024-05-28-05-06-55-out.txt
was mostly warnings (about 940 lines), the end of the file:https://github.com/JetBrains/compose-multiplatform/blob/7131b5b9a665e8b1d72aabc9476947650145c11e/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/ProguardSettings.kt#L15
https://github.com/JetBrains/compose-multiplatform/blob/7131b5b9a665e8b1d72aabc9476947650145c11e/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/tasks/AbstractUnpackDefaultComposeApplicationResourcesTask.kt#L19
This file might need to be updated: https://github.com/JetBrains/compose-multiplatform/blob/master/gradle-plugins/compose/src/main/resources/default-compose-desktop-rules.pro
Disabling Proguard optimization will give you the exact same issue:
Related Issues
3818
4391
497