Skip to content

Commit 0b6f8ff

Browse files
authored
Merge pull request #20 from tuuhin/feat/target-alias-names
Feature: Allowing alias names for kotlin targets
2 parents eda61e1 + 9e64268 commit 0b6f8ff

5 files changed

Lines changed: 101 additions & 27 deletions

File tree

gradle/libs.versions.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
kotlin = "2.3.20"
33
pluginPublish = "2.1.0"
44
versionCheck = "0.53.0"
5+
kotlinx-coroutines = "1.11.0"
6+
junit = "4.13.2"
57

68
[plugins]
79
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
@@ -10,6 +12,10 @@ pluginPublish = { id = "com.gradle.plugin-publish", version.ref = "pluginPublish
1012
versionCheck = { id = "com.github.ben-manes.versions", version.ref = "versionCheck" }
1113

1214
[libraries]
13-
junit = "junit:junit:4.13.2"
15+
junit = { module = "junit:junit", version.ref = "junit" }
1416
kotlin-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
1517
kotlin-compiler-embeddable = { group = "org.jetbrains.kotlin", name = "kotlin-compiler-embeddable", version.ref = "kotlin" }
18+
# coroutines
19+
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
20+
kotlinx-coroutines-core-jvm = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", version.ref = "kotlinx-coroutines" }
21+
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }

