{"id":26555294,"url":"https://github.com/gobley/gobley","last_synced_at":"2025-03-22T10:25:54.971Z","repository":{"id":280390706,"uuid":"940359865","full_name":"gobley/gobley","owner":"gobley","description":"Embed Rust into your Kotlin Multiplatform project","archived":false,"fork":false,"pushed_at":"2025-03-18T05:21:37.000Z","size":1263,"stargazers_count":20,"open_issues_count":29,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-18T06:28:50.436Z","etag":null,"topics":["ffi","gradle","gradle-plugin","kotlin","kotlin-multiplatform","rust","rust-lang"],"latest_commit_sha":null,"homepage":"https://gobley.dev","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gobley.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-28T03:24:45.000Z","updated_at":"2025-03-18T05:21:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"f0ce00ff-28b9-489b-9841-a832afe52929","html_url":"https://github.com/gobley/gobley","commit_stats":null,"previous_names":["gobley/gobley"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gobley%2Fgobley","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gobley%2Fgobley/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gobley%2Fgobley/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gobley%2Fgobley/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gobley","download_url":"https://codeload.github.com/gobley/gobley/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244940177,"owners_count":20535568,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffi","gradle","gradle-plugin","kotlin","kotlin-multiplatform","rust","rust-lang"],"created_at":"2025-03-22T10:25:54.178Z","updated_at":"2025-03-22T10:25:54.956Z","avatar_url":"https://github.com/gobley.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gobley\n\n[![License](https://img.shields.io/github/license/gobley/gobley\n)](https://github.com/gobley/gobley/blob/main/LICENSE)\n[![Crates.io](https://img.shields.io/crates/v/gobley-uniffi-bindgen)](https://crates.io/crates/gobley-uniffi-bindgen)\n[![Gradle Plugin Portal](https://img.shields.io/maven-central/v/dev.gobley.gradle/gobley-gradle\n)](https://central.sonatype.com/artifact/dev.gobley.gradle/gobley-gradle)\n[![GitHub Actions Workflow Status](\nhttps://img.shields.io/github/actions/workflow/status/gobley/gobley/pr-build-test.yml?branch=main\u0026label=tests)](\nhttps://github.com/gobley/gobley/actions/workflows/pr-build-test.yml?query=branch%3Amain)\n\nKotlin Multiplatform bindings generation for [UniFFI](https://github.com/mozilla/uniffi-rs).\nThis project was forked from [UniFFI Kotlin Multiplatform bindings](https://gitlab.com/trixnity/uniffi-kotlin-multiplatform-bindings).\nSince the original project is no longer maintained, active development now continues here.\n\nCurrently, Android, Kotlin/JVM, and Kotlin/Native are supported. WASM is not supported yet.\n\n# Features\n\n- Bindings Generation for Kotlin Multiplatform (Android, JVM, Kotlin/Native)\n- [KotlinX Serialization Support](#bindgen-configuration)\n- [Automatic building and linking of Rust libraries to Kotlin projects](#the-cargo-plugin)\n\n# Getting started\n\nWe recommend to first read the [UniFFI user guide](https://mozilla.github.io/uniffi-rs/). Then, please read this documentation in the following order.\n\n- [Development environment and common development practices](#development-environment-and-common-development-practices)\n- [Using the Gradle plugin](#using-the-gradle-plugin)\n- [The Bindgen](#the-bindgen)\n- [Bindgen configuration](#bindgen-configuration)\n- [Cross-compilation tips](#cross-compilation-tips)\n\n## Development environment and common development practices\n\nThere are only one option to code both in Kotlin and Rust in a single IDE: IntelliJ IDEA Ultimate, which needs a paid\nsubscription. Fleet was another option, but JetBrains announced that\n[they are dropping the KMP support in Fleet](https://blog.jetbrains.com/kotlin/2025/02/kotlin-multiplatform-tooling-shifting-gears/).\n\nTherefore, most users may use different IDEs for Kotlin and Rust when developing with this project. For Kotlin, you\ncan use Android Studio or IntelliJ IDEA, and for Rust, you can use `rust-analyzer` with Visual Studio Code or RustRover. \nIn normal cases, Kotlin handles the part interacting with users such as UI while Rust handles the core business logic,\nso using two IDEs won't harm the developer experience that much.\n\nSince building Rust takes much time than compiling Kotlin, try separating the Kotlin part that uses Rust directly as a\ncore library. You can build and publish the core library using the `maven-publish` plugin and the other Kotlin part can\ndownload it from a maven repository.\n\nThe more platforms you target, the larger the build result will be. Ensure your CI has enough space to build your project.\nGradle caches files from the build in `~/.gradle/caches`. If you encounter much more `No space left on device` errors after\nusing this project, try removing `~/.gradle/caches`. Since Gradle still tries to find cached files in `~/.gradle/caches`\nafter you remove it, remove all `.gradle` and `build` directories in your project as well. On macOS \u0026 Linux:\n\n```\nfind . -name .gradle | xargs rm -rf\nfind . -name \"build\" | grep -v '^./target' | xargs -r rm -rf\n```\n\nIn PowerShell on Windows:\n\n```powershell\nGet-ChildItem . -Attributes Directory -Recurse |\n    Where-Object { $_.Name -eq \".gradle\" } |\n    ForEach-Object { Remove-Item -Recurse -Force $_ }\nGet-ChildItem . -Attributes Directory -Recurse |\n    Where-Object { $_.Name -eq \"build\" } |\n    Where-Object { -not $_.FullName.Contains(\"\\target\\\") } |\n    ForEach-Object { Remove-Item -Recurse -Force $_ }\n```\n\nWhen you build iOS apps, Xcode generates files in `/private/var/folders/zz`, which are removed automatically after every\nreboot. Try restart your Mac if you still have the disk space issue after removing the Gradle caches.\n\n## Using the Gradle plugin\n\nThis project contains three Gradle plugins:\n\n- [The Cargo plugin (`dev.gobley.cargo`)](#the-cargo-plugin)\n- [The UniFFI plugin (`dev.gobley.uniffi`)](#the-uniffi-plugin)\n- [The Rust plugin (`dev.gobley.rust`)](#the-rust-plugin)\n\nThese plugins are published in Maven Central. In your `settings.gradle.kts`, put `mavenCentral()` in the\n`pluginManagement {}` block.\n\n```\npluginManagement {\n    repositories {\n        mavenCentral()\n    }\n}\n```\n\n### The Cargo plugin\n\n#### Basic usage\n\nThe Cargo plugin is responsible for building and linking the Rust library to your Kotlin project. You can use it even\nwhen you are not using UniFFI. If the `Cargo.toml` is located in the project root, you can simply apply the\n`dev.gobley.cargo` the plugin.\n\n```kotlin\nplugins {\n    kotlin(\"multiplatform\")\n    id(\"dev.gobley.cargo\") version \"0.1.0\"\n}\n```\n\n#### Configuring Cargo package not in the project root\n\nIf the Cargo package is located in another directory, you can configure the path in the `cargo {}` block.\n\n```kotlin\ncargo {\n    // The Cargo package is located in a `rust` subdirectory.\n    packageDirectory = layout.projectDirectory.dir(\"rust\")\n}\n```\n\nSince searching `Cargo.toml` is done\nby [`cargo locate-project`](https://doc.rust-lang.org/cargo/commands/cargo-locate-project.html),\nit still works even if you set `packageDirectory` to a subdirectory, but it is not recommended.\n\n```kotlin\ncargo {\n    // This works\n    packageDirectory = layout.projectDirectory.dir(\"rust/src\")\n}\n```\n\n#### Configuring Cargo to use different Cargo features or build profiles\n\nIf you want to use Cargo features or\ncustomized [Cargo profiles](https://doc.rust-lang.org/cargo/reference/profiles.html),\nyou can configure them in the `cargo {}` block as well.\n\n```kotlin\nimport gobley.gradle.cargo.profiles.CargoProfile\n\ncargo {\n    features.addAll(\"foo\", \"bar\")\n    debug.profile = CargoProfile(\"my-debug\")\n    release.profile = CargoProfile.Bench\n}\n```\n\nIf you want to use different features for each variant (debug or release), you can configure them in the `debug {}` or\n`release {}` blocks.\n\n```kotlin\ncargo {\n    features.addAll(\"foo\")\n    debug {\n        // Use \"foo\", \"logging\" for debug builds\n        features.addAll(\"logging\")\n    }\n    release {\n        // Use \"foo\", \"app-integrity-checks\" for release builds\n        features.addAll(\"app-integrity-checks\")\n    }\n}\n```\n\n`features` are inherited from the outer block to the inner block. To override this behavior in the inner block,\nuse `.set()` or the `=` operator overloading.\n\n```kotlin\ncargo {\n    features.addAll(\"foo\")\n    debug {\n        // Use \"foo\", \"logging\" for debug builds\n        features.addAll(\"logging\")\n    }\n    release {\n        // Use \"app-integrity-checks\" (not \"foo\"!) for release builds\n        features.set(setOf(\"app-integrity-checks\"))\n    }\n}\n```\n\nFor configurations applied to all variants, you can use the `variants {}` block.\n\n```kotlin\ncargo {\n    variants {\n        features.addAll(\"another-feature\")\n    }\n}\n```\n\nFor Android and Apple platform builds invoked by Xcode, the plugin automatically decides which profile to use. For other\ntargets, you can configure it with the `jvmVariant` or `nativeVariant` properties. When undecidable, these values\ndefault to `Variant.Debug`.\n\n```kotlin\nimport gobley.gradle.Variant\n\ncargo {\n    jvmVariant = Variant.Release\n    nativeVariant = Variant.Debug\n}\n```\n\n#### The Cargo plugin only builds for required platforms\n\nCargo build tasks are configured as the corresponding Kotlin target is added in the `kotlin {}` block. For example, if\nyou don't invoke `androidTarget()` in `kotlin {}`, the Cargo plugin won't configure the Android build task as well.\n\n```kotlin\ncargo {\n    builds.android {\n        println(\"foo\") // not executed\n    }\n}\n\nkotlin {\n    // The plugin will react to the targets definition\n    jvm()\n    linuxX64()\n}\n```\n\nThe Cargo plugin scans all the Rust dependencies\nusing [`cargo metadata`](https://doc.rust-lang.org/cargo/commands/cargo-metadata.html). If you modify Rust source files\nincluding those in dependencies defined in the Cargo manifest, the Cargo plugin will rebuild the Cargo project.\n\n#### Changing the NDK version used to build Android binaries\n\nFor Android builds, the Cargo plugin automatically determines the SDK and the NDK to use based on the property values of\nthe `android {}` block. To use different a NDK version, set `ndkVersion` to that version.\n\n```kotlin\nandroid {\n    ndkVersion = \"26.2.11394342\"\n}\n```\n\nThe Cargo plugin also automatically determines the ABI to build based on the value\nof `android.defaultConfig.ndk.abiFilters`. If you don't want to build for x86 or x86_64, set this\nto `[\"arm64-v8a\", \"armeabi-v7a\"]`.\n\n```kotlin\nandroid {\n    defaultConfig {\n        ndk.abiFilters += setOf(\"arm64-v8a\", \"armeabi-v7a\")\n    }\n}\n```\n\n#### Changing the environment variables used during the build\n\nThe Cargo plugin automatically configures environment variables like `ANDROID_HOME` or `CC_\u003ctarget\u003e` for you, but if you\nneed finer control, you can directly configure the properties of the build task. The build task is accessible in the\n`builds {}` block.\n\n```kotlin\nimport gobley.gradle.cargo.dsl.*\n\ncargo {\n    builds {\n        // Configure Android builds\n        android {\n            debug.buildTaskProvider.configure {\n                additionalEnvironment.put(\"CLANG\", \"/path/to/clang\")\n            }\n        }\n        // You can configure for other targets as well\n        appleMobile {}\n        desktop {}\n        jvm {}\n        mobile {}\n        native {}\n        posix {}\n        mingw {}\n        linux {}\n        macos {}\n        windows {}\n    }\n}\n```\n\n#### Configuring the platforms used by the JVM target\n\nFor JVM builds, the Cargo plugin tries to build all the targets, whether the required toolchains are installed on the\ncurrent system or not. The list of such targets by the build host is as follows.\n\n| Targets      | Windows | macOS | Linux |\n|--------------|---------|-------|-------|\n| Android      | ✅       | ✅     | ✅     |\n| Apple Mobile | ❌       | ✅     | ❌     |\n| MinGW        | ✅       | ✅     | ✅     |\n| macOS        | ❌       | ✅     | ❌     |\n| Linux        | ✅       | ✅     | ✅     |\n| Visual C++   | ✅       | ❌     | ❌     |\n\nTo build for specific targets only, you can configure that using the `embedRustLibrary` property. For example, to\nbuild a shared library for the current build host only, set this property to\n`rustTarget == GobleyHost.current.rustTarget`.\n\n```kotlin\nimport gobley.gradle.GobleyHost\nimport gobley.gradle.cargo.dsl.*\n\ncargo {\n    builds.jvm {\n        embedRustLibrary = (rustTarget == GobleyHost.current.rustTarget)\n    }\n}\n```\n\nOn Windows, both MinGW and Visual C++ can generate DLLs. By default, the Cargo plugin doesn't invoke the MinGW build\nfor JVM when Visual C++ is available. To override this behavior, use the `embedRustLibrary` property like the\nfollowing. Note that Windows on ARM is not available with MinGW.\n\n```kotlin\nimport gobley.gradle.GobleyHost\nimport gobley.gradle.cargo.dsl.*\nimport gobley.gradle.rust.targets.RustWindowsTarget\n\ncargo {\n    builds.jvm {\n        if (GobleyHost.Platform.Windows.isCurrent) {\n            when (rustTarget) {\n                RustWindowsTarget.X64 -\u003e embedRustLibrary = false\n                RustPosixTarget.MinGWX64 -\u003e embedRustLibrary = true\n                else -\u003e {}\n            }\n        }\n    }\n}\n```\n\n`embedRustLibrary` is also used when you use [the external types feature](https://mozilla.github.io/uniffi-rs/udl/ext_types.html)\nin your project. Rust statically links all the crates unless you specify the library crate's kind as `dylib`. So, the\nfinal Kotlin library does not have to include shared libraries built from every crate. Suppose you have two crates, `foo`, and\n`bar`, where `foo` exposes the external types and `bar` uses types in `foo`. Since when building `bar.dll`, `libbar.dylib`, or\n`libbar.so`, the `foo` crate is also included in `bar`, you don't have to put `foo.dll`, `libfoo.dylib`, or `libfoo.so`\ninside your Kotlin library. So, to configure that, put the followings in `foo/build.gradle.kts`:\n\n```\ncargo {\n    builds.android {\n        embedRustLibrary = false\n    }\n    builds.jvm {\n        embedRustLibrary = false\n    }\n}\n```\n\nand in `foo/uniffi.toml`:\n\n```\n# The cdylib_name used in `bar/uniffi.toml`\ncdylib_name = \"bar\"\n```\n\nThe JVM `loadIndirect()` function in the bindings allow users to override the `cdylib_name` value using the\n`uniffi.component.\u003cnamespace name\u003e.libraryOverride` system property as well. See the\n[`:tests:uniffi:ext-types:ext-types`](./tests/uniffi/ext-types/ext-types) test to see how this works. \n\n#### Configuring the platforms used by Android local unit tests\n\nAndroid local unit tests requires JVM targets to be built, as they run in the host machine's JVM. The Cargo plugin\nautomatically copies the Rust shared library targeting the host machine into Android local unit tests. It also finds\nprojects that depend on the project using the Cargo plugin, and the Rust library will be copied to all projects that\ndirectly or indirectly use the Cargo project. If you want to include shared library built for a different platform, you\ncan control that using the `androidUnitTest` property.\n\n```kotlin\nimport gobley.gradle.cargo.dsl.*\nimport gobley.gradle.rust.targets.RustWindowsTarget\n\ncargo {\n    builds.jvm {\n        // Use Visual C++ X64 for Android local unit tests \n        androidUnitTest = (rustTarget == RustWindowsTarget.X64)\n    }\n}\n\nkotlin {\n    jvm()\n    androidTarget()\n}\n```\n\nLocal unit tests are successfully built even if there are no builds with `androidUnitTest` enabled, but you will\nencounter a runtime error when you invoke a Rust function from Kotlin.\n\nWhen you build or publish your Rust Android library separately and run Android local unit tests in another build, you\nalso have to reference the JVM version of your library from the Android unit tests.\n\nTo build the JVM version, run the `\u003cJVM target name\u003eJar` task. The name of the JVM target can be configured with the\n`jvm()` function, which defaults to `\"jvm\"`. For example, when the name of the JVM target is `\"desktop\"`:\n\n```kotlin\nkotlin {\n    jvm(\"desktop\")\n}\n```\n\nthe name of the task will be `desktopJar`.\n\n```shell\n# ./gradlew :your:library:\u003cJVM target name\u003eJar\n./gradlew :your:library:desktopJar\n```\n\nThe build output will be located in `build/libs/\u003cproject name\u003e-\u003cJVM target name\u003e.jar`. In the above case, the name of\nthe JAR file will be `\u003cproject name\u003e-desktop.jar`. The JAR file then can be referenced using the `files` or the\n`fileTree` functions.\n\n```kotlin\nkotlin {\n    sourceSets {\n        getByName(\"androidUnitTest\") {\n            dependencies {\n                // implementation(files(\"\u003cproject name\u003e-\u003cJVM target name\u003e.jar\"))\n                implementation(files(\"library-desktop.jar\"))\n                implementation(\"net.java.dev.jna:jna:5.13.0\") // required to run\n            }\n        }\n    }\n}\n```\n\nThe above process can be automated using the `maven-publish` Gradle plugin. It publishes the JVM version of your library\nseparately. For more details about using `maven-publish` with Kotlin Multiplatform, please refer\n[here](https://kotlinlang.org/docs/multiplatform-publish-lib.html).\n\nTo publish your library to the local Maven repository on your system, run the `publishToMavenLocal` task.\n\n```shell\n./gradlew :your:project:publishToMavenLocal\n```\n\nIn the local repository which is located in `~/.m2`, you will see that multiple artifacts including `\u003cproject name\u003e` and\n`\u003cproject name\u003e-\u003cJVM target name\u003e` are generated. To reference it, register the `mavenLocal()` repository and put the\nartifact name to `implementation()`.\n\n```kotlin\nrepositories {\n    mavenLocal()\n    // ...\n}\n\nkotlin {\n    sourceSets {\n        getByName(\"androidUnitTest\") {\n            dependencies {\n                // implementation(\"\u003cgroup name\u003e:\u003cproject name\u003e-\u003cJVM target name\u003e:\u003cversion\u003e\")\n                implementation(\"your.library:library-desktop:0.1.0\")\n                implementation(\"net.java.dev.jna:jna:5.13.0\") // required to run\n            }\n        }\n    }\n}\n```\n\n#### Configuring external dynamic libraries your Rust code depends on\n\nIf your Rust library is dependent on other shared libraries, you have to ensure that they are also available during\nruntime. For JVM and Android builds, you can use the `dynamicLibraries` and the `dynamicLibrarySearchPaths` properties.\nThe specified libraries will be embedded into the resulting JAR or the Android bundle.\n\n```kotlin\ncargo {\n    builds.android {\n        // Copies libaaudio.so and libc++_shared.so from NDK\n        dynamicLibraries.addAll(\"aaudio\", \"c++_shared\")\n    }\n    builds.jvm {\n        // Copies libmyaudio.so or myaudio.dll\n        dynamicLibraries.addAll(\"myaudio\")\n    }\n}\n```\n\nSome directories like the NDK installation directory or the Cargo build output directory are already registered in\n`dynamicLibrarySearchPaths`. If your build system uses another directory, add that to this property.\n\n#### Enabling the nightly mode and building tier 3 Rust targets\n\nSome targets like tvOS and watchOS are tier 3 in the Rust world (they are tier 2 on the Kotlin side). Pre-built standard\nlibraries are not available for these targets. To use the standard library, you must pass the `-Zbuild-std` flag to the\n`cargo build` command (See [here](https://doc.rust-lang.org/cargo/reference/unstable.html#build-std) for the official\ndocumentation). Since this flag is available only on the nightly channel, you should tell the Cargo plugin to\nuse the nightly compiler to compile the standard library.\n\nFirst, download the source code of the standard library using the following command.\n\n```\nrustup component add rust-src --toolchain nightly\n```\n\nTo get the tier of a `RustTarget`, you can use the `fun RustTarget.tier(version: String): Int`\nfunction. We can instruct Cargo to build the standard library for tier 3 targets only with it.\n\n```kotlin\ncargo {\n    builds.appleMobile {\n        variants {\n            if (rustTarget.tier(project.rustVersion.get()) \u003e= 3) {\n                buildTaskProvider.configure {\n                    // Pass +nightly to `cargo rustc` (or `cargo build`) to use `-Zbuild-std`.\n                    nightly = true\n                    // Make Cargo build the standard library\n                    extraArguments.add(\"-Zbuild-std\")\n                }\n            }\n        }\n    }\n}\n```\n\n### The UniFFI plugin\n\nThe UniFFI plugin is responsible for generating Kotlin bindings from your Rust package. Here is an example of using the\nUniFFI plugin to build bindings from the resulting library binary.\n\n```kotlin\nimport gobley.gradle.Variant\nimport gobley.gradle.rust.targets.RustAndroidTarget\n\nplugins {\n    kotlin(\"multiplatform\")\n    id(\"dev.gobley.cargo\") version \"0.1.0\"\n    id(\"dev.gobley.uniffi\") version \"0.1.0\"\n}\n\nuniffi {\n    // Generate the bindings using library mode.\n    generateFromLibrary {\n        // The UDL namespace as in the UDL file. Defaults to the library crate name.\n        namespace = \"my_crate\"\n        // The Rust target of the build to use to generate the bindings. If unspecified, one of the available builds\n        // will be automatically selected.\n        build = RustAndroidTarget.Arm64\n        // The variant of the build that makes the library to use. If unspecified, the UniFFI plugin automatically picks\n        // one.\n        variant = Variant.Debug\n    }\n}\n```\n\nIf you want to generate bindings from a UDL file as well, you can specify the path using the `generateFromUdl {}` block.\n\n```kotlin\nuniffi {\n    generateFromUdl {\n        namespace = \"...\"\n        build = ...\n        variant = Variant.Debug\n        // The UDL file. Defaults to \"${crateDirectory}/src/${crateName}.udl\".\n        udlFile = layout.projectDirectory.file(\"rust/src/my_crate.udl\")\n    }\n}\n```\n\nIf you want to run `ktlint` on the generated bindings set `formatCode` to `true`.\n\n```kotlin\nuniffi {\n    formatCode = true\n}\n```\n\nWhen you use Kotlin targets not supported by the UniFFI plugin like `js()`, `wasmJs()`, or `wasmWasi()`,\nthe UniFFI plugin generates stubs. This ensures that the Kotlin code is compiled successfully for all\nplatforms. However, all generated functions except for `RustObject(NoPointer)` constructors will throw\n`kotlin.NotImplementedError`. We are trying to support as many platforms as possible. If you need to\ntarget WASM/JS, please use these stubs until WASM/JS support is released.\n\n### The Rust plugin\n\nThe Rust plugin is for configuring the Rust toolchain you want to use or linking your Rust library to your Kotlin\nproject. By default, the plugins think `cargo` and `rustup` are installed in `~/.cargo/bin` or a directory registered in\nthe `PATH` environment variable, which is okay for almost everyone.\n\nHowever, if you have installed `cargo` or `rustup` in another directory, you can provide that information to the plugin\nvia the `rust {}` block. The information in the `rust {}` block is automatically passed to the Cargo or the UniFFI\nplugins.\n\n```kotlin\nplugins {\n    id(\"dev.gobley.rust\") version \"0.1.0\"\n}\n\nrust {\n    toolchainDirectory = File(\"/path/to/my/Rust/toolchain\")\n}\n```\n\nThe Rust plugin also defines two extension functions `KotlinMultiplatformExtension.hostNativeTarget`\nand `KotlinNativeCompilation.useRustUpLinker` and one extension property `Project.rustVersion`.\n\n`hostNativeTarget` can be invoked in `kotlin {}` and adds the Kotlin Native target for the build host; it invokes\n`mingwX64` on Windows, `macosX64` or `macosArm64` on macOS, and `linuxX64` or `linuxArm64` on Linux, though Linux Arm64\nbuild host is not supported by Kotlin/Native yet.\n\n```kotlin\nimport gobley.gradle.rust.dsl.*\n\nkotlin {\n    hostNativeTarget()\n}\n```\n\n`useRustUpLinker` is for Kotlin Native projects referencing a Rust library but not directly using Rust. Since Kotlin\nNative is shipped with an LLVM older than the one shipped with the Rust toolchain, you may encounter a linker error\nwhen building that Kotlin Native project. `useRustUpLinker` automatically finds the LLVM linker distributed\nwith `rustup`, so you can use this when your Rust project emits a linker flag that is not supported by the Kotlin Native\nLLVM linker.\n\n```kotlin\nimport gobley.gradle.rust.dsl.*\n\nkotlin {\n    iosArm64().compilations.getByName(\"main\") {\n        useRustUpLinker()\n    }\n}\n```\n\n`rustVersion` retrieves the current Rust version via `rustc --version`.\n\n```kotlin\nimport gobley.gradle.rust.dsl.*\n\nprintln(rustVersion.get()) // e.g. 1.81.0\n```\n\n## The Bindgen\n\nThe bindings generator (the \"bindgen\") is the program that generates Kotlin source codes connecting your Kotlin code\nto your Rust code. In most cases, [the UniFFI Gradle plugin](#the-uniffi-plugin) handles the bindings generation, so you\ndon't have to know all the details of the bindgen. Still, you can directly use this bindgen if you have more\ncomplicated build system.\n\nThe minimum Rust version required to install `gobley-uniffi-bindgen` is `1.72`. Newer Rust versions should\nalso work fine. The source code of the bindgen for Kotlin Multiplatform is in [`bindgen`](./bindgen). See comments in\n[`bindgen/src/main.rs`](./bindgen/src/main.rs) or\n[`BuildBindingsTask.kt`](./build-logic/gobley-gradle-uniffi/src/main/kotlin/tasks/BuildBindingsTask.kt)\nto see how to use the bindgen from the command line.\n\nTo install the bindgen, run:\n\n```shell\ncargo install --bin gobley-uniffi-bindgen gobley-uniffi-bindgen@0.1.0\n```\n\nto invoke the bindgen, run:\n\n```shell\ngobley-uniffi-bindgen --lib-file \u003cpath-to-library-file\u003e --out-dir \u003coutput-directory\u003e --crate \u003ccrate-name\u003e \u003cpath-to-udl-file\u003e\n```\n\nIf you want to use the bindgen in your own Crago build script, please read the\n[\"Generating foreign-language bindings\" part](https://mozilla.github.io/uniffi-rs/tutorial/foreign_language_bindings.html)\nin the official UniFFI documentation.\n\nWhen the bindings are generated correctly, it has a directory structure like the following.\n\n```\n\u003coutput directory\u003e\n├── androidMain\n│   └── kotlin\n│       └── \u003cnamespace name\u003e\n│           └── \u003cnamespace name\u003e.android.kt\n├── commonMain\n│   └── kotlin\n│       └── \u003cnamespace name\u003e\n│           └── \u003cnamespace name\u003e.common.kt\n├── jvmMain\n│   └── kotlin\n│       └── \u003cnamespace name\u003e\n│           └── \u003cnamespace name\u003e.jvm.kt\n├── nativeInterop\n│   └── headers\n│       └── \u003cnamespace name\u003e\n│           └── \u003cnamespace name\u003e.h\n├── nativeMain\n│   └── kotlin\n│       └── \u003cnamespace name\u003e\n│           └── \u003cnamespace name\u003e.native.kt\n└── stubMain\n    └── kotlin\n        └── \u003cnamespace name\u003e\n            └── \u003cnamespace name\u003e.stub.kt\n```\n\n### Bindgen configuration\n\nVarious settings used by the bindgen can be configured in `\u003cmanifest dir\u003e/uniffi.toml`. For more\ndetails, see [`bindgen/src/gen_kotlin_multiplatform/mod.rs`](./bindgen/src/gen_kotlin_multiplatform/mod.rs)\nor [`Config.kt`](./build-logic/gobley-gradle-uniffi/src/main/kotlin/Config.kt).\n\n| Configuration Name                     | Type         | Description                                                                                                                                                                                                                                               |\n|----------------------------------------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `package_name`                         | String       | The Kotlin package name to use. Defaults to `uniffi.\u003cnamespace name\u003e`.                                                                                                                                                                                    |\n| `cdylib_name`                          | String       | The name of the resulting dynamic library without the prefix (e.g. `lib`) and the file extension. Defaults to the library's name when bindings are generated from it, or `uniffi_\u003cnamespace\u003e` when generated from a UDL file.                             |\n| `kotlin_multiplatform`                 | Boolean      | When `false`, expect/actual declarations are not used.                                                                                                                                                                                                    |\n| `kotlin_targets`                       | String Array | The list of names of Kotlin targets of the bindings to generate. Possible values are: `jvm`, `android`, `native`, and `stub`.                                                                                                                             |\n| `generate_immutable_records`           | Boolean      | When `true`, generated data classes has `val` properties instead of `var`.                                                                                                                                                                                |\n| `custom_types`                         |              | See [the documentation](https://mozilla.github.io/uniffi-rs/0.28/udl/custom_types.html#custom-types-in-the-bindings-code)                                                                                                                                 |\n| `kotlin_target_version`                | String       | The Kotlin version used by your project. Newer syntax will be used (e.g. `data object` or `Enum.entries`) when the compiler of the specified version supports. This is automatically set to the Kotlin Gradle plugin version by the UniFFI Gradle plugin. |\n| `disable_java_cleaner`                 | Boolean      | When `true`, `com.sun.jna.internal.Cleaner` will be used instead of `android.system.SystemCleaner` or `java.lang.ref.Cleaner`. Defaults to `false`. Consider changing this option when your project targets JVM 1.8.                                      |\n| `generate_serializable_types`          | Boolean      | When `true`, data classes will be annotated with `@kotlinx.serialization.Serializable` when possible. This is automatically set to `true` by the UniFFI Gradle plugin when your Kotlin project uses KotlinX Serialization.                                |\n| `use_pascal_case_enum_class`           | Boolean      | When `true`, enum classes will use PascalCase instead of UPPER_SNAKE_CASE.                                                                                                                                                                                |\n| `jvm_dynamic_library_dependencies`     | String Array | The list of dynamic libraries required by your Rust library on Desktop JVM targets without the prefix and the file extension. Use this if your project depends on an external dynamic library.                                                            |\n| `android_dynamic_library_dependencies` | String Array | The list of dynamic libraries required by your Rust library on Android without the prefix and the file extension.                                                                                                                                         |\n| `dynamic_library_dependencies`         | String Array | The list of dynamic libraries required by your Rust library on both Desktop JVM targets and Android targets.                                                                                                                                              |\n\n# Cross-compilation tips\n\n## Linux cross-compilation on Windows or macOS\n\nIf this is your first time cross-compiling a Linux binary on macOS, you may encounter a linker\nerror reporting that the linker has received some unknown command-line arguments. That happens\nbecause you tried to link a Linux binary using the linker for Apple platforms.\n\n```\nerror linking with `cc` failed: exit status 1\n  |\n  = note: LC_ALL=\"C\" PATH=\"...\" \"\u003clinker path\u003e\" \u003carguments ...\u003e\n  = note: ld: unknown options: --version-script=... --no-undefined-version ...\n          clang: error: linker command failed with exit code 1 (use -v to see invocation)\n```\n\nSimilarly, if you try to cross-compile a Linux binary on Windows, you may encounter a different\nerror by Cargo that it couldn't find `cc`.\n\n```\nerror: linker `cc` not found\n  |\n  = note: program not found\n```\n\n### Install Zig\n\nWhen you want to build your application or library for Linux on Windows or macOS, you have to use a\ndedicated cross-compilation linker for Linux. There are two available options: GCC and Zig. The\nlatter is much easier to install.\n\nYou can manually download Zig [here](https://ziglang.org/download/). If you're using a package\nmanager, you can also install Zig as follows:\n\n| Package Manager      | Command                          | Zig Installation Path                                                   |\n|----------------------|----------------------------------|-------------------------------------------------------------------------|\n| WinGet (Windows)     | `winget install -e --id zig.zig` | `%LOCALAPPDATA%\\Microsoft\\WinGet\\Links\\zig.exe`                         |\n| Chocolatey (Windows) | `choco install zig`              | `C:\\ProgramData\\chocolatey\\bin\\zig.exe`                                 |\n| Homebrew (macOS)     | `brew install zig`               | `/opt/homebrew/bin/zig` (Apple Silicon) or `/usr/local/bin/zig` (Intel) |\n\nNext, we have to make Cargo use Zig when building libraries for Linux. First, find where `zig` is\ninstalled. If you installed Zig using a package manager, the installation path is mentioned above.\nMake sure Zig is installed correctly.\n\nOn Windows using PowerShell:\n\n```\n\u003e \u0026 \"${env:LOCALAPPDATA}\\Microsoft\\WinGet\\Links\\zig.exe\" version\n0.13.0\n\u003e C:\\ProgramData\\chocolatey\\bin\\zig.exe version\n0.13.0\n```\n\nor CMD:\n\n```\n\u003e %LOCALAPPDATA%\\Microsoft\\WinGet\\Links\\zig.exe version\n0.13.0\n```\n\nOn macOS:\n\n```\n\u003e /opt/homebrew/bin/zig version\n0.13.0\n```\n\n### Make Cargo use Zig (Windows)\n\nWe make two batch scripts that uses the `zig` command. You can use any name, but we'll use the\nfollowing names.\n\n\u003e `%USERPROFILE` is `C:\\Users\\\u003cuser name\u003e`.\n\n- `%USERPROFILE%\\.cargo\\x86_64-unknown-linux-gnu-cc.bat`\n- `%USERPROFILE%\\.cargo\\aarch64-unknown-linux-gnu-cc.bat`\n\nIn `x86_64-unknown-linux-gnu-cc.bat`, put the following:\n\n```batch\n@echo off\n\u003czig path\u003e cc -target x86_64-linux-gnu %*\n```\n\nIf you installed Zig with WinGet, the content is:\n\n```batch\n@echo off\n%LOCALAPPDATA%\\Microsoft\\WinGet\\Links\\zig.exe cc -target x86_64-linux-gnu %*\n```\n\nSimilarly, in `aarch64-unknown-linux-gnu-cc.sh`, put as follows:\n\n```batch\n@echo off\n\u003czig path\u003e cc -target aarch64-linux-gnu %*\n```\n\nThis is the final step. Put the paths to the script files in\n[the Cargo configuration file](https://doc.rust-lang.org/cargo/reference/config.html). The easiest\noption is to modify `%USERPROFILE%\\.cargo\\config.toml` as follows.\n\n```toml\n[target.x86_64-unknown-linux-gnu]\nlinker = \"C:\\\\Users\\\\\u003cuser name\u003e\\\\.cargo\\\\x86_64-unknown-linux-gnu.bat\"\n\n[target.aarch64-unknown-linux-gnu]\nlinker = \"C:\\\\Users\\\\\u003cuser name\u003e\\\\.cargo\\\\aarch64-unknown-linux-gnu.bat\"\n```\n\nYou're ready to start building your library and application for Linux.\n\n### Make Cargo use Zig (macOS)\n\nWe make two shell scripts that uses the `zig` command. You can use any name, but we'll use the\nfollowing names.\n\n- `~/.cargo/x86_64-unknown-linux-gnu-cc.sh`\n- `~/.cargo/aarch64-unknown-linux-gnu-cc.sh`\n\nIn `x86_64-unknown-linux-gnu-cc.sh`, put the following:\n\n```shell\n#! /bin/sh\n\u003czig path\u003e cc -target x86_64-linux-gnu \"$@\"\n```\n\nIf you installed Zig with Homebrew on a Apple Silicon Mac, the content is:\n\n```shell\n#! /bin/sh\n/opt/homebrew/bin/zig -target x86_64-linux-gnu \"$@\"\n```\n\nSimilarly, in `aarch64-unknown-linux-gnu-cc.sh`, put as follows:\n\n```shell\n#! /bin/sh\n\u003czig path\u003e cc -target aarch64-linux-gnu \"$@\"\n```\n\nAfter making two script files, ensure that these files are executable.\n\n```\nchmod 555 ~/.cargo/x86_64-unknown-linux-gnu-cc.sh\nchmod 555 ~/.cargo/aarch64-unknown-linux-gnu-cc.sh\n```\n\nThis is the final step. Put the paths to the script files in\n[the Cargo configuration file](https://doc.rust-lang.org/cargo/reference/config.html). The easiest\noption is to modify `~/.cargo/config.toml` as follows.\n\n```toml\n[target.x86_64-unknown-linux-gnu]\nlinker = \"/Users/\u003cuser name\u003e/.cargo/x86_64-unknown-linux-gnu-cc.sh\"\n\n[target.aarch64-unknown-linux-gnu]\nlinker = \"/Users/\u003cuser name\u003e/.cargo/aarch64-unknown-linux-gnu-cc.sh\"\n```\n\nYou're ready to start building your library and application for Linux.\n\n## LLVM version compatibility on Apple Platforms\n\nIf you encounter an undefined symbols linker error like the following when building your Rust library that has\na dependency on a C library for iOS, you may have an LLVM version compatibility issue.\n\n```\nUndefined symbols for architecture arm64:\n  \"___chkstk_darwin\", referenced from:\n      \u003cfunction name\u003e in \u003clibrary file name or object file name\u003e\nld: symbol(s) not found for architecture arm64\nclang: error: linker command failed with exit code 1 (use -v to see invocation)\n```\n\nTo check your Rust toolchain's LLVM version, use `rustc --version --verbose`. For example,\n\n```\n\u003e rustc --version --verbose\nrustc 1.82.0 (f6e511eec 2024-10-15)\nbinary: rustc\ncommit-hash: f6e511eec7342f59a25f7c0534f1dbea00d01b14\ncommit-date: 2024-10-15\nhost: aarch64-apple-darwin\nrelease: 1.82.0\nLLVM version: 19.1.1\n```\n\nYou can see that Rust 1.82 uses LLVM 19. To check the LLVM version used by Xcode, use\n`/usr/bin/gcc --version` (Yeah, Apple puts Clang in that path.)\n\n```\n\u003e /usr/bin/xcodebuild -version\nXcode 16.2\nBuild version 16C5032a\n\u003e /usr/bin/gcc --version\nApple clang version 16.0.0 (clang-1600.0.26.6)\nTarget: arm64-apple-darwin24.3.0\nThread model: posix\nInstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin\n```\n\nYou can see Xcode 16.2 uses LLVM 16. So, the linker in Apple LLVM 16 tried to link object files that\ntargets LLVM 19, which resulted in a linker error.\n\nTo resolve this issue, try downgrading your Rust toolchain to a version that uses lower LLVM version.\nFor example, Rust 1.81 uses LLVM 18, so downgrading to 1.81 might help.\n\n```\n\u003e rustup target add 1.81\n\u003e rustup default 1.81\n\u003e rustc --version --verbose\nrustc 1.81.0 (eeb90cda1 2024-09-04)\nbinary: rustc\ncommit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c\ncommit-date: 2024-09-04\nhost: aarch64-apple-darwin\nrelease: 1.81.0\nLLVM version: 18.1.7\n```\n\nYou can also set the toolchain directory via the `toolchainDirectory` property in the `rust {}` block, so\nconsider using this if you don't want to `rustup default 1.81`.\n\nTo see which Rust version uses which LLVM version, see the Rust compiler\n[CHANGELOG](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1820-2024-10-17). You can see\nLLVM version upgrade notes in `Internal Changes` sections.\n\n## C++ Runtime on Android NDK\n\nAndroid NDK has multiple kinds of C++ runtime libraries, so it is important to check which one you are using now.\nIf you encounter a linker error (whether it's dynamic or static) mentioning functions like `__cxa_pure_virtual`,\nyou may have not linked C++ runtime to your library properly.\n\nSuch error can be a dynamic library load error in runtime like the following:\n\n```\ndlopen failed: cannot locate symbol \"__cxa_pure_virtual\" referenced by \"/data/app/.../libyourlibrary.so\"\n```\n\nor a linking error occurred during build as below.\n\n```\n\u003cfile name\u003e: undefined reference to `__cxa_pure_virtual'\n```\n\nCurrently, two C++ runtime libraries are available: `libc++_static.a` and `libc++_shared.so`. The criteria\nfor choosing which one to use is explained in detail in\n[the official documentation](https://developer.android.com/ndk/guides/cpp-support#ic). If you are\nembedding your Rust library to an application, use `libc++_shared.so`.\n\nTo link C++ runtime, use Cargo [build scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html).\nConfigure the path to the directory containing the runtime libraries via the `cargo::rustc-link-search`\ncommand. Use `cargo::rustc-link-lib` to control which runtime library to link. For example in\n`\u003cmanifest dir\u003e/build.rs`:\n\n```rust\nuse std::env;\nuse std::path::PathBuf;\n\nfn main() {\n    // The ANDROID_NDK_ROOT variable is automatically set to \u003cSDK root\u003e/ndk/\u003cNDK version\u003e by the\n    // Cargo Gradle plugin. You may want to implement your own logic finding the path to NDK if\n    // you are not invoking Cargo from Gradle.\n    let android_ndk_root = env::var(\"ANDROID_NDK_ROOT\").unwrap();\n\n    // set this to false if you want to use libc++_static.a.\n    let use_shared = true;\n\n    let host = if cfg!(target_os = \"windows\") {\n        \"windows-x86_64\"\n    } else if cfg!(target_os = \"macos\") {\n        // Apple Sillion Macs also use x86_64.\n        \"darwin-x86_64\"\n    } else if cfg!(target_os = \"linux\") {\n        \"linux-x86_64\"\n    } else {\n        panic!(\"unsupported host\")\n    };\n\n    let ndk_triplet = match env::var(\"CARGO_CFG_TARGET_ARCH\").unwrap().as_str() {\n        \"aarch64\" =\u003e \"aarch64-linux-android\",\n        \"arm\" =\u003e \"arm-linux-androideabi\",\n        \"x86_64\" =\u003e \"x86_64-linux-android\",\n        \"x86\" =\u003e \"i686-linux-android\",\n        /* RISC-V is not supported by this project yet */\n        _ =\u003e panic!(\"unsupported architecture\"),\n    };\n\n    // `libc++_shared.so` and `libc++_static.a` are in\n    // toolchains/llvm/prebuilt/\u003chost\u003e/sysroot/usr/lib/\u003cNDK triplet\u003e.\n    let library_dir = PathBuf::from(android_ndk_root)\n        .join(\"toolchains\")\n        .join(\"llvm\")\n        .join(\"prebuilt\")\n        .join(host)\n        .join(\"sysroot\")\n        .join(\"usr\")\n        .join(\"lib\")\n        .join(ndk_triplet);\n\n    // Configure the library directory path.\n    println!(\"cargo::rustc-link-search={}\", library_dir.display());\n\n    // Configure the library name.\n    println!(\n        \"cargo::rustc-link-lib={}={}\",\n        if use_shared { \"dylib\" } else { \"static\" },\n        if use_shared { \"c++_shared\" } else { \"c++_static\" },\n    );\n}\n```\n\nSome Rust libraries automatically find `libc++_static.a` or `libc++_shared.so` from NDK, and they usually\nallow users to control this using Cargo features. If some of your dependency uses `libc++_static.a` while\nothers use `libc++_shared.so`, you may encounter another linker error like the following.\n\n```\nld: error: \u003cHOME\u003e/.rustup/toolchains/.../lib/rustlib/armv7-linux-androideabi/lib/libcompiler_builtins-...(compiler_builtins-... .o): symbol __aeabi_memcpy8@@LIBC_N has undefined version LIBC_N\n```\n\nBefore such error is printed, Cargo shows the entire linker invocation arguments. For example, you may\nbe able to see something like:\n\n```\nerror: linking with `\u003clinker path\u003e` failed: exit status: 1\n  |\n  = note: LC_ALL=\"C\" PATH=\"...\" \"\u003clinker path\u003e\" \u003carguments ...\u003e\n```\n\nCopy this error and see if both `-lc++_static` and `-lc++_shared` are in the invocation. If this is the\ncase, inspect the output emitted by build scripts of dependencies. You can read it from\n`target[/\u003cCargo triplet\u003e]/\u003cprofile\u003e/build/\u003cpackage name\u003e-\u003chash\u003e/output`. For example in\n`target/aarch64-linux-android/debug/build/blake3-\u003chash\u003e/output`, you can see something like the following.\n\n```\ncargo:rerun-if-env-changed=CARGO_FEATURE_PURE\ncargo:rerun-if-env-changed=CARGO_FEATURE_NO_NEON\ncargo:rerun-if-env-changed=CARGO_FEATURE_NEON\ncargo:rerun-if-env-changed=CARGO_FEATURE_NEON\ncargo:rerun-if-env-changed=CARGO_FEATURE_NO_NEON\ncargo:rerun-if-env-changed=CARGO_FEATURE_PURE\ncargo:rustc-cfg=blake3_neon\nTARGET = Some(\"aarch64-linux-android\")\nOPT_LEVEL = Some(\"0\")\nHOST = Some(\"aarch64-apple-darwin\")\n...\n```\n\nCheck whether there is something like `cargo::rustc-link-lib=c++_static` in it.\n\nWhen you use `libc++_shared.so`, it should be embedded into the application. Use the `dynamicLibraries`\nproperty in the `builds.android {}` block to ensure `libc++_shared.so` is included in the resulting\nAndroid application/library.\n\n```\ncargo {\n    builds.android {\n        dynamicLibraries.addAll(\"c++_shared\")\n    }\n}\n```\n\n## Building for Windows on ARM\n\nBy default on an x64 machine, Visual Studio installs MSVC for x64/x86 only. If you try to link a\nprogram for ARM64 without the MSVC ARM64 toolchain, you may see an error that Cargo couldn't find\n`link.exe`.\n\n```\n\u003e cargo build --target aarch64-pc-windows-msvc\n\nerror: linker `link.exe` not found\n  |\n  = note: program not found\n\nnote: the msvc targets depend on the msvc linker but `link.exe` was not found\n\nnote: please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.\n\nnote: VS Code is a different product, and is not sufficient.\n```\n\nMake sure you installed the ARM64/ARM64EC compilers and linkers via Visual Studio Installer.\nDouble-check whether you installed the ARM64 toolchain instead of the 32-bit ARM toolchain.\nThis project does not support building for 32-bit ARM Windows.\n\n# Versioning\n\n`gobley-uniffi-bindgen` is versioned separately from `uniffi-rs`. UniFFI follows the\n[SemVer rules from the Cargo Book](https://doc.rust-lang.org/cargo/reference/resolver.html#semver-compatibility)\nwhich states \"Versions are considered compatible if their left-most non-zero major/minor/patch\ncomponent is the same\". A breaking change is any modification to the Kotlin Multiplatform bindings\nthat demands the consumer of the bindings to make corresponding changes to their code to ensure that\nthe bindings continue to function properly. `gobley-uniffi-bindgen` is young, and it's\nunclear how stable the generated bindings are going to be between versions. For this reason, major\nversion is currently 0, and most changes are probably going to bump minor version.\n\nTo ensure consistent feature set across external binding generators, `gobley-uniffi-bindgen`\ntargets a specific `uniffi-rs` version. A consumer using these bindings or any other external\nbindings (for example, [Go bindings](https://github.com/NordSecurity/uniffi-bindgen-go/) or\n[C# bindings](https://github.com/NordSecurity/uniffi-bindgen-cs)) expects the same features to be\navailable across multiple bindings generators. This means that the consumer should choose external\nbinding generator versions such that each generator targets the same `uniffi-rs` version.\n\nHere is how `gobley-uniffi-bindgen` versions are tied to `uniffi-rs` are tied:\n\n| gobley-uniffi-bindgen version | uniffi-rs version |\n|-------------------------------|-------------------|\n| v0.1.0                        | v0.28.3           |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgobley%2Fgobley","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgobley%2Fgobley","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgobley%2Fgobley/lists"}