https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
u

ursus

02/19/2023, 2:44 AM
I have a project with 100+ gradle modules. Got a KMM proof of concept going, and now I'd like to start adding kmm support one by one. However ios devs tell me, there is a limit to the number of .frameworks in a single app Is this true? I cannot have say 50 kmm modules in a given ios app?
e

ephemient

02/19/2023, 2:49 AM
you want all your Kotlin modules to be built into a single monolithic framework for iOS
u

ursus

02/19/2023, 8:15 AM
right, but why? they say you would have like max 6 frameworks, which sounds odd to me as our android project has 200
e

ephemient

02/19/2023, 10:42 AM
JVM is traditionally lazy-loaded, so adding libraries is somewhat "free": you only pay the cost for what you actually execute. however iOS is not, and frameworks are either linked at build time (if static) or startup (if dynamic). there isn't a hard limit, but it increases app launch time. https://bpoplauschi.github.io/2021/10/25/Advanced-static-vs-dynamic-libraries-and-frameworks.html
u

ursus

02/19/2023, 10:56 AM
does static increase app start time as well?
per article it seems dynamic is slowest app startup and riskiest so why bother, build time?
e

ephemient

02/19/2023, 11:11 AM
to an extent, yes static increases app start time, but mostly as an effect that the larger an app binary is, the longer it takes to load
u

ursus

02/19/2023, 11:13 AM
then I'm confused .. if app startup corelates with binary size, then why is it preffered to have less bigger frameworks
e

ephemient

02/19/2023, 11:14 AM
dynamic linking has its uses, but I think the biggest reason for iOS is that in previous versions, Swift required dynamic linking
maybe you're still supporting those
u

ursus

02/19/2023, 11:16 AM
im probably confused on the difference between static and dynamic .. if dynamic is linked at runtime, is it sort of like thin vs far jars on jvm? i.e. bundled with os vs bundled with app?
e

ephemient

02/19/2023, 11:17 AM
everything on JVM is dynamic whether you have fat jars or not
u

ursus

02/19/2023, 11:17 AM
in terms of when classes are loaded?
e

ephemient

02/19/2023, 11:17 AM
JVM will link incrementally as each class is loaded (on first use), yes
u

ursus

02/19/2023, 11:18 AM
I see im familiar with that .. so ios dynamic framework is wholy loaded eagerly at app start?
e

ephemient

02/19/2023, 11:19 AM
depends
but typically yes
on native, binaries are loaded directly into memory, and then fixups need to be performed (due to differences such as load address) across the whole thing
u

ursus

02/19/2023, 11:20 AM
therefore static linking "pretends" that the framework code is my own source?
e

ephemient

02/19/2023, 11:20 AM
effectively yes
u

ursus

02/19/2023, 11:21 AM
so the downside is paying a penalty of long clean build time?
btw why is static faster to start, when as you said, on native everything is loaded into memory, regardless if its 3rd party or 1st party code .. I read it as code needs to be loaded, options are static vs dynamic, dynamic is loaded eagerly at app start, well then when is static loaded? somehow sooner? I would get if dynamic were lazy loaded like on jvm, but since its eager, doenst make much sense to me
e

ephemient

02/19/2023, 11:48 AM
static linking: linking into the binary at build time dynamic linking: linking into running executable there are multiple ways of using dyld (the dynamic linker), such as declaring in the program headers that these libraries/frameworks are required, which will cause them to be loaded immediately. you can avoid that, but need to be careful because there's no safety guards against calling a function in a library that hasn't yet been loaded (will crash)
frameworks default to dynamic because that's what makes sense on macos, where system frameworks are shared between all running executables and re-use the same memory (mostly, aside from fixups and other writable sections). static frameworks didn't even exist until recent iOS versions. static libraries were available since ~forever, but they don't support having resources
https://kotlinlang.org/docs/multiplatform-dsl-reference.html#native-targets Kotlin/Native can produce both static and dynamic frameworks
u

ursus

02/19/2023, 11:56 AM
wait, dynamic framework binary is not included in the app binary? just expected to be in the platform? like android shim jar?
e

ephemient

02/19/2023, 11:57 AM
both
a .app/.ipa can contain internal frameworks, and the system has frameworks
u

ursus

02/19/2023, 11:59 AM
but say app dynamically links Alamofire 3.2.1, then this code is physically able to be shared by different apps on the system?
e

ephemient

02/19/2023, 11:59 AM
no, because of iOS's sandboxing. it is possible on macos though
u

ursus

02/19/2023, 12:00 PM
okay so, does it make sense to have dynamic frameworks on ios at all? seems only downsides
e

ephemient

02/19/2023, 12:00 PM
the biggest reason is historical
but in any case, to bring this back to Kotlin: you still want all of your Kotlin code to be exported as a single umbrella framework, regardless of static or dynamic
u

ursus

02/19/2023, 12:01 PM
where the precedens is what, dynamic?
e

ephemient

02/19/2023, 12:01 PM
yes
because K/N follows a closed-world compilation model, you can only share Kotlin objects within a single library/framework
(same as basically everything that targets native)
Objective-C/Swift are in a bit of a privileged position because of how they're built into the system
u

ursus

