Feature request / discussion: “Thin” Kotlin/Native Apple frameworks (shared runtime/deps; non-self-contained framework)

Context

Hi Kotlin team and community,

We are using Kotlin Multiplatform with Kotlin/Native to build and ship Apple frameworks (XCFrameworks) for a large modularized codebase. We want to split our deliverables
into two Apple frameworks:

  • Foundation framework: provides common runtime & platform layers

  • Business framework: provides only business APIs (still exported as ObjC/Swift headers generated by Kotlin/Native)

The Business framework depends on Foundation.

The problem

By default, Kotlin/Native frameworks are effectively self-contained closures: each framework binary typically embeds Kotlin/Native runtime + stdlib + transitive KMP deps (e.g., kotlinx.coroutines, our platform modules), which causes:

  1. Huge size duplication when we ship multiple K/N frameworks

  2. Potentially dangerous behavior if duplication is not caught at link time (e.g. multiple runtime/global singletons, type metadata, etc.)

  3. Difficulties building a layered “Foundation provides everything; Business is thin” architecture

We specifically want the Business framework to not embed:

  • Kotlin/Native runtime / stdlib

  • kotlinx.coroutines (and other shared deps)

  • our platform modules (KMP modules used by business APIs)
    and instead have these resolved by linking against the Foundation framework.

We still require:

  • Business APIs must be exposed via Kotlin-generated ObjC headers (ObjCExport / framework generation)

  • Headers are allowed to reference types from Foundation (i.e., Business headers may depend on Foundation’s types)

Why this matters

In large modular projects, it’s common to split deliverables into multiple “SDK frameworks”. In Apple-native ecosystems (ObjC/Swift), we can usually create a “thin framework” that depends on another framework and does not re-package all common code.

With Kotlin/Native frameworks, this “thin consumer framework” model seems difficult because of how K/N links and packages runtime and deps by default.

Additional constraints: cinterop + dynamic frameworks

We also use cinterop to interact with iOS native code via headers. In our case, the implementation lives in a source Pod (from another iOS repo) with many dependencies.
That leads to an additional complication:

  • When building dynamic frameworks, linkers require all symbols to be resolved within the framework’s link closure (including cinterop symbols). If the native implementation is only present at app link time (or in a different repo/pod closure), the dynamic framework build fails.

  • As a result, we currently ship static frameworks as a workaround (undefineds can be resolved at final app link step), but our long-term goal is still to have a clean layered solution and avoid duplication.

What we are asking for (feature idea)

A first-class, officially supported way to build a Kotlin/Native Apple framework in a non-self-contained / thin mode:

Proposed capability

For a given K/N framework binary, allow:

  1. Do not embed Kotlin/Native runtime/stdlib and selected transitive dependencies (kotlinx, etc.)

  2. Still generate ObjC headers / Swift module as usual

  3. Link against another framework (e.g., -framework FoundationFramework) so unresolved symbols are resolved there

  4. Ideally offer predictable tooling for distribution (XCFramework, CocoaPods integration, etc.)

This could be presented as:

  • a Gradle DSL option (e.g. framework { sharedRuntime = true } / embedRuntime = false / thinFramework = true)

  • or compiler/linker flags controlling default libs (like a K/N equivalent to -nodefaultlibs / “do not link default runtime libs into this binary”)

  • plus explicit exported dependency frameworks

Optional: control symbol exporting

Even if dependencies are not embedded, it would also be very helpful to:

  • restrict exported symbols to only the API surface (ObjCExport + public Kotlin declarations), to reduce symbol pollution/conflicts.

Questions to Kotlin team

  1. Is the Kotlin/Native team planning any “shared runtime / thin framework” feature for Apple frameworks?

  2. What is the recommended official approach today for:

    • splitting multiple K/N frameworks without duplicating runtime/stdlib/kotlinx?
    • having one “foundation” framework provide shared dependencies?
  3. Are there known limitations in K/N runtime/type system that make multiple-framework shared runtime risky or unsupported?

  4. If this is not planned, what would be the correct design direction (compiler backend vs Gradle packaging vs link pipeline) to implement it safely?

  5. Any YouTrack issues or docs you can point to that are related?

Our current workaround (not ideal)

  • Ship everything as static frameworks and accept duplication / or attempt to flatten deliverables into a single framework.

  • Consider patching the K/N toolchain to support a “consumer framework” mode, but we’d prefer an official solution and guidance.

YouTrack issue

We have filed a feature request to track this officially:
KMT-2364 — [K/N] Allow building non-self-contained (“thin”) Apple frameworks

If you are facing a similar problem, please upvote the YouTrack issue to help prioritize it.

If anyone from Kotlin team/community has experience with similar architecture (multiple K/N frameworks, shared deps, or runtime sharing), we’d appreciate advice, references, or best practices — and feel free to comment on the YouTrack issue directly.

Thanks!

4 Likes