1 import com.vanniktech.maven.publish.KotlinMultiplatform
2 import com.vanniktech.maven.publish.JavadocJar
3
4 plugins {
5 id("org.jetbrains.kotlin.multiplatform")
6 id("com.android.library")
7 id("com.vanniktech.maven.publish")
8 id("signing")
9 }
10
11 kotlin {
12 androidTarget {
13 publishLibraryVariants("release")
14 compilations.all {
15 kotlinOptions { jvmTarget = "17" }
16 }
17 }
18
19 jvm {
20 compilations.all {
21 kotlinOptions { jvmTarget = "17" }
22 }
23 }
24
25 sourceSets {
26 // Both androidMain and jvmMain share the code in src/shared/kotlin/
27 // and the UniFFI-generated bindings in src/generated/kotlin/.
28 // This avoids the complexity of intermediate source sets while keeping
29 // the shared engine wrapper code DRY.
30
31 androidMain.dependencies {
32 // JNA — UniFFI-generated onde.kt uses com.sun.jna.* for its FFI bridge.
33 // The @aar suffix pulls the Android-specific build with native .so files.
34 implementation("net.java.dev.jna:jna:5.14.0@aar")
35 // Coroutines — suspend funs and Flow streaming in OndeInference
36 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")
37 }
38
39 jvmMain.dependencies {
40 // Desktop JNA with native libs for macOS/Linux/Windows
41 implementation("net.java.dev.jna:jna:5.14.0")
42 // Coroutines
43 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
44 }
45
46 // Add shared source directories to both JVM-based targets.
47 // src/shared/kotlin/ — hand-written OndeInference wrapper + convenience objects
48 // src/generated/kotlin/ — UniFFI-generated onde.kt (gitignored, regenerated)
49 androidMain.get().kotlin.srcDir("src/shared/kotlin")
50 androidMain.get().kotlin.srcDir("src/generated/kotlin")
51 jvmMain.get().kotlin.srcDir("src/shared/kotlin")
52 jvmMain.get().kotlin.srcDir("src/generated/kotlin")
53 }
54 }
55
56 android {
57 namespace = "com.ondeinference.onde"
58 compileSdk = 35
59
60 defaultConfig {
61 minSdk = 26 // Os.setenv needs API 26+
62 consumerProguardFiles("consumer-rules.pro")
63 }
64
65 lint {
66 // The UniFFI-generated onde.kt uses java.lang.ref.Cleaner (API 33+)
67 // with an internal fallback for older API levels. We don't control
68 // the generated code, so suppress the lint error.
69 disable += "NewApi"
70 }
71
72 compileOptions {
73 sourceCompatibility = JavaVersion.VERSION_17
74 targetCompatibility = JavaVersion.VERSION_17
75 }
76
77 sourceSets {
78 getByName("main") {
79 // Android JNI shared libraries live under androidMain/jniLibs/
80 jniLibs.srcDirs("src/androidMain/jniLibs")
81 }
82 }
83 }
84
85 // ── Maven Central publishing (KMP) ─────────────────────────────────────────
86 //
87 // Required secrets (in ~/.gradle/gradle.properties or CI env vars):
88 // ORG_GRADLE_PROJECT_mavenCentralUsername
89 // ORG_GRADLE_PROJECT_mavenCentralPassword
90 // ORG_GRADLE_PROJECT_signingKeyId
91 // ORG_GRADLE_PROJECT_signingKey (ASCII-armored PGP private key)
92 // ORG_GRADLE_PROJECT_signingPassword
93 // ── Signing ────────────────────────────────────────────────────────────────
94 // Vanniktech 0.28 looks for signingInMemoryKey / signingInMemoryKeyId /
95 // signingInMemoryKeyPassword. Local gradle.properties (and CI secrets) use
96 // the shorter names signingKey / signingKeyId / signingPassword.
97 // Bridge them here so both naming conventions work.
98 val signingKeyId = findProperty("signingInMemoryKeyId") as String?
99 ?: findProperty("signingKeyId") as String?
100 val signingKey = findProperty("signingInMemoryKey") as String?
101 ?: findProperty("signingKey") as String?
102 val signingPassword = findProperty("signingInMemoryKeyPassword") as String?
103 ?: findProperty("signingPassword") as String?
104
105 signing {
106 if (signingKey != null) {
107 useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
108 }
109 }
110
111
112 mavenPublishing {
113 configure(
114 KotlinMultiplatform(
115 javadocJar = JavadocJar.Empty(),
116 sourcesJar = true,
117 )
118 )
119
120 publishToMavenCentral()
121 signAllPublications()
122
123 // Coordinates are read automatically from gradle.properties:
124 // GROUP → groupId
125 // POM_ARTIFACT_ID → artifactId
126 // VERSION_NAME → version
127 // Do NOT call coordinates() explicitly — it conflicts with the
128 // properties-based approach and causes "value is final" errors.
129
130 pom {
131 name.set("Onde Inference")
132 description.set(
133 "On-device LLM inference for Android and JVM (macOS Apple Silicon). " +
134 "Run Qwen 2.5 models locally — no cloud, no API key, no data leaving the device."
135 )
136 url.set("https://ondeinference.com")
137 inceptionYear.set("2025")
138
139 licenses {
140 license {
141 name.set("MIT OR Apache-2.0")
142 url.set("https://github.com/ondeinference/onde/blob/main/LICENSE")
143 distribution.set("repo")
144 }
145 }
146
147 developers {
148 developer {
149 id.set("ondeinference")
150 name.set("Onde Inference")
151 email.set("hello@ondeinference.com")
152 url.set("https://ondeinference.com")
153 organization.set("Splitfire AB")
154 organizationUrl.set("https://splitfire.se")
155 }
156 }
157
158 scm {
159 url.set("https://github.com/ondeinference/onde")
160 connection.set("scm:git:github.com/ondeinference/onde.git")
161 developerConnection.set("scm:git:ssh://github.com/ondeinference/onde.git")
162 }
163 }
164 }