Hi! In our company we are starting to use KMP to s...
# multiplatform
a
Hi! In our company we are starting to use KMP to share logic and UI (with CMP). It ended up well but a couple of days ago I realized about the "umbrella" module needed so iOS XCFrameworks don’t get shipped with duplicated dependencies. This could potentially be an issue for us since we are just starting and we already have 3 different modules, each one in its own repository. So my question is, is the umbrella module the only solution? How would you handle a lot of modules with a lot of different teams maintaining them with out it to be a complete mess?
j
Hi, our situation may be interesting! We have a main Shared repo with some core modules (think networking, error handling) and features. It also hosts the [umbrella] module. We also have a separate repository B that depends on the core modules and outputs a feature module (klib, no XCFramework). The Shared repo's umbrella module depends on the feature module from repository B, to prevent duplicate code. This umbrella module is the only place an XCFramework is built. Our approach to this is still very fresh. I think it would scale to your situation too. A challenge is versioning: we're careful in following SemVer as to not introduce breaking changes that may crash on runtime if incompatible versions are mixed. We do binary compatibility validation with good backwards compatibility guarantees.
a
Thanks for the insights Jacob! I think we will need to implement something like that too. Can you tell me how do you manage versioning? I mean you increase the patch or the minor on every release? Or do you use release trains? How do you decide when a new version should be published? Because when several teams starts working on the single repo, there will be a lot of changes coming in and every team will like their changes to be published. How do you handle that mess? Also I would love to know how do you do backwards compatibility checks
j
We use semantic versioning (semver.org) and indeed increase the version on every release. We're currently still in a setup phase but the plan is to be backwards mostly backwards compatible. Maybe doing an aligned major version bump once in a while. For backwards compatibility, we use https://github.com/Kotlin/binary-compatibility-validator. It just prints the diffs in the PR overview, so there's extra attention to it.
a
Oh didn’t know that tool… so basically when you create a PR you add the text file produced by the Binary Compatibility Validator? Do you enforce something around that file? Also, when the PR is merged to main you increase the version? In that case, which version, minor or patch?
j
The text file is already there, and during CI we run the API check to see if it needs to be changed. If so, creator of the PR should run
apiDump
and commit the updated
.api
file, so it's extra clear in the PR that the public API changes For versions: we bump them per PR, major/minor/patch depending on the PR's contents
I'm a big fan of the https://github.com/mheap/require-checklist-action action. In our PR templates, we have some checklist items like "Updated changelog" or "Bumped version (if needed)". The action enforces that they're checked, and it's required, so it's a nice reminder to do those things we consider important for each PR
a
Oh great! This create a some checkpoints to allow for control before merging something, thank you for the insights! Will discuss these options with my team, I think that at least I have an idea now of how a single umbrella module can be managed
p
The reality is you always have to go through one only umbrella. You can have as many kotlin kmp modules as you want(could be different repos in different teams and including CMP). But they all will have to produce a
.klib
not an
xcframwork
. All these
klibs
will be compiled into a one single framework that your iOS App will consume.
1
a
So what is that klib format? Some articles I've been reading mention it but I haven’t see an explanation of what it is
p
Basically a zip file with the module code pre-compiled or pre-transpiled rather. It has all supported targets, Android has aar, js has js lib and native has LVVM code
a
Thanks @Pablichjenkov ! I googled a little bit about it today and it seems is the intermediate Kotlin representation that is used to, later, compile to the respective target. That makes sense and I understand now how KMP libs are distributed
👌 1