Support for Compose Resources in native macOS executables.
- Added a new integration test `macosExecutableResources` to verify
resource copying for macOS executables.
- Updated `configureNativeApplication.kt` to pass Compose resource
directories from Kotlin Native binaries to the packaging task.
- Resources are now copied into the `.app/Contents/Resources` directory
for packaged macOS applications.
- Packaging tasks for macOS now depend on the corresponding resource
copying task.
## Testing
Executing tasks: [:compose:test-Gradle(9.0.0)-Agp(8.9.0), --tests,
org.jetbrains.compose.test.tests.integration.ResourcesTest.macosExectuableResources]
## Release Notes
### Fixes - Resources
- Fixed an issue where resources were not copied when packaging the
macOS native target, causing the application to crash when it attempted
to read those resources.
This PR is a supposed fix for
https://youtrack.jetbrains.com/issue/CMP-8990
Basically the problem is that `copyRecursively` does not guarantee
execution flag to be preserved
## Testing
`./gradlew checkComposeCases`
## Release Notes
N/A
It fixes Robolectric tests where a context is available through
InstrumentationRegistry
Fixes https://youtrack.jetbrains.com/issue/CMP-6612
## Release Notes
### Fixes - Resources
- Fix resource access in a Robolectric test environment.
Fixes https://youtrack.jetbrains.com/issue/CMP-6676
## Release Notes
### Features - Resources
- Add `setResourceReaderAndroidContext` to configure Android context in
cases when a provider initialization is not available.
I had a situation when the folder was empty, and the git log collected
commits from the parent repo compose-multiplatform instead of
compose-multiplatform-core
## Release Notes
N/A
- Remove windows skiko image (moved to skiko repo -
https://github.com/JetBrains/skiko/pull/1096)
- Combined into unified `linux-tests` image
- Preinstalled Android SDK allows removing this step from 4 build stages
- Ubuntu 22.04 -> 24.04
- Update JDK to 17 -> 21
- Update Google Chrome 121 -> 140, and use specifc pinned version
instead of "latest"
- Update Firefox 138 -> 142, and use specifc pinned version instead of
"latest"
Related fixes:
- CI change: https://jetbrains.team/p/ui/reviews/49
- Missing JDK 17 fix -
51a87ca55c
- Failing HTML tests on Chrome 140 - #5426
- Failing Compose Web test tests on Firefox 142 -
https://github.com/JetBrains/compose-multiplatform-core/pull/2398
## Release Notes
N/A
**Describe proposed changes and the issue being fixed**
Corrected grammar in documentation:
changed *"if you already runned this sample before"*
to *"if you already ran this sample before"*.
No other changes were made.
Provides `generateResourceContentHashAnnotation` property for
`generateResourceAccessorsFor*` tasks that defines whether to generate
`@ResourceContentHash` annotation for resource accessors.
The property can be set the following way:
```
tasks.configureEach {
if (this is org.jetbrains.compose.resources.ResourceAccessorsConfiguration) {
generateResourceContentHashAnnotation.set(true)
}
}
```
## Release Notes
### Features - Multiple Platforms
- Provide public API for `@ResourceContentHash` annotation generation
- Updated Gradle to support version 9.0.0.
- Improved Compose resource configuration to handle AGP versions below
8.10 with a fallback implementation.
- Bumped Kotlin to 2.2.0 release and updated related dependencies.
- Adjusted tests to reflect changes in AGP-specific behavior and
logging.
Fixes https://youtrack.jetbrains.com/issue/CMP-8771
## Release Notes
### Fixes - Gradle Plugin
- Support `AGP 9.0.0`
Used by Compose Hot Reload to mark a related accessor as dirty if the
hash is changed after reloading of new accessors.
Fixes [CMP-8513](https://youtrack.jetbrains.com/issue/CMP-8513)
## Release Notes
N/A
Fixes
https://youtrack.jetbrains.com/issue/CMP-8050/Desktop-runRelease-crash-when-upgrade-to-CMP-1.8.0-rc01
`./gradlew runRelease` throws an error:
```
Exception in thread "main" kotlinx.a.g: Serializer for class 'LoginRoute' is not found
```
in this code:
```
import androidx.compose.ui.window.singleWindowApplication
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import kotlinx.serialization.Serializable
fun main() = singleWindowApplication {
NavHost(
navController = rememberNavController(),
startDestination = LoginRoute()
) {
composable<LoginRoute> {}
}
}
@Serializable
data class LoginRoute(val id: Long? = null)
```
with obfuscation enabled:
```
compose.desktop {
application {
mainClass = "MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "org.jetbrains.nav_cupcake"
packageVersion = "1.0.0"
}
buildTypes.release.proguard {
obfuscate.set(true)
}
}
}
```
It crashes because:
- we use `@InternalSerializationApi kotlinx.serialization.serializer`
which is used by Navigation
- it uses reflection underneath. Looks like it tries to find serializer
2 ways:
- Looking at the field `static final LoginRoute.Companion.serializer`
- Looking at the `inner class LoginRoute.Companion` and its name
- The [the
default](https://github.com/Kotlin/kotlinx.serialization/blob/4667a18/rules/common.pro)
rules:
- [no obfuscation] work by the second way, but doesn't work by the first
- [with obfuscation] don't work by both ways
The new rule support the first for both obfuscated/non-obfuscated code
## Details
### Old rules
#### Without obfuscation
```
// LoginRoute.class
public final class LoginRoute {
public static final Companion Companion = new Companion((byte)0);
...
public static final class Companion {
private Companion() {}
}
}
// LoginRoute$Companion.class
public final class Companion {
private Companion() {}
}
```
#### With obfuscation
```
// LoginRoute.class
@Serializable
public final class LoginRoute {
public static final a Companion = new a((byte)0);
...
}
// a.class
public final class a {
private a() {}
}
```
### With new rule
#### Without obfuscation
```
// LoginRoute.class
@Serializable
public final class LoginRoute {
public static final Companion Companion = new Companion((byte)0);
...
public static final class Companion {
private Companion() {}
public final KSerializer<LoginRoute> serializer() {
return (KSerializer<LoginRoute>)LoginRoute.$serializer.INSTANCE;
}
}
}
// LoginRoute$Companion.class
public final class Companion {
private Companion() {}
public final KSerializer<LoginRoute> serializer() {
return (KSerializer<LoginRoute>)LoginRoute.$serializer.INSTANCE;
}
}
```
#### With obfuscation
```
// LoginRoute.class
@Serializable
public final class LoginRoute {
public static final a Companion = new a((byte)0);
...
}
// a.class
public final class a {
private a() {}
public final b serializer() {
return (b)LoginRoute$$serializer.INSTANCE;
}
}
```
## Testing
- new test
- snippet above doesn't produce the error anymore
## Release Notes
### Fixes - Desktop
Fix `runRelease` task when navigation and `obfuscate.set(true)` are used
Update Docker image for Skiko Windows build to the latest Windows Server
2022 and Visual Studio 2022
Also add LLVM to the image and avoid downloading it on every build
## Testing
Latest Skiko compiles successfully on CI
This should be tested by QA
## Release Notes
N/A
CompatibilityDistributionTest::testWebJsWasmReconfigured makes sure that
composeCompatibilityBrowserDistribution task can be reconfigured to be
used with arbitrary set of input tasks
## Testing
Pipeline
## Release Notes
N/A