Adding iOS dependencies
Apple SDK dependencies (such as Foundation or Core Bluetooth) are available as a set of prebuilt libraries in Kotlin Multiplatform projects. They do not require any additional configuration.
You can also reuse other libraries and frameworks from the iOS ecosystem in your iOS source sets. Kotlin supports interoperability with Objective-C dependencies and Swift dependencies if their APIs are exported to Objective-C with the @objc
attribute. Pure Swift dependencies are not yet supported.
Integration with the CocoaPods dependency manager is also supported with the same limitation – you cannot use pure Swift pods.
We recommend using CocoaPods to handle iOS dependencies in Kotlin Multiplatform projects. Manage dependencies manually only if you want to tune the interop process specifically or if you have some other strong reason to do so.
With CocoaPods
Perform initial CocoaPods integration setup.
Add a dependency on a Pod library from the CocoaPods repository that you want to use by including the
pod()
function call inbuild.gradle(.kts)
of your project.kotlin { cocoapods { //.. pod("FirebaseAuth") { version = "10.16.0" } } }kotlin { cocoapods { //.. pod('FirebaseAuth') { version = '10.16.0' } } }You can add the following dependencies on a Pod library:
Run Reload All Gradle Projects in IntelliJ IDEA (or Sync Project with Gradle Files in Android Studio) to re-import the project.
To use the dependency in your Kotlin code, import the package cocoapods.<library-name>
. For the example above, it's:
Without CocoaPods
If you don't want to use CocoaPods, you can use the cinterop tool to create Kotlin bindings for Objective-C or Swift declarations. This will allow you to call them from the Kotlin code.
The steps differ a bit for libraries and frameworks, but the idea remains the same.
Download your dependency.
Build it to get its binaries.
Create a special
.def
file that describes this dependency to cinterop.Adjust your build script to generate bindings during the build.
Add a library without CocoaPods
Download the library source code and place it somewhere where you can reference it from your project.
Build a library (library authors usually provide a guide on how to do this) and get a path to the binaries.
In your project, create a
.def
file, for exampleDateTools.def
.Add a first string to this file:
language = Objective-C
. If you want to use a pure C dependency, omit the language property.Provide values for two mandatory properties:
headers
describes which headers will be processed by cinterop.package
sets the name of the package these declarations should be put into.
For example:
headers = DateTools.h package = DateToolsAdd information about interoperability with this library to the build script:
Pass the path to the
.def
file. This path can be omitted if your.def
file has the same name as cinterop and is placed in thesrc/nativeInterop/cinterop/
directory.Tell cinterop where to look for header files using the
includeDirs
option.Configure linking to library binaries.
kotlin { iosArm64() { compilations.getByName("main") { val DateTools by cinterops.creating { // Path to the .def file definitionFile.set(project.file("src/nativeInterop/cinterop/DateTools.def")) // Directories for header search (an analogue of the -I<path> compiler option) includeDirs("include/this/directory", "path/to/another/directory") } val anotherInterop by cinterops.creating { /* ... */ } } binaries.all { // Linker options required to link to the library. linkerOpts("-L/path/to/library/binaries", "-lbinaryname") } } }kotlin { iosArm64 { compilations.main { cinterops { DateTools { // Path to the .def file definitionFile = project.file("src/nativeInterop/cinterop/DateTools.def") // Directories for header search (an analogue of the -I<path> compiler option) includeDirs("include/this/directory", "path/to/another/directory") } anotherInterop { /* ... */ } } } binaries.all { // Linker options required to link to the library. linkerOpts "-L/path/to/library/binaries", "-lbinaryname" } } }Build the project.
Now you can use this dependency in your Kotlin code. To do that, import the package you've set up in the package
property in the .def
file. For the example above, this will be:
Add a framework without CocoaPods
Download the framework source code and place it somewhere that you can reference it from your project.
Build the framework (framework authors usually provide a guide on how to do this) and get a path to the binaries.
In your project, create a
.def
file, for exampleMyFramework.def
.Add the first string to this file:
language = Objective-C
. If you want to use a pure C dependency, omit the language property.Provide values for these two mandatory properties:
modules
– the name of the framework that should be processed by the cinterop.package
– the name of the package these declarations should be put into.
For example:
modules = MyFramework package = MyFrameworkAdd information about interoperability with the framework to the build script:
Pass the path to the .def file. This path can be omitted if your
.def
file has the same name as the cinterop and is placed in thesrc/nativeInterop/cinterop/
directory.Pass the framework name to the compiler and linker using the
-framework
option. Pass the path to the framework sources and binaries to the compiler and linker using the-F
option.
kotlin { iosArm64() { compilations.getByName("main") { val DateTools by cinterops.creating { // Path to the .def file definitionFile.set(project.file("src/nativeInterop/cinterop/DateTools.def")) compilerOpts("-framework", "MyFramework", "-F/path/to/framework/") } val anotherInterop by cinterops.creating { /* ... */ } } binaries.all { // Tell the linker where the framework is located. linkerOpts("-framework", "MyFramework", "-F/path/to/framework/") } } }kotlin { iosArm64 { compilations.main { cinterops { DateTools { // Path to the .def file definitionFile = project.file("src/nativeInterop/cinterop/MyFramework.def") compilerOpts("-framework", "MyFramework", "-F/path/to/framework/") } anotherInterop { /* ... */ } } } binaries.all { // Tell the linker where the framework is located. linkerOpts("-framework", "MyFramework", "-F/path/to/framework/") } } }Build the project.
Now you can use this dependency in your Kotlin code. To do this, import the package you've set up in the package property in the .def
file. For the example above, this will be:
Learn more about Objective-C and Swift interop and configuring cinterop from Gradle.
What's next?
Check out other resources on adding dependencies in multiplatform projects and learn more about: