@@ -105,7 +105,7 @@ public class BinaryCompatibilityValidatorPlugin : Plugin<Project> {
105
105
kotlin.targets.matching { it.jvmBased }.all { target ->
106
106
val targetConfig = TargetConfig (project, extension, target.name, jvmDirConfig)
107
107
if (target.platformType == KotlinPlatformType .jvm) {
108
- target.mainCompilations.all {
108
+ target.mainCompilationOrNull?. also {
109
109
project.configureKotlinCompilation(it, extension, targetConfig, commonApiDump, commonApiCheck)
110
110
}
111
111
} else if (target.platformType == KotlinPlatformType .androidJvm) {
@@ -219,11 +219,9 @@ private fun Project.configureKotlinCompilation(
219
219
220
220
val apiBuild = task<KotlinApiBuildTask >(targetConfig.apiTaskName(" Build" )) {
221
221
// 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() }
227
225
// 'group' is not specified deliberately, so it will be hidden from ./gradlew tasks
228
226
description =
229
227
" Builds Kotlin API for 'main' compilations of $projectName . Complementary task and shouldn't be called manually"
@@ -419,6 +417,8 @@ private class KlibValidationPipelineBuilder(
419
417
project.name
420
418
projectApiFile = klibApiDir.get().resolve(klibDumpFileName)
421
419
generatedApiFile = klibMergeDir.resolve(klibDumpFileName)
420
+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
421
+ onlyIf(" There are no klibs compiled for the project" ) { hasCompilableTargets.get() }
422
422
}
423
423
424
424
private fun Project.dumpKlibsTask (
@@ -431,6 +431,8 @@ private class KlibValidationPipelineBuilder(
431
431
group = " other"
432
432
from = klibMergeDir.resolve(klibDumpFileName)
433
433
to = klibApiDir.get().resolve(klibDumpFileName)
434
+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
435
+ onlyIf(" There are no klibs compiled for the project" ) { hasCompilableTargets.get() }
434
436
}
435
437
436
438
private fun Project.extractAbi (
@@ -449,6 +451,8 @@ private class KlibValidationPipelineBuilder(
449
451
supportedTargets = supportedTargets()
450
452
inputAbiFile = klibApiDir.get().resolve(klibDumpFileName)
451
453
outputAbiFile = klibOutputDir.resolve(klibDumpFileName)
454
+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
455
+ onlyIf(" There are no klibs compiled for the project" ) { hasCompilableTargets.get() }
452
456
}
453
457
454
458
private fun Project.mergeInferredKlibsUmbrellaTask (
@@ -464,6 +468,8 @@ private class KlibValidationPipelineBuilder(
464
468
" into a single merged KLib ABI dump"
465
469
dumpFileName = klibDumpFileName
466
470
mergedFile = klibMergeDir.resolve(klibDumpFileName)
471
+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
472
+ onlyIf(" There are no dumps to merge" ) { hasCompilableTargets.get() }
467
473
}
468
474
469
475
private fun Project.mergeKlibsUmbrellaTask (
@@ -475,6 +481,8 @@ private class KlibValidationPipelineBuilder(
475
481
" different targets into a single merged KLib ABI dump"
476
482
dumpFileName = klibDumpFileName
477
483
mergedFile = klibMergeDir.resolve(klibDumpFileName)
484
+ val hasCompilableTargets = project.hasCompilableTargetsPredicate()
485
+ onlyIf(" There are no dumps to merge" ) { hasCompilableTargets.get() }
478
486
}
479
487
480
488
fun Project.bannedTargets (): Set <String > {
@@ -499,30 +507,22 @@ private class KlibValidationPipelineBuilder(
499
507
500
508
val supportedTargetsProvider = supportedTargets()
501
509
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
506
511
507
512
val targetName = currentTarget.targetName
508
513
val targetConfig = TargetConfig (project, extension, targetName, intermediateFilesConfig)
509
514
val apiBuildDir = targetConfig.apiDir.map { project.layout.buildDirectory.asFile.get().resolve(it) }.get()
510
515
val targetSupported = targetIsSupported(currentTarget)
511
516
// If a target is supported, the workflow is simple: create a dump, then merge it along with other dumps.
512
517
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)
526
526
}
527
527
return @configureEach
528
528
}
@@ -534,9 +534,12 @@ private class KlibValidationPipelineBuilder(
534
534
}
535
535
// The actual merge will happen here, where we'll try to infer a dump for the unsupported target and merge
536
536
// it with other supported target dumps.
537
- val proxy = unsupportedTargetDumpProxy(klibApiDir, targetConfig,
537
+ val proxy = unsupportedTargetDumpProxy(
538
+ mainCompilation,
539
+ klibApiDir, targetConfig,
538
540
extractUnderlyingTarget(currentTarget),
539
- apiBuildDir, supportedTargetsProvider)
541
+ apiBuildDir, supportedTargetsProvider
542
+ )
540
543
mergeInferredTask.configure {
541
544
it.addInput(targetName, apiBuildDir)
542
545
it.dependsOn(proxy)
@@ -555,18 +558,20 @@ private class KlibValidationPipelineBuilder(
555
558
556
559
private fun Project.targetIsSupported (target : KotlinTarget ): Boolean {
557
560
if (bannedTargets().contains(target.targetName)) return false
558
- return when (target) {
561
+ return when (target) {
559
562
is KotlinNativeTarget -> HostManager ().isEnabled(target.konanTarget)
560
563
else -> true
561
564
}
562
565
}
563
566
567
+ // Compilable targets supported by the host compiler
564
568
private fun Project.supportedTargets (): Provider <Set <String >> {
565
569
val banned = bannedTargets() // for testing only
566
570
return project.provider {
567
571
val hm = HostManager ()
568
572
project.kotlinMultiplatform.targets.matching { it.emitsKlib }
569
573
.asSequence()
574
+ .filter { it.mainCompilationOrNull?.hasAnySources() == true }
570
575
.filter {
571
576
if (it is KotlinNativeTarget ) {
572
577
hm.isEnabled(it.konanTarget) && it.targetName !in banned
@@ -579,6 +584,14 @@ private class KlibValidationPipelineBuilder(
579
584
}
580
585
}
581
586
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
+ }
582
595
583
596
private fun Project.configureKlibCompilation (
584
597
compilation : KotlinCompilation <KotlinCommonOptions >,
@@ -590,11 +603,9 @@ private class KlibValidationPipelineBuilder(
590
603
val buildTask = project.task<KotlinKlibAbiBuildTask >(targetConfig.apiTaskName(" Build" )) {
591
604
target = targetConfig.targetName!!
592
605
// 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() }
598
609
// 'group' is not specified deliberately, so it will be hidden from ./gradlew tasks
599
610
description = " Builds Kotlin KLib ABI dump for 'main' compilations of $projectName . " +
600
611
" Complementary task and shouldn't be called manually"
@@ -620,6 +631,7 @@ private class KlibValidationPipelineBuilder(
620
631
}
621
632
622
633
private fun Project.unsupportedTargetDumpProxy (
634
+ compilation : KotlinCompilation <KotlinCommonOptions >,
623
635
klibApiDir : Provider <File >,
624
636
targetConfig : TargetConfig ,
625
637
underlyingTarget : String ,
@@ -629,6 +641,8 @@ private class KlibValidationPipelineBuilder(
629
641
val targetName = targetConfig.targetName!!
630
642
return project.task<KotlinKlibInferAbiForUnsupportedTargetTask >(targetConfig.apiTaskName(" Infer" )) {
631
643
isEnabled = klibAbiCheckEnabled(project.name, extension)
644
+ val hasSourcesPredicate = compilation.hasAnySourcesPredicate()
645
+ onlyIf { hasSourcesPredicate.get() }
632
646
description = " Try to infer the dump for unsupported target $targetName using dumps " +
633
647
" generated for supported targets."
634
648
group = " other"
@@ -676,10 +690,18 @@ private fun extractUnderlyingTarget(target: KotlinTarget): String {
676
690
private val Project .kotlinMultiplatform
677
691
get() = extensions.getByName(" kotlin" ) as KotlinMultiplatformExtension
678
692
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 }
681
695
682
696
private val Project .jvmDumpFileName: String
683
697
get() = " $name .api"
684
698
private val Project .klibDumpFileName: String
685
699
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