11package dev.nucleusframework.nna.plugin
22
3+ import dev.nucleusframework.nna.plugin.catalog.kotlinEmbeddedCompiler
34import dev.nucleusframework.nna.plugin.catalog.kotlinxCoroutineDependency
45import dev.nucleusframework.nna.plugin.catalog.kotlinxCoroutineJvmDependency
56import dev.nucleusframework.nna.plugin.catalog.kotlinxCoroutineTestDependency
@@ -9,6 +10,10 @@ import org.gradle.api.Plugin
910import org.gradle.api.Project
1011import org.gradle.api.logging.LogLevel
1112import org.gradle.api.tasks.testing.Test
13+ import org.gradle.kotlin.dsl.create
14+ import org.gradle.kotlin.dsl.getByType
15+ import org.gradle.kotlin.dsl.register
16+ import org.gradle.kotlin.dsl.withType
1217import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
1318import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
1419import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
@@ -33,10 +38,8 @@ import java.io.File
3338class KotlinNativeExportPlugin : Plugin <Project > {
3439
3540 override fun apply (project : Project ) {
36- val extension = project.extensions.create(
37- " kotlinNativeExport" ,
38- KotlinNativeExportExtension ::class .java,
39- )
41+
42+ val extension = project.extensions.create<KotlinNativeExportExtension >(" kotlinNativeExport" )
4043
4144 extension.nativeLibName.convention(" nativelib" )
4245 extension.nativePackage.convention(" " )
@@ -48,7 +51,7 @@ class KotlinNativeExportPlugin : Plugin<Project> {
4851 }
4952
5053 private fun configureKmp (project : Project , extension : KotlinNativeExportExtension ) {
51- val kotlin = project.extensions.getByType( KotlinMultiplatformExtension :: class .java )
54+ val kotlin = project.extensions.getByType< KotlinMultiplatformExtension >( )
5255
5356 val libName = extension.nativeLibName.get()
5457 val pkg = extension.nativePackage.get()
@@ -100,34 +103,30 @@ class KotlinNativeExportPlugin : Plugin<Project> {
100103 val commonSources = project.files(if (commonMainDir.exists()) commonMainDir else null )
101104
102105 // ── PSI parser classpath (kotlin-compiler-embeddable for isolated Worker classloader) ──
103- val kotlinVersion = kotlin.coreLibrariesVersion
104- val psiClasspath = project.configurations.create(" knePsiClasspath" ) {
105- it.isCanBeConsumed = false
106- it.isCanBeResolved = true
107- it.isVisible = false
106+ val knePsiScope = project.configurations.dependencyScope(" knePsiScope" ).get()
107+ val psiClasspath = project.configurations.resolvable(" knePsiClasspath" ) {
108+ extendsFrom(knePsiScope)
109+ description = " Classpath for KNE PSI resolution"
108110 }
109- project.dependencies.add(" knePsiClasspath " , " org.jetbrains.kotlin:kotlin-compiler-embeddable: $kotlinVersion " )
111+ project.dependencies.add(knePsiScope.name, project.kotlinEmbeddedCompiler )
110112
111113 // ── Code-generation tasks ────────────────────────────────────────────
112114
113115 // Single task generates both native bridges and JVM proxies (PSI parsing + codegen in isolated worker)
114- val generateBridges = project.tasks.register(
115- " generateKneNativeBridges" ,
116- GenerateNativeBridgesTask ::class .java,
117- ) { task ->
118- task.group = " kne"
119- task.description = " Generate Kotlin/Native bridges and JVM FFM proxies"
120- task.nativeSources.from(userNativeSources)
121- task.commonSources.from(commonSources)
122- task.libName.set(libName)
123- task.jvmPackage.set(pkg)
124- task.outputDir.set(nativeBridgesDir)
125- task.jvmOutputDir.set(jvmProxiesDir)
126- task.jvmResourcesDir.set(jvmResourcesDir)
127- task.psiClasspath.from(psiClasspath)
116+ val generateBridges = project.tasks.register<GenerateNativeBridgesTask >(" generateKneNativeBridges" ) {
117+ group = " kne"
118+ description = " Generate Kotlin/Native bridges and JVM FFM proxies"
119+ taskNativeSources.from(userNativeSources)
120+ taskCommonSources.from(commonSources)
121+ taskLibName.set(libName)
122+ taskJvmPackage.set(pkg)
123+ taskOutputDir.set(nativeBridgesDir)
124+ taskJvmOutputDir.set(jvmProxiesDir)
125+ taskJvmResourcesDir.set(jvmResourcesDir)
126+ taskPsiClasspath.from(psiClasspath)
128127 }
129128 // Keep old task name as alias
130- project.tasks.register(" generateKneJvmProxies" ) { it. dependsOn(generateBridges) }
129+ project.tasks.register(" generateKneJvmProxies" ) { dependsOn(generateBridges) }
131130
132131 // ── Coroutines dependency (required for suspend function support) ──
133132 nativeTarget?.let { target ->
@@ -158,28 +157,28 @@ class KotlinNativeExportPlugin : Plugin<Project> {
158157 kotlin.sourceSets.findByName(jvmMainSourceSetName)?.resources?.srcDir(jvmResourcesDir)
159158
160159 // Ensure compilation waits for generation
161- project.tasks.configureEach { task ->
160+ project.tasks.filter { task ->
162161 val name = task.name
163- if (name.startsWith(" compileKotlin" ) &&
164- (name.contains(" Native" , ignoreCase = true ) || name.contains(nativeTargetTaskName, ignoreCase = true ))
165- ) {
166- task.dependsOn(generateBridges)
167- }
168- if (name == " compileKotlin$jvmTaskName " || name == " compileKotlin$jvmMainTaskName " ) {
169- task.dependsOn(generateBridges)
170- }
162+ val isCompileKotlinOrNative = task.name.startsWith(" compileKotlin" ) &&
163+ (task.name.contains(" Native" , ignoreCase = true ) || task.name.contains(
164+ nativeTargetTaskName,
165+ ignoreCase = true
166+ ))
167+
168+ val isJvmTask = name == " compileKotlin$jvmTaskName " || name == " compileKotlin$jvmMainTaskName "
169+ isJvmTask || isCompileKotlinOrNative
170+ }.forEach { task ->
171+ task.dependsOn(generateBridges)
171172 }
172173
173174 // ── Native binaries (both debug + release, like swift-java) ──────────
174175
175- kotlin.targets
176- .filterIsInstance<KotlinNativeTarget >()
177- .forEach { target ->
178- target.binaries.sharedLib(
179- namePrefix = libName,
180- buildTypes = listOf (NativeBuildType .DEBUG , NativeBuildType .RELEASE ),
181- )
182- }
176+ kotlin.targets.filterIsInstance<KotlinNativeTarget >().forEach { target ->
177+ target.binaries.sharedLib(
178+ namePrefix = libName,
179+ buildTypes = listOf (NativeBuildType .DEBUG , NativeBuildType .RELEASE ),
180+ )
181+ }
183182
184183 // ── Bundle native lib into JVM resources (zero-config deployment) ────
185184
@@ -199,11 +198,11 @@ class KotlinNativeExportPlugin : Plugin<Project> {
199198 val nativeLibResourceDir = project.layout.buildDirectory.dir(" generated/kne/nativeLib" )
200199
201200 val buildDir = project.layout.buildDirectory
202- val copyNativeLib = project.tasks.register(" copyKneNativeLib" ) { task ->
203- task. group = " kne"
204- task. description = " Copy native shared library into JVM resources for JAR bundling"
205- task. dependsOn(linkTaskName)
206- task. doLast {
201+ val copyNativeLib = project.tasks.register(" copyKneNativeLib" ) {
202+ group = " kne"
203+ description = " Copy native shared library into JVM resources for JAR bundling"
204+ dependsOn(linkTaskName)
205+ doLast {
207206 val releaseDir = buildDir
208207 .dir(" bin/$targetAliasName /${libName} ReleaseShared" ).get().asFile
209208 val nativeFile = releaseDir.listFiles()?.firstOrNull { f ->
@@ -213,7 +212,7 @@ class KotlinNativeExportPlugin : Plugin<Project> {
213212 val destDir = nativeLibResourceDir.get().asFile.resolve(" kne/native/$platform " )
214213 destDir.mkdirs()
215214 nativeFile.copyTo(destDir.resolve(nativeFile.name), overwrite = true )
216- task. logger.lifecycle(" kne: Bundled ${nativeFile.name} → kne/native/$platform /" )
215+ logger.lifecycle(" kne: Bundled ${nativeFile.name} → kne/native/$platform /" )
217216 }
218217 }
219218 }
@@ -222,9 +221,9 @@ class KotlinNativeExportPlugin : Plugin<Project> {
222221 kotlin.sourceSets.findByName(jvmMainSourceSetName)?.resources?.srcDir(nativeLibResourceDir)
223222
224223 // Ensure processResources waits for the native lib copy
225- project.tasks.configureEach { task ->
226- if (task. name == " ${jvmTarget.name} ProcessResources" || task. name == " process${jvmMainTaskName} Resources" ) {
227- task. dependsOn(copyNativeLib)
224+ project.tasks.configureEach {
225+ if (name == " ${jvmTarget.name} ProcessResources" || name == " process${jvmMainTaskName} Resources" ) {
226+ dependsOn(copyNativeLib)
228227 }
229228 }
230229 }
@@ -283,10 +282,10 @@ class KotlinNativeExportPlugin : Plugin<Project> {
283282 val buildType = extension.buildType.get().replaceFirstChar { it.uppercaseChar() }
284283 val linkTaskName = " link${libCap}${buildType} Shared$targetCap "
285284
286- project.tasks.withType( Test :: class .java ).configureEach { testTask ->
287- testTask. dependsOn(project.tasks.matching { it.name == linkTaskName })
288- testTask. useJUnitPlatform()
289- testTask. jvmArgs(
285+ project.tasks.withType< Test >( ).configureEach {
286+ dependsOn(project.tasks.matching { it.name == linkTaskName })
287+ useJUnitPlatform()
288+ jvmArgs(
290289 " -Djava.library.path=$libraryPath " ,
291290 " --enable-native-access=ALL-UNNAMED" ,
292291 )
0 commit comments