Has anyone tried building for Compose/Desktop usin...
# compose-desktop
m
Has anyone tried building for Compose/Desktop using JDK21 and Proguard? It seems like the Compose plugin uses proguard 7.2, but proguard 7.4 is required for JDK21 support. As per the version docs, JDK17 and above is supposed to be supported.
o
you can try to use a newer proguard version:
Copy code
compose.desktop {
    application {
        buildTypes.release.proguard {
              version.set("7.4.2") // for example
        }
    }
}
👍 1
m
Will try that - it seems to me like that should be the default...
This says JDK17 "and later" is supported, which would imply that the default version of proguard is set to a version that is compatible with a supported (LTS) JDK version
👍 1
o
That makes sense. We'll need to test that nothing breaks with new default proguard version
👍 1
m
Yes... additional testing with Proguard would be good (including obfuscation enabled). I found out of the box KTOR serialization doesn't work (kotlinx serialization is fine, but ktor .body() calls fail). https://youtrack.jetbrains.com/issue/KTOR-6703/Ktor-Client-body-serialization-fails-on-JVM-when-using-Proguard
Maybe if all the example projects were use proguard fully (e.g. obfuscation enabled) that would help uncover things.
👍 1
1
m
I’ve been using ProGuard 7.4.0 with Java 21 for a while now and did not notice any failures with that combination. (Just upgraded to 7.4.2)
🙏 1
m
What version of Compose are you running? I'm getting a verify error when using Proguard 7.4.2 . I was able to reproduce that verify error by taking the compose desktop template generated out of the box by the multiplatform wizard, and simply setting the proguard version reproduced the error
@Oleksandr Karpovich [JB] I think using Proguard 7.4.x doesn't work. I was able to reproduce errors using the out-of-the-box Kotlin multiplatform wizard template by just taking the template and setting the proguard version: https://github.com/JetBrains/compose-multiplatform/issues/3818#issuecomment-1921090223
Just to be sure: I did post a reproduction sample project
thank you color 1
m
I am using
Copy code
kotlin.version=1.9.22
agp.version=8.2.0
compose.version=1.6.0-dev1397
and built a fairly large application (compared to the various demos floating around) with it, which supports macOS (X86 & ARM), Windows and Linux. I also just upgraded to version 7.4.2 and did not notice any problems (if you don’t count the tens of thousands of notes and warnings that you get from ProGuard).
m
I'm using Kotlin 1.9.20 and Compose 1.5.11 (which were the latest production versions until 3 days ago)
... versions that the project wizard is still using
m
I haven’t used these old versions for a while.
When did the error that you describe happen and on which platform? I am developing and building on macOS Sonoma for example. (Windows and Linux on GitHub Action runners.)
m
Happened hours ago... using Ubuntu 23.10 with OpenJDK 17. Will see if I get the same result with JDK 21
Same result with JDK21
m
I can confirm that your example fails for me too on my Mac with the same error. The reason is that you did not switch off ProGuard optimization. With this
Copy code
buildTypes.release.proguard {
            obfuscate.set(false)
            optimize.set(false)
            version.set("7.4.0")
        }
setup your example works perfectly. I have noticed previously that optimization causes nothing but problems on desktop, so I always switch it off.
m
Optimize is enabled by default
Thank you for testing the example
Optimize is supported and enabled by default. Obfuscation is (as per the docs) supposed to be supported. So I'd say that's a bug
m
Actually I reported this error a long time ago and it was supposed to be fixed but it seems to have popped up again. https://github.com/JetBrains/compose-multiplatform/issues/3387
j
It looks like one of the VerifyError issues is the known issue relating to the
class/enum/unboxing
optimization which you can disable with
-optimizations !class/enum/unboxing
(https://github.com/Guardsquare/proguard/issues/349) There is different issue when disabling that specific optimization (not all VerifyErrors have the same cause) in one of the
androidx.compose
classes. You can also provide more targeted config than completely disabling optimizations, for example excluding classes from optimization that are causing issues:
Copy code
-keep,includecode,allowobfuscation,allowshrinking class androidx.compose.runtime.SnapshotStateKt** { *; }
Your sample works for me if you add the following to the
compose-desktop.pro
config:
Copy code
-optimizations !class/enum/unboxing
-keep,includecode,allowobfuscation,allowshrinking class androidx.compose.runtime.SnapshotStateKt** { *; }
You'll also need to tell the Compose build to use the config in the Gradle file:
Copy code
compose.desktop {
    application {
        mainClass = "MainKt"

        buildTypes.release.proguard {
            obfuscate.set(false)
            version.set("7.4.2")
            // Add this line
            configurationFiles.from(project.file("compose-desktop.pro"))            
        }

        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageName = "com.ustadmobile.pgvt"
            packageVersion = "1.0.0"
        }
    }   
}
m
@James Hamilton Many thanks for the feedback. Can you also tell us what benefits we might expect from optimization when the code was generated with a modern compiler and is run only on desktop with the latest Java VM. I am still wondering what kind of optimizations any tool could still do which a modern desktop Java cannot or just doesn’t do for whatever reason.
j
The optimizations are not just about runtime performance optimizations though some of them are and those may not be as applicable these days as they used to. The other reason to do the optimizations is for shrinking. If you can e.g. remove the uses of a class by some optimization then you can remove the class. For example, if you have an unused parameter which has some class type, the class will be kept by the shrinking step but there is an optimization that removes unused parameters where possible. The shrinker is re-executed after each optimization pass because more classes, methods and fields could become removable. It depends on your application though, so it's best to test it out for your use-case to see how much it improves shrinking and/or performance. You can control which optimizations are applied with the
-optimizations
option: the available optimizations are listed here https://www.guardsquare.com/manual/configuration/optimizations In the sample in the comment above, in terms of classes removed: the shrinking step on it's own removes a lot of the unused classes:
Copy code
Removing unused program classes and class elements...
  Original number of program classes:            8964
  Final number of program classes:               4397
Then after 1 optimization pass, some more are removed:
Copy code
Removing unused program classes and class elements...
  Original number of program classes:            4397
  Final number of program classes:               4226
If you do another pass (
-optimizationpasses 2
), a few more are removed:
Copy code
Removing unused program classes and class elements...
  Original number of program classes:            4226
  Final number of program classes:               4192
🙏 1
👀 1
m
Thank you @James Hamilton for that extra info. I think Proguard is doing what it is supposed to do here, and it is essential to get JVM-based desktop app sizes to be more reasonable. The problem is that those publishing / distributing libraries and frameworks need to support it publishing rules for shrinking / optimization (especially when they say that it is supported as per docs on stable releases). In the perfect world, automatic consumption of rules from libraries would be great. Just documenting the rules would be a major start. As I said above, I think all example projects should have optimization and obfuscation enabled so that such issues would be more likely to surface before release.
👍 1
m
@James Hamilton Many thanks for the clarifying infos. But I think I will wait with optimization until this has stabilized and works without problems out of the box. I also don’t see any reason trying to squeeze out the last byte from my code as long as we are just waisting more than 20 MB like this: Intel binary in ARM library But I’ll keep an eye on it.
👍 1
353 Views