From 989b7339a0e7e44ec56f3d3056180bc1ce278de8 Mon Sep 17 00:00:00 2001 From: Kirill Zhukov Date: Fri, 29 Jul 2022 15:23:23 -0700 Subject: [PATCH] Convert Gradle script plugin for generating UniFfi bindings into a composite build. --- buildSrc/build.gradle.kts | 8 - buildSrc/settings.gradle.kts | 0 .../generate-android-bindings.gradle.kts | 153 --------------- .../plugins/generate-jvm-bindings.gradle.kts | 100 ---------- {buildSrc => plugins}/README.md | 0 plugins/build.gradle.kts | 17 ++ plugins/settings.gradle.kts | 8 + .../kotlin/org/bitcoindevkit/plugins/Enums.kt | 0 .../plugins/UniFfiAndroidPlugin.kt | 178 ++++++++++++++++++ .../bitcoindevkit/plugins/UniFfiJvmPlugin.kt | 114 +++++++++++ settings.gradle.kts | 1 + 11 files changed, 318 insertions(+), 261 deletions(-) delete mode 100644 buildSrc/build.gradle.kts delete mode 100644 buildSrc/settings.gradle.kts delete mode 100644 buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/generate-android-bindings.gradle.kts delete mode 100644 buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/generate-jvm-bindings.gradle.kts rename {buildSrc => plugins}/README.md (100%) create mode 100644 plugins/build.gradle.kts create mode 100644 plugins/settings.gradle.kts rename {buildSrc => plugins}/src/main/kotlin/org/bitcoindevkit/plugins/Enums.kt (100%) create mode 100644 plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiAndroidPlugin.kt create mode 100644 plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiJvmPlugin.kt diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts deleted file mode 100644 index 3f0ee3c..0000000 --- a/buildSrc/build.gradle.kts +++ /dev/null @@ -1,8 +0,0 @@ -plugins { - `kotlin-dsl` - // id("org.gradle.kotlin.kotlin-dsl") version "2.2.0" -} - -repositories { - mavenCentral() -} diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts deleted file mode 100644 index e69de29..0000000 diff --git a/buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/generate-android-bindings.gradle.kts b/buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/generate-android-bindings.gradle.kts deleted file mode 100644 index e81c60a..0000000 --- a/buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/generate-android-bindings.gradle.kts +++ /dev/null @@ -1,153 +0,0 @@ -package org.bitcoindevkit.plugins - -import org.gradle.kotlin.dsl.register - -val llvmArchPath = when (operatingSystem) { - OS.MAC -> "darwin-x86_64" - OS.LINUX -> "linux-x86_64" - OS.OTHER -> throw Error("Cannot build Android library from current architecture") -} - -// arm64-v8a is the most popular hardware architecture for Android -val buildAndroidAarch64Binary by tasks.register("buildAndroidAarch64Binary") { - - workingDir("${project.projectDir}/../bdk-ffi") - val cargoArgs: MutableList = mutableListOf("build", "--release", "--target", "aarch64-linux-android") - - executable("cargo") - args(cargoArgs) - - // if ANDROID_NDK_ROOT is not set then set it to github actions default - if (System.getenv("ANDROID_NDK_ROOT") == null) { - environment( - Pair("ANDROID_NDK_ROOT", "${System.getenv("ANDROID_SDK_ROOT")}/ndk-bundle") - ) - } - - environment( - // add build toolchain to PATH - Pair("PATH", "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"), - - Pair("CFLAGS", "-D__ANDROID_API__=21"), - Pair("CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER", "aarch64-linux-android21-clang"), - Pair("CC", "aarch64-linux-android21-clang") - ) - - doLast { - println("Native library for bdk-android on aarch64 built successfully") - } -} - -// the x86_64 version of the library is mostly used by emulators -val buildAndroidX86_64Binary by tasks.register("buildAndroidX86_64Binary") { - - workingDir("${project.projectDir}/../bdk-ffi") - val cargoArgs: MutableList = mutableListOf("build", "--release", "--target", "x86_64-linux-android") - - executable("cargo") - args(cargoArgs) - - // if ANDROID_NDK_ROOT is not set then set it to github actions default - if (System.getenv("ANDROID_NDK_ROOT") == null) { - environment( - Pair("ANDROID_NDK_ROOT", "${System.getenv("ANDROID_SDK_ROOT")}/ndk-bundle") - ) - } - - environment( - // add build toolchain to PATH - Pair("PATH", "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"), - - Pair("CFLAGS", "-D__ANDROID_API__=21"), - Pair("CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER", "x86_64-linux-android21-clang"), - Pair("CC", "x86_64-linux-android21-clang") - ) - - doLast { - println("Native library for bdk-android on x86_64 built successfully") - } -} - -// armeabi-v7a version of the library for older 32-bit Android hardware -val buildAndroidArmv7Binary by tasks.register("buildAndroidArmv7Binary") { - - workingDir("${project.projectDir}/../bdk-ffi") - val cargoArgs: MutableList = mutableListOf("build", "--release", "--target", "armv7-linux-androideabi") - - executable("cargo") - args(cargoArgs) - - // if ANDROID_NDK_ROOT is not set then set it to github actions default - if (System.getenv("ANDROID_NDK_ROOT") == null) { - environment( - Pair("ANDROID_NDK_ROOT", "${System.getenv("ANDROID_SDK_ROOT")}/ndk-bundle") - ) - } - - environment( - // add build toolchain to PATH - Pair("PATH", "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"), - - Pair("CFLAGS", "-D__ANDROID_API__=21"), - Pair("CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER", "armv7a-linux-androideabi21-clang"), - Pair("CC", "armv7a-linux-androideabi21-clang") - ) - - doLast { - println("Native library for bdk-android on armv7 built successfully") - } -} - -// move the native libs build by cargo from bdk-ffi/target//release/ -// to their place in the bdk-android library -// the task only copies the available binaries built using the buildAndroidBinary tasks -val moveNativeAndroidLibs by tasks.register("moveNativeAndroidLibs") { - - dependsOn(buildAndroidAarch64Binary) - - into("${project.projectDir}/../android/src/main/jniLibs/") - - into("arm64-v8a") { - from("${project.projectDir}/../bdk-ffi/target/aarch64-linux-android/release/libbdkffi.so") - } - - into("x86_64") { - from("${project.projectDir}/../bdk-ffi/target/x86_64-linux-android/release/libbdkffi.so") - } - - into("armeabi-v7a") { - from("${project.projectDir}/../bdk-ffi/target/armv7-linux-androideabi/release/libbdkffi.so") - } - - doLast { - println("Native binaries for Android moved to ./android/src/main/jniLibs/") - } -} - -// generate the bindings using the bdk-ffi-bindgen tool located in the bdk-ffi submodule -val generateAndroidBindings by tasks.register("generateAndroidBindings") { - dependsOn(moveNativeAndroidLibs) - - workingDir("${project.projectDir}/../bdk-ffi") - executable("cargo") - args("run", "--package", "bdk-ffi-bindgen", "--", "--language", "kotlin", "--out-dir", "../android/src/main/kotlin") - - doLast { - println("Android bindings file successfully created") - } -} - -// create an aggregate task which will run the required tasks to build the Android libs in order -// the task will also appear in the printout of the ./gradlew tasks task with group and description -tasks.register("buildAndroidLib") { - group = "Bitcoindevkit" - description = "Aggregate task to build Android library" - - dependsOn( - buildAndroidAarch64Binary, - buildAndroidX86_64Binary, - buildAndroidArmv7Binary, - moveNativeAndroidLibs, - generateAndroidBindings - ) -} diff --git a/buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/generate-jvm-bindings.gradle.kts b/buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/generate-jvm-bindings.gradle.kts deleted file mode 100644 index 2eb11a0..0000000 --- a/buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/generate-jvm-bindings.gradle.kts +++ /dev/null @@ -1,100 +0,0 @@ -package org.bitcoindevkit.plugins - -// register a task called buildJvmBinaries which will run something like -// cargo build --release --target aarch64-apple-darwin -val buildJvmBinaries by tasks.register("buildJvmBinaries") { - if (operatingSystem == OS.MAC) { - exec { - workingDir("${project.projectDir}/../bdk-ffi") - executable("cargo") - val cargoArgs: List = listOf("build", "--release", "--target", "x86_64-apple-darwin") - args(cargoArgs) - } - exec { - workingDir("${project.projectDir}/../bdk-ffi") - executable("cargo") - val cargoArgs: List = listOf("build", "--release", "--target", "aarch64-apple-darwin") - args(cargoArgs) - } - } else if(operatingSystem == OS.LINUX) { - exec { - workingDir("${project.projectDir}/../bdk-ffi") - executable("cargo") - val cargoArgs: List = listOf("build", "--release", "--target", "x86_64-unknown-linux-gnu") - args(cargoArgs) - } - } -} -// move the native libs build by cargo from bdk-ffi/target/.../release/ -// to their place in the bdk-jvm library -val moveNativeJvmLibs by tasks.register("moveNativeJvmLibs") { - - // dependsOn(buildJvmBinaryX86_64MacOS, buildJvmBinaryAarch64MacOS, buildJvmBinaryLinux) - dependsOn(buildJvmBinaries) - - data class CopyMetadata(val targetDir: String, val resDir: String, val ext: String) - val libsToCopy: MutableList = mutableListOf() - - if (operatingSystem == OS.MAC) { - libsToCopy.add( - CopyMetadata( - targetDir = "aarch64-apple-darwin", - resDir = "darwin-aarch64", - ext = "dylib" - ) - ) - libsToCopy.add( - CopyMetadata( - targetDir = "x86_64-apple-darwin", - resDir = "darwin-x86-64", - ext = "dylib" - ) - ) - } else if (operatingSystem == OS.LINUX) { - libsToCopy.add( - CopyMetadata( - targetDir = "x86_64-unknown-linux-gnu", - resDir = "linux-x86-64", - ext = "so" - ) - ) - } - - libsToCopy.forEach { - doFirst { - copy { - with(it) { - from("${project.projectDir}/../bdk-ffi/target/${this.targetDir}/release/libbdkffi.${this.ext}") - into("${project.projectDir}/../jvm/src/main/resources/${this.resDir}/") - } - } - } - } -} - -// generate the bindings using the bdk-ffi-bindgen tool created in the bdk-ffi submodule -val generateJvmBindings by tasks.register("generateJvmBindings") { - - dependsOn(moveNativeJvmLibs) - - workingDir("${project.projectDir}/../bdk-ffi") - executable("cargo") - args("run", "--package", "bdk-ffi-bindgen", "--", "--language", "kotlin", "--out-dir", "../jvm/src/main/kotlin") - - doLast { - println("JVM bindings file successfully created") - } -} - -// we need an aggregate task which will run the 3 required tasks to build the JVM libs in order -// the task will also appear in the printout of the ./gradlew tasks task with a group and description -tasks.register("buildJvmLib") { - group = "Bitcoindevkit" - description = "Aggregate task to build JVM library" - - dependsOn( - buildJvmBinaries, - moveNativeJvmLibs, - generateJvmBindings - ) -} diff --git a/buildSrc/README.md b/plugins/README.md similarity index 100% rename from buildSrc/README.md rename to plugins/README.md diff --git a/plugins/build.gradle.kts b/plugins/build.gradle.kts new file mode 100644 index 0000000..0cf3c86 --- /dev/null +++ b/plugins/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id("java-gradle-plugin") + `kotlin-dsl` +} + +gradlePlugin { + plugins { + create("uniFfiJvmBindings") { + id = "org.bitcoindevkit.plugins.generate-jvm-bindings" + implementationClass = "org.bitcoindevkit.plugins.UniFfiJvmPlugin" + } + create("uniFfiAndroidBindings") { + id = "org.bitcoindevkit.plugins.generate-android-bindings" + implementationClass = "org.bitcoindevkit.plugins.UniFfiAndroidPlugin" + } + } +} diff --git a/plugins/settings.gradle.kts b/plugins/settings.gradle.kts new file mode 100644 index 0000000..a17f99e --- /dev/null +++ b/plugins/settings.gradle.kts @@ -0,0 +1,8 @@ +dependencyResolutionManagement { + repositories { + mavenCentral() + google() + } +} + +include(":plugins") diff --git a/buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/Enums.kt b/plugins/src/main/kotlin/org/bitcoindevkit/plugins/Enums.kt similarity index 100% rename from buildSrc/src/main/kotlin/org/bitcoindevkit/plugins/Enums.kt rename to plugins/src/main/kotlin/org/bitcoindevkit/plugins/Enums.kt diff --git a/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiAndroidPlugin.kt b/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiAndroidPlugin.kt new file mode 100644 index 0000000..308b82a --- /dev/null +++ b/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiAndroidPlugin.kt @@ -0,0 +1,178 @@ +package org.bitcoindevkit.plugins + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.Copy +import org.gradle.api.tasks.Exec +import org.gradle.kotlin.dsl.environment +import org.gradle.kotlin.dsl.getValue +import org.gradle.kotlin.dsl.provideDelegate +import org.gradle.kotlin.dsl.register + +internal class UniFfiAndroidPlugin : Plugin { + override fun apply(target: Project): Unit = target.run { + val llvmArchPath = when (operatingSystem) { + OS.MAC -> "darwin-x86_64" + OS.LINUX -> "linux-x86_64" + OS.OTHER -> throw Error("Cannot build Android library from current architecture") + } + + // arm64-v8a is the most popular hardware architecture for Android + val buildAndroidAarch64Binary by tasks.register("buildAndroidAarch64Binary") { + + workingDir("${projectDir}/../bdk-ffi") + val cargoArgs: MutableList = + mutableListOf("build", "--release", "--target", "aarch64-linux-android") + + executable("cargo") + args(cargoArgs) + + // if ANDROID_NDK_ROOT is not set then set it to github actions default + if (System.getenv("ANDROID_NDK_ROOT") == null) { + environment( + Pair("ANDROID_NDK_ROOT", "${System.getenv("ANDROID_SDK_ROOT")}/ndk-bundle") + ) + } + + environment( + // add build toolchain to PATH + Pair("PATH", + "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"), + + Pair("CFLAGS", "-D__ANDROID_API__=21"), + Pair("CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER", "aarch64-linux-android21-clang"), + Pair("CC", "aarch64-linux-android21-clang") + ) + + doLast { + println("Native library for bdk-android on aarch64 built successfully") + } + } + + // the x86_64 version of the library is mostly used by emulators + val buildAndroidX86_64Binary by tasks.register("buildAndroidX86_64Binary") { + + workingDir("${project.projectDir}/../bdk-ffi") + val cargoArgs: MutableList = + mutableListOf("build", "--release", "--target", "x86_64-linux-android") + + executable("cargo") + args(cargoArgs) + + // if ANDROID_NDK_ROOT is not set then set it to github actions default + if (System.getenv("ANDROID_NDK_ROOT") == null) { + environment( + Pair("ANDROID_NDK_ROOT", "${System.getenv("ANDROID_SDK_ROOT")}/ndk-bundle") + ) + } + + environment( + // add build toolchain to PATH + Pair("PATH", + "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"), + + Pair("CFLAGS", "-D__ANDROID_API__=21"), + Pair("CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER", "x86_64-linux-android21-clang"), + Pair("CC", "x86_64-linux-android21-clang") + ) + + doLast { + println("Native library for bdk-android on x86_64 built successfully") + } + } + + // armeabi-v7a version of the library for older 32-bit Android hardware + val buildAndroidArmv7Binary by tasks.register("buildAndroidArmv7Binary") { + + workingDir("${project.projectDir}/../bdk-ffi") + val cargoArgs: MutableList = + mutableListOf("build", "--release", "--target", "armv7-linux-androideabi") + + executable("cargo") + args(cargoArgs) + + // if ANDROID_NDK_ROOT is not set then set it to github actions default + if (System.getenv("ANDROID_NDK_ROOT") == null) { + environment( + Pair("ANDROID_NDK_ROOT", "${System.getenv("ANDROID_SDK_ROOT")}/ndk-bundle") + ) + } + + environment( + // add build toolchain to PATH + Pair("PATH", + "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"), + + Pair("CFLAGS", "-D__ANDROID_API__=21"), + Pair("CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER", + "armv7a-linux-androideabi21-clang"), + Pair("CC", "armv7a-linux-androideabi21-clang") + ) + + doLast { + println("Native library for bdk-android on armv7 built successfully") + } + } + + // move the native libs build by cargo from bdk-ffi/target//release/ + // to their place in the bdk-android library + // the task only copies the available binaries built using the buildAndroidBinary tasks + val moveNativeAndroidLibs by tasks.register("moveNativeAndroidLibs") { + + dependsOn(buildAndroidAarch64Binary) + + into("${project.projectDir}/../android/src/main/jniLibs/") + + into("arm64-v8a") { + from("${project.projectDir}/../bdk-ffi/target/aarch64-linux-android/release/libbdkffi.so") + } + + into("x86_64") { + from("${project.projectDir}/../bdk-ffi/target/x86_64-linux-android/release/libbdkffi.so") + } + + into("armeabi-v7a") { + from("${project.projectDir}/../bdk-ffi/target/armv7-linux-androideabi/release/libbdkffi.so") + } + + doLast { + println("Native binaries for Android moved to ./android/src/main/jniLibs/") + } + } + + // generate the bindings using the bdk-ffi-bindgen tool located in the bdk-ffi submodule + val generateAndroidBindings by tasks.register("generateAndroidBindings") { + dependsOn(moveNativeAndroidLibs) + + workingDir("${project.projectDir}/../bdk-ffi") + executable("cargo") + args("run", + "--package", + "bdk-ffi-bindgen", + "--", + "--language", + "kotlin", + "--out-dir", + "../android/src/main/kotlin") + + doLast { + println("Android bindings file successfully created") + } + } + + // create an aggregate task which will run the required tasks to build the Android libs in order + // the task will also appear in the printout of the ./gradlew tasks task with group and description + tasks.register("buildAndroidLib") { + group = "Bitcoindevkit" + description = "Aggregate task to build Android library" + + dependsOn( + buildAndroidAarch64Binary, + buildAndroidX86_64Binary, + buildAndroidArmv7Binary, + moveNativeAndroidLibs, + generateAndroidBindings + ) + } + } +} diff --git a/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiJvmPlugin.kt b/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiJvmPlugin.kt new file mode 100644 index 0000000..a811eff --- /dev/null +++ b/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiJvmPlugin.kt @@ -0,0 +1,114 @@ +package org.bitcoindevkit.plugins + +import org.gradle.api.DefaultTask +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.Exec +import org.gradle.kotlin.dsl.getValue +import org.gradle.kotlin.dsl.provideDelegate +import org.gradle.kotlin.dsl.register + +internal class UniFfiJvmPlugin : Plugin { + override fun apply(target: Project): Unit = target.run { + + // register a task called buildJvmBinaries which will run something like + // cargo build --release --target aarch64-apple-darwin + val buildJvmBinaries by tasks.register("buildJvmBinaries") { + if (operatingSystem == OS.MAC) { + exec { + workingDir("${project.projectDir}/../bdk-ffi") + executable("cargo") + val cargoArgs: List = listOf("build", "--release", "--target", "x86_64-apple-darwin") + args(cargoArgs) + } + exec { + workingDir("${project.projectDir}/../bdk-ffi") + executable("cargo") + val cargoArgs: List = listOf("build", "--release", "--target", "aarch64-apple-darwin") + args(cargoArgs) + } + } else if(operatingSystem == OS.LINUX) { + exec { + workingDir("${project.projectDir}/../bdk-ffi") + executable("cargo") + val cargoArgs: List = listOf("build", "--release", "--target", "x86_64-unknown-linux-gnu") + args(cargoArgs) + } + } + } + + // move the native libs build by cargo from bdk-ffi/target/.../release/ + // to their place in the bdk-jvm library + val moveNativeJvmLibs by tasks.register("moveNativeJvmLibs") { + + // dependsOn(buildJvmBinaryX86_64MacOS, buildJvmBinaryAarch64MacOS, buildJvmBinaryLinux) + dependsOn(buildJvmBinaries) + + data class CopyMetadata(val targetDir: String, val resDir: String, val ext: String) + val libsToCopy: MutableList = mutableListOf() + + if (operatingSystem == OS.MAC) { + libsToCopy.add( + CopyMetadata( + targetDir = "aarch64-apple-darwin", + resDir = "darwin-aarch64", + ext = "dylib" + ) + ) + libsToCopy.add( + CopyMetadata( + targetDir = "x86_64-apple-darwin", + resDir = "darwin-x86-64", + ext = "dylib" + ) + ) + } else if (operatingSystem == OS.LINUX) { + libsToCopy.add( + CopyMetadata( + targetDir = "x86_64-unknown-linux-gnu", + resDir = "linux-x86-64", + ext = "so" + ) + ) + } + + libsToCopy.forEach { + doFirst { + copy { + with(it) { + from("${project.projectDir}/../bdk-ffi/target/${this.targetDir}/release/libbdkffi.${this.ext}") + into("${project.projectDir}/../jvm/src/main/resources/${this.resDir}/") + } + } + } + } + } + + // generate the bindings using the bdk-ffi-bindgen tool created in the bdk-ffi submodule + val generateJvmBindings by tasks.register("generateJvmBindings") { + + dependsOn(moveNativeJvmLibs) + + workingDir("${project.projectDir}/../bdk-ffi") + executable("cargo") + args("run", "--package", "bdk-ffi-bindgen", "--", "--language", "kotlin", "--out-dir", "../jvm/src/main/kotlin") + + doLast { + println("JVM bindings file successfully created") + } + } + + // we need an aggregate task which will run the 3 required tasks to build the JVM libs in order + // the task will also appear in the printout of the ./gradlew tasks task with a group and description + tasks.register("buildJvmLib") { + group = "Bitcoindevkit" + description = "Aggregate task to build JVM library" + + dependsOn( + buildJvmBinaries, + moveNativeJvmLibs, + generateJvmBindings + ) + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index eed67d2..cf39893 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,4 @@ rootProject.name = "bdk-kotlin" include(":jvm", ":android") +includeBuild("plugins")