02/19/2023, 12:03 PM
and I would do that how, in terms of gradle, just have a :umbrella module which includes all other gradle modules necessary for the app business wise, and only expose umbrella.framework to the ios app?
e

ephemient

02/19/2023, 12:03 PM
yes
with re-exports of other modules as necessary, documented in links above
u

ursus

02/19/2023, 12:04 PM
because, cost of a module loaded is mostly amortized, so 1 big with size of 1 is better than 2 with size of 0.5?
e

ephemient

02/19/2023, 12:05 PM
no. because if you have two frameworks, the type of a kotlin object in one framework is not the same as the type of a kotlin object in the other framework, even if they were compiled from the same shared module
u

ursus

02/19/2023, 12:05 PM
oh, I see
btw if I have the .framework file, does it imply if its static or dynamic, or can it be both
also, given macOS and dynamic framework .. I would bundle the binary with app binary, i.e. it is physically there, but if some other app would already load the exactly same framework, only a single "instance" of framework is in the memory ..i.e. its only a runtime optimization (which is not the same as thin vs fat jars, where you optimize binary physical size)
e

ephemient

02/19/2023, 12:14 PM
it's one or the other
I believe memory is only shared if it is mapped from the same physical file
(memory deduplication does exist on some platforms, but I am not aware of it being a thing on macos)
u

ursus

02/19/2023, 12:18 PM
yes but just by having .framewkrk file, I cannot tell? Would I need to inspect some internals? Or is it how it is used where the difference is? i.e. same .framework file can be both be used statically in app A and dynamically in app B?
e

ephemient

02/19/2023, 12:20 PM
you have to inspect the binary file inside the framework to determine if it is static or dynamic
u

ursus

02/19/2023, 12:21 PM
I see btw when a pure ios project, no kotlin, pulls in dependencies via cocoapods or spm, those are dynamic. frameworks by default?
e

ephemient

02/19/2023, 12:26 PM
depends on the dependency
u

ursus

02/19/2023, 12:27 PM
why, doesnt cocoapods by default pull in sources via git and compile on your machine?
e

ephemient

02/19/2023, 12:28 PM
it allows the dependency to declare whether it should be built as static or dynamic
u

ursus

02/19/2023, 12:29 PM
but regardless of static or dynamic, it's built on my machine, right? Or can it just "add" a prebuilt binary as well? which is what kmm uses?
e

ephemient

02/19/2023, 12:30 PM
yes
u

ursus

02/19/2023, 12:31 PM
btw why do they do that? why no "maven" hosting pre built binaries? historic reasons?
e

ephemient

02/19/2023, 12:33 PM
an Xcode project doesn't know how to consume artifacts from Maven
it doesn't really know anything outside of local dependencies, which is how we ended up with third-party solutions like cocoapods
u

ursus

02/19/2023, 12:36 PM
yes but for sake of argument, let's say cocoapods is gradle, there is the maven bit still missing, and all cocoapods dependencies I've seen are pulled in via link to github repo, seems odd to me they didn't do that part, so much cpu wasted?
SPM should host the pre built binaries, right?
e

ephemient

02/19/2023, 12:37 PM
cocoapods piggy-backed off of the free-ness of GitHub instead of building their own infrastructure
I haven't used SPM but it does seem to support a more traditional package registry
u

ursus

02/19/2023, 12:41 PM
okay but the actual linking config, that is a xcode thing, right? xcode knows nothing about cocoapods, right?
e

ephemient

02/19/2023, 12:41 PM
right. pod just puts everything into place for xcode to find
u

ursus

02/19/2023, 12:44 PM
okay so say I have a monorepo, which's point is to share code between android and ios (and lets say ios has no 3rd party libaries) .. or lets just say a pure ios codebase, lets say its two apps, Uber and Uber-Rider, and they want to share code -- then there is no need to use cocoapods, right?
e

ephemient

02/19/2023, 12:45 PM
you can still use cocoapods with an private git repo
u

ursus

02/19/2023, 12:45 PM
yes but let's say its a monorepo
would you still use cocoapod to dependency manage internal frameworks?
e

ephemient

02/19/2023, 12:46 PM
if you're already using pods for external dependencies then yes
u

ursus

02/19/2023, 12:46 PM
why
e

ephemient

02/19/2023, 12:47 PM
so you can uniformly manage all the pods, both your app's direct dependencies and your internal frameworks' dependencies
u

ursus

02/19/2023, 12:49 PM
I see, but don't you then need to
pod install
anytime you change a public api in the shared code?
e

ephemient

02/19/2023, 12:51 PM
I don't work on iOS but as far as I know, not with local pods
u

ursus

02/19/2023, 12:52 PM
I do a little bit, hence my queries on kmm, but maybe a its a xcode thing, that I dont see latest stuff
do you by chance have any insight on how would say the Uber and UberRider projects looks like? To me it kind of feels like ios doesn't want such granular modules like android does, I could imagine that those two on android would consist of 300+ modules
or is it just a feeling? (that they would like to have 10 at most)
btw, the issue of having many dynamic frameworks - assuming pure ios environment - would that be able to be workedaround via the
umbrella
approach from kmm as well?
11 Views