I've been through various iterations of experimenting with different ways of sharing KMP modules and it ultimately boils down to what the team is most comfortable with and what they're also comfortable explaining to new joiners. I find that good documentation is necessary regardless of whatever approach is taken.
A single (monorepo) is good but probably not always ideal, especially with larger teams with already existing workflows and setups. Sometimes, teams built like this prefer to leave their codebase separate and rely on a third shared module for KMP.
In my previous workplace, they started with copy-pasting the shared KMP code since the Android and iOS codebases were completely separate. The first initiative I implemented was to use git submodules for the shared module. It was painful integrating this with Github actions and Bitrise, but eventually worked out. The unit tests were written in the shared module and I don't recall us ever having a scenario where we needed to run unit tests again after making a change to the Android or iOS code. Tests that were platform-specific were run on their respective platform modules.
Managing the versions became hell though, especially for our git flow - we had to seek out certain commit hashes to push hotfixes and their respective commits which Android and iOS pointed to in the shared module were almost never in sync. Then to top it all up, there's the fact that not everyone is familiar with git submodules and that always led to inconsistencies and confusion.
The most promising outcome involved using
Touchlab's KmmBridge to publish Xcframework binaries to SPM while using maven to publish for Android. With some CI/CD manipulation, backed by extensive documentation on what we should do in certain scenarios, this enabled us achieve a consistent way of pushing out new code. It's a bit ironic that Touchlab did a 180° and recommended the opposite in their
https://touchlab.co/kmp-teams-use-source article. It felt like a breath of fresh air, particularly for the iOS developers when they just had to use SPM for the latest KMP code changes. I hooked it up via Github actions to be created on PR events, so creating a PR on the shared KMP codebase created a new SPM build which was uniquely identified by the library version + the unique incremental PR number. Surprisingly, this ended up making the iOS developers even more eager to write KMP code since they could easily experiment and test with SPM. And just like with git submodules, the unit tests on the shared module weren't affected by changes to the platform modules.