Multi-Module Setup
When your KMP project has multiple modules that each contribute DI bindings (e.g. feature modules, data module, domain module), you need to configure KSP so each module generates its own contributor and aggregate them at the app level. This page explains how.
Why Multi-Module?
In a large project, you might have:
- app — Entry point; aggregates all contributors
- feature-auth — Auth feature with its own bindings
- feature-home — Home feature with its own bindings
- data — Repositories, API
- domain — Use cases
Each module that has @Inject classes or @Module classes needs to generate a contributor. You then aggregate them in the app module and pass them to Anchor.init().
Step 1: Per-Module KSP Option
In each feature or shared module that has DI bindings, add the KSP plugin and the module ID option:
// feature-auth/build.gradle.kts
plugins {
id("com.google.devtools.ksp")
}
dependencies {
implementation("io.github.12345debdut:anchor-di-api:x.x.x")
implementation("io.github.12345debdut:anchor-di-core:x.x.x")
add("kspCommonMainMetadata", "io.github.12345debdut:anchor-di-ksp:x.x.x")
add("kspAndroid", "io.github.12345debdut:anchor-di-ksp:x.x.x")
add("kspIosArm64", "io.github.12345debdut:anchor-di-ksp:x.x.x")
add("kspIosSimulatorArm64", "io.github.12345debdut:anchor-di-ksp:x.x.x")
}
ksp {
arg("anchorDiModuleId", "auth")
}
This generates AnchorGenerated_auth instead of the default AnchorGenerated. Each module should have a unique anchorDiModuleId (e.g. auth, home, data, app).
Step 2: Aggregate Contributors in App Module
In your app module, collect all contributors and pass them to Anchor.init():
// app — commonMain (expect)
expect fun getAnchorContributors(): Array<ComponentBindingContributor>
// app — androidMain (actual)
actual fun getAnchorContributors(): Array<ComponentBindingContributor> = arrayOf(
AnchorGenerated_app,
AnchorGenerated_auth,
AnchorGenerated_home,
AnchorGenerated_data
)
// app — iosArm64Main and iosSimulatorArm64Main (actual)
actual fun getAnchorContributors(): Array<ComponentBindingContributor> = arrayOf(
AnchorGenerated_app,
AnchorGenerated_auth,
AnchorGenerated_home,
AnchorGenerated_data
)
Order: The order of contributors can matter if modules override bindings (though typically you avoid overrides). List them in a consistent order (e.g. app, then features, then data).
Step 3: Module Dependencies
- Each module that contributes bindings needs
anchor-di-api,anchor-di-core, andanchor-di-ksp. - The app module must depend on all feature/data modules so the generated
AnchorGenerated_*classes are on the classpath. - Use the same
anchorDiModuleIdfor a given module across all targets (commonMain, android, ios, etc.).
Example Layout
project/
app/ — anchorDiModuleId: "app"
feature-auth/ — anchorDiModuleId: "auth"
feature-home/ — anchorDiModuleId: "home"
data/ — anchorDiModuleId: "data"
app depends on feature-auth, feature-home, and data. Each generates its own contributor. The app's getAnchorContributors() returns all of them.
Next Steps
- Installation Setup — Full installation guide
- Platform-Specific Setup — iOS KSP setup and more