Adding Swift packages as dependencies to KMP modules
Kotlin Gradle plugin with SwiftPM import integration allows you to import Objective-C APIs from Objective-C and Swift code using SwiftPM dependencies declared for your Apple targets.
For transitive dependencies (projects that depend on those that use SwiftPM import), the Kotlin Gradle plugin automatically provides the necessary machine code from SwiftPM dependencies. For example, you don't need to do any additional configuration when running Kotlin/Native tests or linking a framework.
To configure your project:
Set up environment
To try out the SwiftPM import functionality, you need to use a specific development version of Kotlin. Keep in mind, this version is not intended for production.
To set up the Kotlin Multiplatform Gradle plugin:
In your
settings.gradle.ktsfile, add the development package repository for dependencies and plugins:dependencyResolutionManagement { repositories { maven("https://packages.jetbrains.team/maven/p/kt/dev") mavenCentral() } } pluginManagement { repositories { maven("https://packages.jetbrains.team/maven/p/kt/dev") mavenCentral() gradlePluginPortal() } }In your version catalog, apply the experimental version of the Kotlin Multiplatform Gradle plugin:
kotlin = "2.3.20-titan-222" [plugins] kotlin-multiplatform = "2.3.20-titan-222"Sync Gradle files and try adding a
kotlin.swiftPMDependencies {}block to thebuild.gradle.ktsfile in your KMP module.If the
swiftPMDependenciesname cannot be resolved, add the following block to the rootbuild.gradle.ktsfile to force the experimental Kotlin Multiplatform Gradle plugin version:buildscript { dependencies.constraints { "classpath"("org.jetbrains.kotlin:kotlin-gradle-plugin:2.3.20-titan-222") } }
Set up KMP IDE plugin
If you are using the Kotlin Multiplatform IDE plugin recommended for KMP projects, explicitly specify the path to the iOS project that is built from the KMP module.
In the build.gradle.kts file where you call the iosTarget.binaries.framework API, add the API call that sets the path:
Add and call SwiftPM dependencies
Configure build file
Specific SwiftPM dependencies can be added in the swiftPMDependencies block of the build.gradle.kts file, where your Apple targets are declared. For example, for Firebase:
SwiftPM integration is based on importing Clang modules. By default, the import mechanism automatically discovers Clang modules in specified Swift packages and makes all available modules accessible to Kotlin code — similar to how API visibility works in Swift and Objective-C.
To disable the default behavior and automatic module discovery, set the discoverClangModulesImplicitly to false. When module discovery is disabled, SwiftPM import uses product names as Clang module names.
To import Clang modules whose names differ from product names, use the importedClangModules parameter, for example:
Set platform constraints
Some SwiftPM dependencies may not compile or provide valid APIs for all targets in your build script. For example, the Google Maps SDK currently only supports iOS targets.
So, while your project only targets iOS, you don't need to declare platforms explicitly. But as soon as you add another target, for example, macOS, you need to specify the platform constraint for each dependency.
To make sure that a dependency is applied only for relevant compilations, specify the correct targets in the platforms parameter of a product specification:
Use imported APIs
Imported Objective-C APIs are contained in namespaces that start with the swiftPMImport prefix and end with Gradle names of the project and its group.
For example, the Kotlin build script specifies the group name as follows:
Here, groupName is the Gradle group name of the project, and subproject is the project name. Now you can import Firebase APIs in the iosMain source set of that module:
Additional import options
Importing local Swift packages
The SwiftPM import mechanism also allows importing Swift packages from the local file system.
Let's consider a Swift package with the following manifest, located in the /path/to/ExamplePackage directory:
To import it in your Kotlin build script, use the localSwiftPackage API:
Sync the Gradle files to perform SwiftPM import, then use the imported APIs in your Kotlin code:
Specific deployment versions
If your dependencies require a higher deployment version, specify it in the *MinimumDeploymentTarget parameter. For example, for iOS:
Location and version of Swift packages
Similar to Package.swift manifest files, you can specify the location and version of your Swift package in the swiftPackage() call. Both have a couple of mutually exclusive options.
To set the location, you can use a URL or a SwiftPM registry ID:
To specify the version, use the following Gradle- and Git-style version specifications:
Known limitations with dynamic Kotlin/Native frameworks
Currently, SwiftPM import integration doesn't support all edge cases that might arise when producing a dynamic Kotlin/Native framework. You might encounter issues during the build in Xcode or see warnings at runtime, for example:
Undefined symbols for architecture ...: "...", referenced from: ld: symbol(s) not found ...dyld: Symbol not found: ...objc[...]: Class _Foo is implemented in both /path/to/Shared and /path/to/Bar. This may cause spurious casting failures and mysterious crashes. One of the duplicates must be removed or renamed.
A general fix for these issues is to change the linkage mode of your framework by setting the isStatic property to true:
If you encountered any of these issues, need to keep isStatic=false, or if changing this property didn't help resolve build failures, let us know in our Slack channel. Get an invite and join #kmp-swift-package-manager.
What's next?
Learn more about switching from CocoaPods to SwiftPM dependencies in your KMP project.