When <exporting multiple modules> as an XCFramewor...
# multiplatform
g
When exporting multiple modules as an XCFramework, is there a way to optimize the binary size by limiting which components are included? I’m particularly interested in libraries like
Kotlinx_coroutines
,
Kotlinx_serialization
,
Koin
, which, as far as I understand, generate unnecessary Objective-C headers that could potentially be avoided. Is there a method to exclude unnecessary parts of these dependencies to reduce the size of the resulting binary? Example, I have a
moduleA
that depends on SQLDelight, where all SQL configurations (code generation, etc.) and DAOs are defined. I also have a
moduleB
that depends on
moduleA
and provides access to these DAOs. The XCF will export
moduleB
, and no SQLDelight code is included in the XCF (success!). Is this approach the best way to handle such use cases? (Actually this also applies to modules that do not use the export functionality)
đź‘€ 1
f
Do you use explicitApi() gradle ?
I mean, by default everything’s is public when building a kotlin framework, so everything are exposed. if you want to reduce the content exported, set your methods/class as internal.
your issue is an old subject...
g
When the code is mine, I can control what’s internal, @HiddenFromObjc etc… but with external dependencies is different
particularly with SQLDelight I could hide everything since the “database” module is not exported only the “dao access module”, so it’s ok.
but with kotlinx_coroutines or _serialization a lot of code is exported. Maybe it’s needed, honestly I don’t know, but I would like to play with it if possible, to see what optimisations could be done
f
Oh, you mean transitive dependencies and the generated associate code.
g
yes what’s get into
Headers.h
example:
Copy code
/**
 * @note annotations
 *   kotlinx.serialization.ExperimentalSerializationApi
*/
__attribute__((swift_name("Kotlinx_serialization_coreSerializersModuleCollector")))
@protocol WNSKotlinx_serialization_coreSerializersModuleCollector
@required
- (void)contextualKClass:(id<WNSKotlinKClass>)kClass provider:(id<WNSKotlinx_serialization_coreKSerializer> (^)(NSArray<id<WNSKotlinx_serialization_coreKSerializer>> *))provider __attribute__((swift_name("contextual(kClass:provider:)")));
- (void)contextualKClass:(id<WNSKotlinKClass>)kClass serializer:(id<WNSKotlinx_serialization_coreKSerializer>)serializer __attribute__((swift_name("contextual(kClass:serializer:)")));
- (void)polymorphicBaseClass:(id<WNSKotlinKClass>)baseClass actualClass:(id<WNSKotlinKClass>)actualClass actualSerializer:(id<WNSKotlinx_serialization_coreKSerializer>)actualSerializer __attribute__((swift_name("polymorphic(baseClass:actualClass:actualSerializer:)")));
- (void)polymorphicDefaultBaseClass:(id<WNSKotlinKClass>)baseClass defaultDeserializerProvider:(id<WNSKotlinx_serialization_coreDeserializationStrategy> _Nullable (^)(NSString * _Nullable))defaultDeserializerProvider __attribute__((swift_name("polymorphicDefault(baseClass:defaultDeserializerProvider:)"))) __attribute__((deprecated("Deprecated in favor of function with more precise name: polymorphicDefaultDeserializer")));
- (void)polymorphicDefaultDeserializerBaseClass:(id<WNSKotlinKClass>)baseClass defaultDeserializerProvider:(id<WNSKotlinx_serialization_coreDeserializationStrategy> _Nullable (^)(NSString * _Nullable))defaultDeserializerProvider __attribute__((swift_name("polymorphicDefaultDeserializer(baseClass:defaultDeserializerProvider:)")));
- (void)polymorphicDefaultSerializerBaseClass:(id<WNSKotlinKClass>)baseClass defaultSerializerProvider:(id<WNSKotlinx_serialization_coreSerializationStrategy> _Nullable (^)(id))defaultSerializerProvider __attribute__((swift_name("polymorphicDefaultSerializer(baseClass:defaultSerializerProvider:)")));
@end

__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Koin_coreKind")))
@interface WNSKoin_coreKind : WNSKotlinEnum<WNSKoin_coreKind *>
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable));
@property (class, readonly) WNSKoin_coreKind *singleton __attribute__((swift_name("singleton")));
@property (class, readonly) WNSKoin_coreKind *factory __attribute__((swift_name("factory")));
@property (class, readonly) WNSKoin_coreKind *scoped __attribute__((swift_name("scoped")));
+ (WNSKotlinArray<WNSKoin_coreKind *> *)values __attribute__((swift_name("values()")));
@property (class, readonly) NSArray<WNSKoin_coreKind *> *entries __attribute__((swift_name("entries")));
@end
Kotlinx_serialization_coreSerializersModuleCollector
,
Koin_coreKind
, etc… I cannot make them
@HiddenFromObjc
for instance. Maybe I need those, but still, would like to test and see 🙂 because manually I don’t call those methods.
f
I just did a little test
If you want to remove the generate code, you need to change all their visibility
for example, if Koin is exposed as non-internal, so it’s generated inside the objc header
all code needed by Koin for working
make all YOUR code referencing Koin as internal and no code is generated
I think this behavior is normal, and you need to play with the visibility
g
Ok, already doing that so maybe I hit the “best optimisation” for now