· 2 min read

arst

Reduce your API Surface

Code that is exported in the header directly to Swift requires additional binary to handle that communication and overhead. This can add significant binary to the total.

The code that is actually called directly from Swift is usually a small subset of the total Kotlin code that exists in your KMP. The Kotlin compiler does not know what code you plan to call from Swift, so it will export anything public and reachable from the module generating the Framework. When we audit KMP code, teams almost universally will expose dependencies and code that Swift does not need, which results in extra binary that serves no purpose.

Additionally, you can configure the Kotlin compiler to export modules and dependencies to Swift that otherwise would not be. This is often useful and necessary, but needs to be done with care. Kotlin also lets you transitively export dependencies. Doing so makes accessing code from Swift simpler, but is almost never needed, and can have a significant, negative impact on both your binary size and header size, thereby also decreasing readability of your KMP API.

The general rules:

  • Mark structures that don’t need public visibility as internal
  • Don’t export dependencies unless necessary, and minimize the public surface of those that you do
  • Never transitively export
  • Be careful with types of parameters and return values. Making a type from a dependency visible requires dragging in everything it exports. This can dramatically increase the export size
  • Consider isolating portions of your code in modules that aren’t globally exported, but only referenced with parameters and return types, which will be selectively and minimally exported.
  • Be careful with code-generation tools. They often expose code you don’t need directly.