It would be nice if there was the inverse of `@Hid...
# kotlin-native
a
It would be nice if there was the inverse of
@HiddenFromObjC
, where you can expose public APIs for Kotlin, then disable ObjC export of public APIs (unless explicitly allowed) by default. I’ve seen issues with Obj-C export with some cases where it just craps out, I think it may have been some public compose functions. We took the approach of literally marking EVERYTHING as
internal
unless explicitly required. The alternative being obscene levels of modularisation and explicitly exporting modules with things you need on Swift/ObjC side.
a
Are you using library mode? It would enforce you pick visibility for your modules , this way you don’t accidentally leak APIs unless you want them public
a
I don’t think this will help in this case. I want to expose public APIs to other Kotlin modules, with a very small amount of APIs exposed to ObjC without having to annotate 90% of the API surface with
@HiddenFromObjC
. Basically, it would be a lot less cumbersome if it was possible to explicitly export a select few APIs. As it stands, my only option is to split into 2 modules and do the following: 1. module A with the public API that I want to export to ObjC 2. module B with the public API that I don’t want to export to ObjC, but available in consuming Kotlin modules (this would depend on the module A) 3. The consuming shared/composeApp module then has: a. an api dependency for module A with ObjC export b. an implementation dependency for module B without ObjC export
TL;DR: a single module compose app created from the Jetbrains KMP project wizard will leak every public API in the top level composeApp module unless explicitly marked as internal, so it’s not a problem exclusive to library authors. The problem is worsened by some public APIs causing compilation failures due to the export process not liking some things that you probably didn’t want to export anyway, where modularisation becomes the only option.
r
FYI you can use explicit API mode even for non-library modules. It definitely helps to pick a visibility instead of everything just being public automatically.
The problem is worsened by some public APIs causing compilation failures
Please report those, if they haven’t already been reported.
where modularisation becomes the only option.
True, but IMO most of the time this is fairly straightforward. Could you share some more details on your use case regarding wanting to share declarations with other Kotlin modules, but not with ObjC consumers? Why aren’t such declarations needed in ObjC, and why would you still like them to be in the shared Kotlin module? E.g. what is the issue with having another Kotlin module with the common Kotlin declarations (that isn’t used from ObjC)?
a
I'll try to dig out the exact case that was failing the export process as it was a while ago now, but from what I remember it was some
@Composable
declaration it wasn't happy about. In a typical compose multiplatform app, there is very little that needs to be be exported for Swift/ObjC, which is obviously not the case for a more traditional KMP app where you would need access to much more of the shared code from the Swift side.
x
I will share my usage scenarios here. Background: In the ObjC layer, we had to enable
-ObjC
because we used Categories, which resulted in the loss of the linker's ability to strip unused code in ObjC. Although the
explicit API mode
can solve this problem, due to the good strip (Code shrinking) capabilities of Kt-jvm and agp, a large number of our codes that have been ported from Kt-jvm to kt-Native (iOS) also do not have clear markings for visibility. Often, the interface layer of iOS only needs a very small number of interfaces, which binds a large amount of ObjC code, resulting in a huge waste of size. We have calculated that the same Kotlin symbol may be 7-8 times larger after one ObjC binding. So I also think it would be nice if there's a reverse operation for
@HiddenFromObjC
. By the way, I'm trying to implement a Kotlin Compiler Plugin to add
@HiddenFromObjC
to Symbols by default. I tried adding annotations in the
IrGenerationExtension
phase, but it didn't seem to work. I need some hints on which phase I should start with?...
r
Unfortunately it isn't possible to add
@HiddenFromObjC
annotation with a plugin. The ObjC export uses FIR output which doesn't provide a way to add the annotations.
🫠 1
l
It sure wound be nice if the default visibility was
internal
.
💯 1
x
We could do that with -Xbinary=objcExportEntryPointsPath=export-entrypoints.txt https://github.com/JetBrains/kotlin/commit/9ef93a1ad5ff0e31375d7d588d261cc498bb0802