Skip to content

Commit e1b99c9

Browse files
committed
use Groovy metaprogramming to access KGP when applied via settings plugin
1 parent 121769a commit e1b99c9

File tree

2 files changed

+81
-20
lines changed

2 files changed

+81
-20
lines changed

modules/bcv-gradle-plugin-functional-tests/src/functionalTest/kotlin/kotlinx/validation/test/SettingsPluginDslTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ private fun kotlinMultiplatformProjectWithBcvSettingsPlugin() =
148148
private val settingsGradleKtsWithBcvPlugin = """
149149
buildscript {
150150
dependencies {
151-
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.20")
151+
//classpath("org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.20")
152152
}
153153
}
154154

modules/bcv-gradle-plugin/src/main/kotlin/BCVProjectPlugin.kt

+80-19
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import dev.adamko.kotlin.binary_compatibility_validator.tasks.BCVApiDumpTask
1616
import dev.adamko.kotlin.binary_compatibility_validator.tasks.BCVApiGenerateTask
1717
import dev.adamko.kotlin.binary_compatibility_validator.tasks.BCVDefaultTask
1818
import javax.inject.Inject
19+
import org.gradle.api.NamedDomainObjectContainer
1920
import org.gradle.api.NamedDomainObjectProvider
2021
import org.gradle.api.Plugin
2122
import org.gradle.api.Project
@@ -181,31 +182,91 @@ constructor(
181182
extension: BCVProjectExtension,
182183
) {
183184
project.pluginManager.withPlugin("kotlin-multiplatform") {
184-
val kotlinTargetsContainer = project.extensions.getByType<KotlinTargetsContainer>()
185-
186-
kotlinTargetsContainer.targets
187-
.matching {
188-
it.platformType in arrayOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm)
189-
}.all {
190-
val targetPlatformType = platformType
191-
192-
extension.targets.register(targetName) {
193-
enabled.convention(true)
194-
compilations
195-
.matching {
196-
when (targetPlatformType) {
197-
KotlinPlatformType.jvm -> it.name == "main"
198-
KotlinPlatformType.androidJvm -> it.name == "release"
199-
else -> false
185+
try {
186+
val kotlinTargetsContainer = project.extensions.getByType<KotlinTargetsContainer>()
187+
188+
kotlinTargetsContainer.targets
189+
.matching {
190+
it.platformType in arrayOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm)
191+
}.all {
192+
val targetPlatformType = platformType
193+
194+
extension.targets.register(targetName) {
195+
enabled.convention(true)
196+
compilations
197+
.matching {
198+
when (targetPlatformType) {
199+
KotlinPlatformType.jvm -> it.name == "main"
200+
KotlinPlatformType.androidJvm -> it.name == "release"
201+
else -> false
202+
}
203+
}.all {
204+
inputClasses.from(output.classesDirs)
200205
}
201-
}.all {
202-
inputClasses.from(output.classesDirs)
203-
}
206+
}
207+
}
208+
} catch (e: Throwable) {
209+
when (e) {
210+
is NoClassDefFoundError,
211+
is TypeNotPresentException -> {
212+
logger.info("Failed to apply BCVProjectPlugin to project ${project.path} with plugin $id using KGP classes $e")
213+
createKotlinMultiplatformTargetsHack(project, extension)
204214
}
215+
216+
else -> throw e
205217
}
218+
}
206219
}
207220
}
208221

222+
private fun createKotlinMultiplatformTargetsHack(
223+
project: Project,
224+
extension: BCVProjectExtension,
225+
) {
226+
logger.info("Falling back to Groovy metaprogramming to access to KGP classes ${project.path} https://github.com/adamko-dev/kotlin-binary-compatibility-validator-mu/issues/1")
227+
val kmpExtAny = project.extensions.findByName("kotlin")
228+
?: return
229+
230+
val targets = kmpExtAny.withGroovyBuilder { "getTargets"() }
231+
as NamedDomainObjectContainer<*>
232+
233+
targets
234+
.matching { target ->
235+
val platformType = target.withGroovyBuilder { "getPlatformType"() }
236+
?: return@matching false
237+
platformType.withGroovyBuilder {
238+
val name = "getName"()
239+
name in listOf("jvm", "androidJvm")
240+
}
241+
}
242+
.all action@{
243+
val platformType = withGroovyBuilder { "getPlatformType"() } ?: return@action
244+
val platformTypeName = platformType.withGroovyBuilder { "getName"() }
245+
val targetName = withGroovyBuilder { "getTargetName"() }// as String
246+
val compilations = withGroovyBuilder { "getCompilations"() }
247+
as NamedDomainObjectContainer<*>
248+
249+
extension.targets.register(targetName.toString()) {
250+
enabled.convention(true)
251+
252+
compilations
253+
.matching { comp ->
254+
val compName = comp.withGroovyBuilder { "getName"() }
255+
256+
when (platformTypeName) {
257+
"jvm" -> compName == "main"
258+
"androidJvm" -> compName == "release"
259+
else -> false
260+
}
261+
}.all {
262+
val output = withGroovyBuilder { "getOutput"() } ?: return@all
263+
val classesDirs = output.withGroovyBuilder { "getClassesDirs"() }
264+
inputClasses.from(classesDirs)
265+
}
266+
}
267+
}
268+
}
269+
209270
private fun createJavaTestFixtureTargets(
210271
project: Project,
211272
extension: BCVProjectExtension,

0 commit comments

Comments
 (0)