Skip to content

Commit e1ee086

Browse files
committed
use Groovy metaprogramming to access KGP when applied via settings plugin
1 parent 70f7779 commit e1ee086

File tree

2 files changed

+80
-20
lines changed

2 files changed

+80
-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

+79-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,90 @@ 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 kotlinExtension = project.extensions.findByName("kotlin")
228+
?: return
229+
230+
val targets = kotlinExtension.withGroovyBuilder { "getTargets"() }
231+
as NamedDomainObjectContainer<*>
232+
233+
targets
234+
.matching { target ->
235+
val platformType = target.withGroovyBuilder { "getPlatformType"() }
236+
?: return@matching false
237+
val platformName = platformType.withGroovyBuilder { "getName"() }
238+
platformName in listOf("jvm", "androidJvm")
239+
}
240+
.all action@{
241+
val platformType = withGroovyBuilder { "getPlatformType"() } ?: return@action
242+
val platformName = platformType.withGroovyBuilder { "getName"() }
243+
val targetName = withGroovyBuilder { "getTargetName"() }
244+
val compilations = withGroovyBuilder { "getCompilations"() }
245+
as NamedDomainObjectContainer<*>
246+
247+
extension.targets.register(targetName.toString()) {
248+
enabled.convention(true)
249+
250+
compilations
251+
.matching { comp ->
252+
val compName = comp.withGroovyBuilder { "getName"() }
253+
254+
when (platformName) {
255+
"jvm" -> compName == "main"
256+
"androidJvm" -> compName == "release"
257+
else -> false
258+
}
259+
}
260+
.all {
261+
val output = withGroovyBuilder { "getOutput"() } ?: return@all
262+
val classesDirs = output.withGroovyBuilder { "getClassesDirs"() }
263+
inputClasses.from(classesDirs)
264+
}
265+
}
266+
}
267+
}
268+
209269
private fun createJavaTestFixtureTargets(
210270
project: Project,
211271
extension: BCVProjectExtension,

0 commit comments

Comments
 (0)