@@ -105,7 +105,7 @@ public class BinaryCompatibilityValidatorPlugin : Plugin<Project> {
105105 kotlin.targets.matching { it.jvmBased }.all { target ->
106106 val targetConfig = TargetConfig (project, extension, target.name, jvmDirConfig)
107107 if (target.platformType == KotlinPlatformType .jvm) {
108- target.mainCompilations.all {
108+ target.mainCompilationOrNull?. also {
109109 project.configureKotlinCompilation(it, extension, targetConfig, commonApiDump, commonApiCheck)
110110 }
111111 } else if (target.platformType == KotlinPlatformType .androidJvm) {
@@ -219,11 +219,9 @@ private fun Project.configureKotlinCompilation(
219219
220220 val apiBuild = task<KotlinApiBuildTask >(targetConfig.apiTaskName(" Build" )) {
221221 // Do not enable task for empty umbrella modules
222- isEnabled =
223- apiCheckEnabled(
224- projectName,
225- extension
226- ) && compilation.allKotlinSourceSets.any { it.kotlin.srcDirs.any { it.exists() } }
222+ isEnabled = apiCheckEnabled(projectName, extension)
223+ val hasSourcesPredicate = compilation.hasAnySourcesPredicate()
224+ onlyIf { hasSourcesPredicate.get() }
227225 // 'group' is not specified deliberately, so it will be hidden from ./gradlew tasks
228226 description =
229227 " Builds Kotlin API for 'main' compilations of $projectName . Complementary task and shouldn't be called manually"
@@ -419,6 +417,8 @@ private class KlibValidationPipelineBuilder(
419417 project.name
420418 projectApiFile = klibApiDir.get().resolve(klibDumpFileName)
421419 generatedApiFile = klibMergeDir.resolve(klibDumpFileName)
420+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
421+ onlyIf(" There are no klibs compiled for the project" ) { hasCompilableTargets.get() }
422422 }
423423
424424 private fun Project.dumpKlibsTask (
@@ -431,6 +431,8 @@ private class KlibValidationPipelineBuilder(
431431 group = " other"
432432 from = klibMergeDir.resolve(klibDumpFileName)
433433 to = klibApiDir.get().resolve(klibDumpFileName)
434+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
435+ onlyIf(" There are no klibs compiled for the project" ) { hasCompilableTargets.get() }
434436 }
435437
436438 private fun Project.extractAbi (
@@ -449,6 +451,8 @@ private class KlibValidationPipelineBuilder(
449451 supportedTargets = supportedTargets()
450452 inputAbiFile = klibApiDir.get().resolve(klibDumpFileName)
451453 outputAbiFile = klibOutputDir.resolve(klibDumpFileName)
454+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
455+ onlyIf(" There are no klibs compiled for the project" ) { hasCompilableTargets.get() }
452456 }
453457
454458 private fun Project.mergeInferredKlibsUmbrellaTask (
@@ -464,6 +468,8 @@ private class KlibValidationPipelineBuilder(
464468 " into a single merged KLib ABI dump"
465469 dumpFileName = klibDumpFileName
466470 mergedFile = klibMergeDir.resolve(klibDumpFileName)
471+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
472+ onlyIf(" There are no dumps to merge" ) { hasCompilableTargets.get() }
467473 }
468474
469475 private fun Project.mergeKlibsUmbrellaTask (
@@ -475,6 +481,8 @@ private class KlibValidationPipelineBuilder(
475481 " different targets into a single merged KLib ABI dump"
476482 dumpFileName = klibDumpFileName
477483 mergedFile = klibMergeDir.resolve(klibDumpFileName)
484+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
485+ onlyIf(" There are no dumps to merge" ) { hasCompilableTargets.get() }
478486 }
479487
480488 fun Project.bannedTargets (): Set <String > {
@@ -499,30 +507,22 @@ private class KlibValidationPipelineBuilder(
499507
500508 val supportedTargetsProvider = supportedTargets()
501509 kotlin.targets.matching { it.emitsKlib }.configureEach { currentTarget ->
502- val mainCompilations = currentTarget.mainCompilations
503- if (mainCompilations.none()) {
504- return @configureEach
505- }
510+ val mainCompilation = currentTarget.mainCompilationOrNull ? : return @configureEach
506511
507512 val targetName = currentTarget.targetName
508513 val targetConfig = TargetConfig (project, extension, targetName, intermediateFilesConfig)
509514 val apiBuildDir = targetConfig.apiDir.map { project.layout.buildDirectory.asFile.get().resolve(it) }.get()
510515 val targetSupported = targetIsSupported(currentTarget)
511516 // If a target is supported, the workflow is simple: create a dump, then merge it along with other dumps.
512517 if (targetSupported) {
513- mainCompilations.all {
514- val buildTargetAbi = configureKlibCompilation(
515- it, extension, targetConfig,
516- apiBuildDir
517- )
518- mergeTask.configure {
519- it.addInput(targetName, apiBuildDir)
520- it.dependsOn(buildTargetAbi)
521- }
522- mergeInferredTask.configure {
523- it.addInput(targetName, apiBuildDir)
524- it.dependsOn(buildTargetAbi)
525- }
518+ val buildTargetAbi = configureKlibCompilation(mainCompilation, extension, targetConfig, apiBuildDir)
519+ mergeTask.configure {
520+ it.addInput(targetName, apiBuildDir)
521+ it.dependsOn(buildTargetAbi)
522+ }
523+ mergeInferredTask.configure {
524+ it.addInput(targetName, apiBuildDir)
525+ it.dependsOn(buildTargetAbi)
526526 }
527527 return @configureEach
528528 }
@@ -534,9 +534,12 @@ private class KlibValidationPipelineBuilder(
534534 }
535535 // The actual merge will happen here, where we'll try to infer a dump for the unsupported target and merge
536536 // it with other supported target dumps.
537- val proxy = unsupportedTargetDumpProxy(klibApiDir, targetConfig,
537+ val proxy = unsupportedTargetDumpProxy(
538+ mainCompilation,
539+ klibApiDir, targetConfig,
538540 extractUnderlyingTarget(currentTarget),
539- apiBuildDir, supportedTargetsProvider)
541+ apiBuildDir, supportedTargetsProvider
542+ )
540543 mergeInferredTask.configure {
541544 it.addInput(targetName, apiBuildDir)
542545 it.dependsOn(proxy)
@@ -555,18 +558,20 @@ private class KlibValidationPipelineBuilder(
555558
556559 private fun Project.targetIsSupported (target : KotlinTarget ): Boolean {
557560 if (bannedTargets().contains(target.targetName)) return false
558- return when (target) {
561+ return when (target) {
559562 is KotlinNativeTarget -> HostManager ().isEnabled(target.konanTarget)
560563 else -> true
561564 }
562565 }
563566
567+ // Compilable targets supported by the host compiler
564568 private fun Project.supportedTargets (): Provider <Set <String >> {
565569 val banned = bannedTargets() // for testing only
566570 return project.provider {
567571 val hm = HostManager ()
568572 project.kotlinMultiplatform.targets.matching { it.emitsKlib }
569573 .asSequence()
574+ .filter { it.mainCompilationOrNull?.hasAnySources() == true }
570575 .filter {
571576 if (it is KotlinNativeTarget ) {
572577 hm.isEnabled(it.konanTarget) && it.targetName !in banned
@@ -579,6 +584,14 @@ private class KlibValidationPipelineBuilder(
579584 }
580585 }
581586
587+ // Returns a predicate that checks if there are any compilable targets
588+ private fun Project.hasCompilableTargetsPredicate (): Provider <Boolean > {
589+ return project.provider {
590+ project.kotlinMultiplatform.targets.matching { it.emitsKlib }
591+ .asSequence()
592+ .any { it.mainCompilationOrNull?.hasAnySources() == true }
593+ }
594+ }
582595
583596 private fun Project.configureKlibCompilation (
584597 compilation : KotlinCompilation <KotlinCommonOptions >,
@@ -590,11 +603,9 @@ private class KlibValidationPipelineBuilder(
590603 val buildTask = project.task<KotlinKlibAbiBuildTask >(targetConfig.apiTaskName(" Build" )) {
591604 target = targetConfig.targetName!!
592605 // Do not enable task for empty umbrella modules
593- isEnabled =
594- klibAbiCheckEnabled(
595- projectName,
596- extension
597- ) && compilation.allKotlinSourceSets.any { it.kotlin.srcDirs.any { it.exists() } }
606+ isEnabled = klibAbiCheckEnabled(projectName, extension)
607+ val hasSourcesPredicate = compilation.hasAnySourcesPredicate()
608+ onlyIf { hasSourcesPredicate.get() }
598609 // 'group' is not specified deliberately, so it will be hidden from ./gradlew tasks
599610 description = " Builds Kotlin KLib ABI dump for 'main' compilations of $projectName . " +
600611 " Complementary task and shouldn't be called manually"
@@ -620,6 +631,7 @@ private class KlibValidationPipelineBuilder(
620631 }
621632
622633 private fun Project.unsupportedTargetDumpProxy (
634+ compilation : KotlinCompilation <KotlinCommonOptions >,
623635 klibApiDir : Provider <File >,
624636 targetConfig : TargetConfig ,
625637 underlyingTarget : String ,
@@ -629,6 +641,8 @@ private class KlibValidationPipelineBuilder(
629641 val targetName = targetConfig.targetName!!
630642 return project.task<KotlinKlibInferAbiForUnsupportedTargetTask >(targetConfig.apiTaskName(" Infer" )) {
631643 isEnabled = klibAbiCheckEnabled(project.name, extension)
644+ val hasSourcesPredicate = compilation.hasAnySourcesPredicate()
645+ onlyIf { hasSourcesPredicate.get() }
632646 description = " Try to infer the dump for unsupported target $targetName using dumps " +
633647 " generated for supported targets."
634648 group = " other"
@@ -676,10 +690,18 @@ private fun extractUnderlyingTarget(target: KotlinTarget): String {
676690private val Project .kotlinMultiplatform
677691 get() = extensions.getByName(" kotlin" ) as KotlinMultiplatformExtension
678692
679- private val KotlinTarget .mainCompilations
680- get() = compilations.matching { it.name == " main " }
693+ private val KotlinTarget .mainCompilationOrNull : KotlinCompilation < KotlinCommonOptions > ?
694+ get() = compilations.firstOrNull { it.name == KotlinCompilation . MAIN_COMPILATION_NAME }
681695
682696private val Project .jvmDumpFileName: String
683697 get() = " $name .api"
684698private val Project .klibDumpFileName: String
685699 get() = " $name .klib.api"
700+
701+ private fun KotlinCompilation<KotlinCommonOptions>.hasAnySources (): Boolean = allKotlinSourceSets.any {
702+ it.kotlin.srcDirs.any(File ::exists)
703+ }
704+
705+ private fun KotlinCompilation<KotlinCommonOptions>.hasAnySourcesPredicate (): Provider <Boolean > = project.provider {
706+ this .hasAnySources()
707+ }
0 commit comments