plugin-build/plugin/build.gradle.kts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import org.gradle.api.publish.maven.MavenPublication
2-
31
plugins {
42
kotlin("jvm")
53
`java-gradle-plugin`

plugin-build/plugin/src/main/kotlin/io/github/kdroidfilter/nucleusnativeaccess/plugin/KotlinNativeExportPlugin.kt

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
package io.github.kdroidfilter.nucleusnativeaccess.plugin
22

3+
import io.github.kdroidfilter.nucleusnativeaccess.plugin.catalog.kotlinxCoroutineDependency
4+
import io.github.kdroidfilter.nucleusnativeaccess.plugin.catalog.kotlinxCoroutineJvmDependency
5+
import io.github.kdroidfilter.nucleusnativeaccess.plugin.catalog.kotlinxCoroutineTestDependency
36
import io.github.kdroidfilter.nucleusnativeaccess.plugin.tasks.GenerateNativeBridgesTask
7+
import org.gradle.api.GradleException
48
import org.gradle.api.Plugin
59
import org.gradle.api.Project
10+
import org.gradle.api.logging.LogLevel
611
import org.gradle.api.tasks.testing.Test
712
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
813
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
914
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
15+
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
1016
import java.io.File
1117

1218
/**
@@ -43,27 +49,50 @@ class KotlinNativeExportPlugin : Plugin<Project> {
4349

4450
private fun configureKmp(project: Project, extension: KotlinNativeExportExtension) {
4551
val kotlin = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
52+
4653
val libName = extension.nativeLibName.get()
4754
val pkg = extension.nativePackage.get()
4855

56+
// read the jvm target name
57+
// JVM target should exist otherwise the plugin is of no use
58+
val jvmTarget = kotlin.targets.filterIsInstance<KotlinJvmTarget>()
59+
.firstOrNull() ?: throw GradleException("Sorry this plugin required jvm target to work with")
60+
61+
val jvmMainSourceSetName = jvmTarget.name + "Main"
62+
val jvmTestSourceSetName = jvmTarget.name + "Test"
63+
val jvmMainTaskName = jvmMainSourceSetName.replaceFirstChar { it.titlecase() }
64+
val jvmTaskName = jvmTarget.name.replaceFirstChar { it.titlecase() }
65+
4966
val nativeBridgesDir = project.layout.buildDirectory.dir("generated/kne/nativeBridges")
5067
val jvmProxiesDir = project.layout.buildDirectory.dir("generated/kne/jvmProxies")
5168
val jvmResourcesDir = project.layout.buildDirectory.dir("generated/kne/jvmResources")
5269

53-
// Detect native target and its source sets.
70+
// Detect the first native target and its source sets.
5471
// Convention: use src/nativeMain if it exists (shared native source set),
5572
// otherwise fall back to the first native target's main source set (e.g. linuxX64Main).
5673
val nativeTarget = kotlin.targets
5774
.filterIsInstance<KotlinNativeTarget>()
5875
.firstOrNull()
5976

60-
val userNativeSrcDirs = mutableListOf<java.io.File>()
77+
78+
val nativeTargetTaskName = nativeTarget?.name?.replaceFirstChar { it.titlecase() } ?: "Native"
79+
80+
val userNativeSrcDirs = mutableListOf<File>()
81+
82+
// check if native main dir present
6183
val nativeMainDir = project.projectDir.resolve("src/nativeMain/kotlin")
6284
if (nativeMainDir.exists()) userNativeSrcDirs.add(nativeMainDir)
85+
86+
// if native target present use that too
6387
if (nativeTarget != null) {
88+
project.logger.log(
89+
LogLevel.INFO,
90+
"NATIVE TARGET FOUND :${nativeTarget.konanTarget.name} ALIAS:${nativeTarget.name}"
91+
)
6492
val targetMainDir = project.projectDir.resolve("src/${nativeTarget.name}Main/kotlin")
6593
if (targetMainDir.exists()) userNativeSrcDirs.add(targetMainDir)
6694
}
95+
6796
val userNativeSources = project.files(userNativeSrcDirs)
6897

6998
// Collect commonMain sources for data class discovery
@@ -101,20 +130,20 @@ class KotlinNativeExportPlugin : Plugin<Project> {
101130
project.tasks.register("generateKneJvmProxies") { it.dependsOn(generateBridges) }
102131

103132
// ── Coroutines dependency (required for suspend function support) ──
104-
val coroutinesVersion = "1.10.2"
105133
nativeTarget?.let { target ->
106134
kotlin.sourceSets.findByName("${target.name}Main")?.dependencies {
107-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
135+
implementation(project.kotlinxCoroutineDependency)
108136
}
109137
}
110138
kotlin.sourceSets.findByName("nativeMain")?.dependencies {
111-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
139+
implementation(project.kotlinxCoroutineDependency)
112140
}
113-
kotlin.sourceSets.findByName("jvmMain")?.dependencies {
114-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:$coroutinesVersion")
141+
142+
kotlin.sourceSets.findByName(jvmMainSourceSetName)?.dependencies {
143+
implementation(project.kotlinxCoroutineJvmDependency)
115144
}
116-
kotlin.sourceSets.findByName("jvmTest")?.dependencies {
117-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion")
145+
kotlin.sourceSets.findByName(jvmTestSourceSetName)?.dependencies {
146+
implementation(project.kotlinxCoroutineTestDependency)
118147
}
119148

120149
// Wire generated bridges into the native source set (try nativeMain, fall back to <target>Main)
@@ -123,21 +152,20 @@ class KotlinNativeExportPlugin : Plugin<Project> {
123152
nativeSourceSet?.kotlin?.srcDir(nativeBridgesDir)
124153

125154
// Wire generated JVM proxies into jvmMain
126-
kotlin.sourceSets.findByName("jvmMain")?.kotlin?.srcDir(jvmProxiesDir)
155+
kotlin.sourceSets.findByName(jvmMainSourceSetName)?.kotlin?.srcDir(jvmProxiesDir)
127156

128157
// Wire generated GraalVM metadata into JVM resources
129-
kotlin.sourceSets.findByName("jvmMain")?.resources?.srcDir(jvmResourcesDir)
158+
kotlin.sourceSets.findByName(jvmMainSourceSetName)?.resources?.srcDir(jvmResourcesDir)
130159

131160
// Ensure compilation waits for generation
132161
project.tasks.configureEach { task ->
133162
val name = task.name
134163
if (name.startsWith("compileKotlin") &&
135-
(name.contains("Native", ignoreCase = true) || name.contains("LinuxX64") ||
136-
name.contains("MacosArm64") || name.contains("MingwX64"))
164+
(name.contains("Native", ignoreCase = true) || name.contains(nativeTargetTaskName, ignoreCase = true))
137165
) {
138166
task.dependsOn(generateBridges)
139167
}
140-
if (name == "compileKotlinJvm" || name == "compileKotlinJvmMain") {
168+
if (name == "compileKotlin$jvmTaskName" || name == "compileKotlin$jvmMainTaskName") {
141169
task.dependsOn(generateBridges)
142170
}
143171
}
@@ -156,10 +184,17 @@ class KotlinNativeExportPlugin : Plugin<Project> {
156184
// ── Bundle native lib into JVM resources (zero-config deployment) ────
157185

158186
if (nativeTarget != null) {
159-
val targetName = nativeTarget.name
160-
val targetCap = targetName.replaceFirstChar { it.uppercaseChar() }
187+
// konan target names are the actual target name but we can have an associated alias
188+
val targetAliasName = nativeTarget.name
189+
val targetName = nativeTarget.konanTarget.name
190+
191+
project.logger.log(LogLevel.INFO, "TARGET ALIAS :$targetAliasName, TARGET NAME:$targetName")
192+
193+
val targetCap = targetAliasName.replaceFirstChar { it.uppercaseChar() }
161194
val libCap = libName.replaceFirstChar { it.uppercaseChar() }
195+
162196
val platform = mapTargetToPlatform(targetName)
197+
163198
val linkTaskName = "link${libCap}ReleaseShared$targetCap"
164199
val nativeLibResourceDir = project.layout.buildDirectory.dir("generated/kne/nativeLib")
165200

@@ -170,7 +205,7 @@ class KotlinNativeExportPlugin : Plugin<Project> {
170205
task.dependsOn(linkTaskName)
171206
task.doLast {
172207
val releaseDir = buildDir
173-
.dir("bin/$targetName/${libName}ReleaseShared").get().asFile
208+
.dir("bin/$targetAliasName/${libName}ReleaseShared").get().asFile
174209
val nativeFile = releaseDir.listFiles()?.firstOrNull { f ->
175210
f.extension in listOf("so", "dylib", "dll")
176211
}
@@ -184,11 +219,11 @@ class KotlinNativeExportPlugin : Plugin<Project> {
184219
}
185220

186221
// Wire native lib resource dir into JVM resources
187-
kotlin.sourceSets.findByName("jvmMain")?.resources?.srcDir(nativeLibResourceDir)
222+
kotlin.sourceSets.findByName(jvmMainSourceSetName)?.resources?.srcDir(nativeLibResourceDir)
188223

189224
// Ensure processResources waits for the native lib copy
190225
project.tasks.configureEach { task ->
191-
if (task.name == "jvmProcessResources" || task.name == "processJvmMainResources") {
226+
if (task.name == "${jvmTarget.name}ProcessResources" || task.name == "process${jvmMainTaskName}Resources") {
192227
task.dependsOn(copyNativeLib)
193228
}
194229
}
@@ -200,11 +235,18 @@ class KotlinNativeExportPlugin : Plugin<Project> {
200235
}
201236

202237
/** Map Kotlin/Native target name to platform directory name. */
203-
private fun mapTargetToPlatform(targetName: String): String = when {
204-
targetName.startsWith("linux") -> if (targetName.contains("Arm") || targetName.contains("aarch")) "linux-aarch64" else "linux-x64"
205-
targetName.startsWith("macos") -> if (targetName.contains("Arm") || targetName.contains("arm64") || targetName.contains("Arm64")) "darwin-aarch64" else "darwin-x64"
206-
targetName.startsWith("mingw") -> if (targetName.contains("Arm")) "win32-arm64" else "win32-x64"
207-
else -> "unknown"
238+
private fun mapTargetToPlatform(targetName: String): String {
239+
240+
val isArm = targetName.contains("Arm")
241+
val isArch = targetName.contains("aarch")
242+
val isArm64 = targetName.contains("arm64") || targetName.contains("Arm64")
243+
244+
return when {
245+
targetName.startsWith("linux") -> if (isArm || isArch) "linux-aarch64" else "linux-x64"
246+
targetName.startsWith("macos") -> if (isArm || isArm64) "darwin-aarch64" else "darwin-x64"
247+
targetName.startsWith("mingw") -> if (isArm) "win32-arm64" else "win32-x64"
248+
else -> "unknown"
249+
}
208250
}
209251

210252
/**
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.github.kdroidfilter.nucleusnativeaccess.plugin.catalog
2+
3+
import org.gradle.api.Project
4+
5+
6+
val Project.kotlinxCoroutineDependency
7+
get() = catalog.findLibrary("kotlinx.coroutines.core").get()
8+
.get()
9+
10+
val Project.kotlinxCoroutineJvmDependency
11+
get() = catalog.findLibrary("kotlinx.coroutines.core.jvm").get()
12+
.get()
13+
14+
val Project.kotlinxCoroutineTestDependency
15+
get() = catalog.findLibrary("kotlinx.coroutines.test").get()
16+
.get()
17+
18+
val Project.kotlinEmbeddedCompiler
19+
get() = catalog.findLibrary("kotlin.compiler.embeddable").get()
20+
.get()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.github.kdroidfilter.nucleusnativeaccess.plugin.catalog
2+
3+
import org.gradle.api.Project
4+
import org.gradle.api.artifacts.VersionCatalog
5+
import org.gradle.api.artifacts.VersionCatalogsExtension
6+
7+
val Project.catalog: VersionCatalog
8+
get() = extensions.getByType(VersionCatalogsExtension::class.java).named("libs")

0 commit comments

Comments
 (0)