compose-multiplatform
compose-multiplatform copied to clipboard
Failing to use Compose runtime in common code targeting native
Failing to compile simple Compose function targeting native code (iOS iosX64
or iosArm64
).
Kotlin 1.7.10
Jetbrains Compose 1.2.0-beta01
Compose compiler 1.3.0
Repo code is in this branch: https://github.com/kirillzh/kmm-production-sample/tree/common-compose.
// shared/src/commonMain
@Composable
fun Foo() {
}
Error:
> Task :shared:linkDebugFrameworkIosSimulatorArm64 FAILED
w: Mimalloc allocator isn't supported on target ios_simulator_arm64. Used standard mode.
e: Compilation failed: No file for com.github.jetbrains.rssreader/Foo|4071909078632269291[0] (@ com.github.jetbrains.rssreader/Foo|4071909078632269291[0]) in module `<RssReader:shared>`[ModuleDescriptorImpl@57d43629]
* Source files:
* Compiler version info: Konan: 1.7.10 / Kotlin: 1.7.20
* Output kind: FRAMEWORK
e: java.lang.IllegalStateException: No file for com.github.jetbrains.rssreader/Foo|4071909078632269291[0] (@ com.github.jetbrains.rssreader/Foo|4071909078632269291[0]) in module `<RssReader:shared>`[ModuleDescriptorImpl@57d43629]
at org.jetbrains.kotlin.backend.common.serialization.BasicIrModuleDeserializer.deserializeIrSymbol(BasicIrModuleDeserializer.kt:95)
Full Error
> Task :shared:linkDebugFrameworkIosSimulatorArm64 FAILED
w: Mimalloc allocator isn't supported on target ios_simulator_arm64. Used standard mode.
e: Compilation failed: No file for com.github.jetbrains.rssreader/Foo|4071909078632269291[0] (@ com.github.jetbrains.rssreader/Foo|4071909078632269291[0]) in module `<RssReader:shared>`[ModuleDescriptorImpl@57d43629]
* Source files:
* Compiler version info: Konan: 1.7.10 / Kotlin: 1.7.20
* Output kind: FRAMEWORK
e: java.lang.IllegalStateException: No file for com.github.jetbrains.rssreader/Foo|4071909078632269291[0] (@ com.github.jetbrains.rssreader/Foo|4071909078632269291[0]) in module `<RssReader:shared>`[ModuleDescriptorImpl@57d43629]
at org.jetbrains.kotlin.backend.common.serialization.BasicIrModuleDeserializer.deserializeIrSymbol(BasicIrModuleDeserializer.kt:95)
at org.jetbrains.kotlin.backend.common.serialization.IrModuleDeserializer.declareIrSymbol(IrModuleDeserializer.kt:74)
at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.findDeserializedDeclarationForSymbol(KotlinIrLinker.kt:127)
at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.deserializeOrResolveDeclaration(KotlinIrLinker.kt:169)
at org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker.getDeclaration(KotlinIrLinker.kt:158)
at org.jetbrains.kotlin.ir.util.ExternalDependenciesGeneratorKt.getDeclaration(ExternalDependenciesGenerator.kt:57)
at org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator.generateUnboundSymbolsAsDependencies(ExternalDependenciesGenerator.kt:44)
at org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator.generateUnboundSymbolsAsDependencies(ModuleGenerator.kt:52)
at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:92)
at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment$default(Psi2IrTranslator.kt:75)
at org.jetbrains.kotlin.backend.konan.PsiToIrKt.psiToIr(PsiToIr.kt:187)
at org.jetbrains.kotlin.backend.konan.ToplevelPhasesKt$psiToIrPhase$1.invoke(ToplevelPhases.kt:120)
at org.jetbrains.kotlin.backend.konan.ToplevelPhasesKt$psiToIrPhase$1.invoke(ToplevelPhases.kt:118)
at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$namedOpUnitPhase$1.invoke(PhaseBuilders.kt:96)
at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$namedOpUnitPhase$1.invoke(PhaseBuilders.kt:94)
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96)
at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:29)
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96)
at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:43)
at org.jetbrains.kotlin.backend.konan.KonanDriverKt.runTopLevelPhases(KonanDriver.kt:40)
at org.jetbrains.kotlin.cli.bc.K2Native.doExecute(K2Native.kt:94)
Moving Composable function under a class/interface, gives a bit different error:
// shared/src/commonMain
interface Example {
@Composable
fun Foo() {
}
}
Error:
e: java.lang.AssertionError: Unbound symbols not allowed
Unbound public symbol IrSimpleFunctionPublicSymbolImpl: com.github.jetbrains.rssreader/Example.Foo|4071909078632269291[0]
at org.jetbrains.kotlin.ir.util.SymbolTableKt.noUnboundLeft(SymbolTable.kt:1141)
at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:96)
at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment$default(Psi2IrTranslator.kt:75)
at org.jetbrains.kotlin.backend.konan.PsiToIrKt.psiToIr(PsiToIr.kt:187)
at org.jetbrains.kotlin.backend.konan.ToplevelPhasesKt$psiToIrPhase$1.invoke(ToplevelPhases.kt:120)
at org.jetbrains.kotlin.backend.konan.ToplevelPhasesKt$psiToIrPhase$1.invoke(ToplevelPhases.kt:118)
at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$namedOpUnitPhase$1.invoke(PhaseBuilders.kt:96)
at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$namedOpUnitPhase$1.invoke(PhaseBuilders.kt:94)
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96)
Possible related to https://github.com/JetBrains/compose-jb/issues/2342
I'm getting the exact same issue. Just adding @Composable
is bringing this error
Can you please try version 1.3.0-alpha01-dev849
and add to gradle.properties: kotlin.native.cacheKind=none
I'm getting the exact same issue. Just adding
@Composable
is bringing this error
I fixed my issue by making the @Composable
function internal
🤦♂️
Maybe relates with https://github.com/JetBrains/compose-jb/issues/2386 and https://github.com/JetBrains/compose-jb/issues/2342
I'm also getting this issue, which was also fixed by marking my composable internal!
@dima-avdeev-jb, I'm understanding that it's not currently possible to make a Composable function public in common code while targeting native.
This is blocking us from being able to modularize the code with Composables, and most importantly being able to incrementally migrate Android logic into shared code base incrementally.
Is there a fix for this in some dev release, and if not, would you have an estimate for when this is planned to be fixed?
@kirillzh Yes, you can't use public Composable functions in iOS for now. But, you can use internal functions.
@kirillzh Except for the composable function of the module finally used in iOS, it is okay to use the public composable function.
For example, I use feature-wise modular like below
graph TD;
A[feature1] --> |Public Composable function| C[presentation]
B[feature2] --> |Public Composable function| C
C --> |Internal Composable function| D[iosApp]
In this case, public composable functions in feature1 and feature2 are available.
Hi @TaehoonLeee, could you share a simple example of what you described. I tried on my side and still no way to expose a Composable in iOS target. This feature is important since many organizations would want to have a shared-ui library, made of components that other iOS projects consume as Composables, not as UIViewControllers.
@pablichjenkov
It is impossible to use composable functions directly on iOS target. Therefore, all the composable functions in the module exported to the iOS target must be specified as internal.
However, the composable functions in other modules may be public. Using this point, it seems possible to modularize composable function.
https://github.com/TaehoonLeee/multi-module-clean-architecture/tree/multi-platform
In above project the iOS app uses presentation module only. So the composable functions written in the presentation module should be internal. And the others in the other modules are can be public.
My English is limited. I ask for your understanding.
@TaehoonLeee , Don't worry about the English mine is probably worst. I believe now I understand better what you explained before, and you are right, the only module affected is the last one used in the iOS interoperability. Saying so, the issue can really be categorized as minor. Thank you so much for your help. It could be really beneficial to document this behavior somewhere. When you get the error the first time, it makes you think that Composables cannot be public in libraries and that is not correct at all. It is only the last library consumed by the iosApp the one enforcing the internal constraint and only for ios target.
Do we know if this is resolved by compose compiler 1.4.0 and Kotlin 1.8.20? I'm seeing similar mentions in other related issues such as https://github.com/JetBrains/compose-multiplatform/issues/2901#issuecomment-1504894914
Do we know if this is resolved by compose compiler 1.4.0 and Kotlin 1.8.20? I'm seeing similar mentions in other related issues such as https://github.com/JetBrains/compose-multiplatform/issues/2901#issuecomment-1504894914
Yeup, got fixed in 1.4.0
Wohoo!
Fixed in Compose 1.4.0
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.