Given that I’ve said I can’t use Gradle, telling me to use Gradle isn’t really helping!
In fact, I’ve made it work, mostly. Turns out that the reason why you can only build common/platform modules with Gradle is that, AFAICT, they don’t actually exist outside Gradle’s imagination: there’s no common module build artifact, and all Gradle does is keep track of which source files were in the common module so that they can be compiled alongside the platform module. (This is based on observing kotlin native, which Gradle invokes by calling the executable via a shell. JVM and JS might work differently.)
It appears that expect/actual only work if the compiler can see both source files at the same time. Trying to build a library containing just expects doesn’t work.
So I’ve restructured my app to use DI and interfaces rather than expect/actual and it’s all happy; and I used my new-found knowledge to bodge up some rather shoddy Bazel macros for building JVM, JS and native: stellation/kotlin.bzl at stellation6 · davidgiven/stellation · GitHub Performance isn’t the best because shelling out to the compiler’s quite a lot slower than Gradle’s persistent compiler process, and all the paths are harcoded, but it all mostly works.
The mostly is because I think that Konan’s library support is a bit flaky, and I’m using lots, and it’s sometimes behaving very weirdly. (Currently it’s refusing to admit that a library exists, even though I can see the compiler’s opened and read it.) I’m still investigating that.