Skip to content

adamko-dev/kotlin-binary-compatibility-validator-mu

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

71af44b · Oct 18, 2024
Mar 6, 2024
Mar 3, 2023
May 31, 2024
Oct 18, 2024
Jan 13, 2024
Feb 28, 2023
Mar 3, 2023
Feb 27, 2023
Jan 13, 2024
Jan 13, 2024
May 31, 2024
Jan 13, 2024
Feb 27, 2023
Jan 13, 2024

Repository files navigation

GitHub license Gradle Plugin Portal Maven Central Maven Central Snapshots

Kotlin Binary Compatibility Validator (Mirror Universe)

BCV-MU is a Gradle Plugin that validates the public JVM binary API of libraries, to make sure that breaking changes are tracked.

BCV-MU is based on Kotlin/binary-compatibility-validator, and contains improvements to better work with the Gradle API, especially in large projects.

Read more about the validation of the public API in the BCV project:

(The MU tag was chosen because I hope to banish this plugin to the Mirror Universe as soon the improvements here are merged upstream.)

Description

Under-the-hood BCV-MU still uses the signature-generation code from BCV, but the Gradle plugin has been refactored to better follow the Gradle API, and generate API signatures more flexibly.

BCV-MU plugin can either be applied as to a Project in any build.gradle(.kts), or (experimentally) as a Settings plugin in settings.gradle(.kts).

Requirements

The minimal supported Gradle version is 7.6.

By default, BCV-MU uses BCV version 0.13.2, which can be overridden, but may introduce runtime errors.

Build plugin

BCV-MU can be applied to each subproject as a standard Gradle plugin.

// build.gradle.kts

plugins {
  id("dev.adamko.kotlin.binary-compatibility-validator") version "$bcvMuVersion"
}

To initialise the API declarations, run the Gradle task

./gradlew apiDump

This will produce API files into the ./api directory of subprojects with the BCV-MU plugin. These API declarations files must be committed to the repository.

To verify that the API declarations is up-to-date, run the Gradle task

./gradlew apiCheck

The apiCheck task will also be run whenever the check task is run.

Configuration

BCV-MU can be configured in a similar manner to BCV:

// build.gradle.kts

plugins {
  kotlin("jvm") version "1.8.10"
  id("dev.adamko.kotlin.binary-compatibility-validator") version "$bcvMuVersion"
}

binaryCompatibilityValidator {

  // Explicitly include specific classes, markers, or packages.
  // If any class, marker, or package is defined then all other declarations will be excluded.
  // If no explicit public declarations are defined, then all declarations will be included by default.
  publicClasses.add("com.company.api.FooPublicClass")
  publicMarkers.add("com.company.api.ExplicitApiAnnotation")
  publicPackages.add("com.company.api")

  // Packages that are excluded from public API dumps even if they contain public API.
  ignoredPackages.add("kotlinx.coroutines.internal")
  // Classes (fully qualified) that are excluded from public API dumps even if they contain public API.
  ignoredClasses.add("com.company.BuildConfig")
  // Set of annotations that exclude API from being public.
  // Typically, it is all kinds of `@InternalApi` annotations that mark
  // effectively private API that cannot be actually private for technical reasons.
  ignoredMarkers.add("my.package.MyInternalApiAnnotation")

  // Disable or enable all BCV-MU tasks for this project
  bcvEnabled.set(true)

  // Override the default BCV version
  kotlinxBinaryCompatibilityValidatorVersion.set("0.13.2")
}
Advanced configuration

BCV automatically generates 'targets' for each Kotlin/JVM source set that it finds. these BCVTargets can be specifically modified, or manually defined, for fine-grained control.

// build.gradle.kts

plugins {
  kotlin("jvm") version "1.8.10"
  id("dev.adamko.kotlin.binary-compatibility-validator") version "$bcvMuVersion"
  `java-test-fixtures`
}

binaryCompatibilityValidator {
  // these are the default values that will be used in all Targets
  ignoredMarkers.add("my.package.MyFirstInternalApiAnnotation")
  ignoredClasses.add("com.company.BuildConfig")

  // BCV will automatically generate targets for each Kotlin/JVM target,
  // and each can be configured manually for fine-grained control. 
  targets.configureEach {
    // values can be appended to the default values
    ignoredMarkers.add("my.package.MySecondInternalApiAnnotation")
    // Or overridden
    ignoredClasses.set(listOf())
  }

  // BCV will automatically register a target for testFixtures, but it must be enabled manually
  targets.testFixtures {
    enabled.set(true)
  }

  // BCV Targets can also be manually defined
  targets.register("customTarget") {
    inputJar.set(tasks.customTargetJar.flatMap { it.archiveFile })
  }
}
Shared configuration with a convention plugin

To share common configuration it is best to set up a convention-plugin.

If you don't have any convention plugins already, then here's a quick guide.

First, set-up buildSrc by creating a file ./buildSrc/build.gradle.kts

In it, add the kotlin-dsl plugin, and add the BCV-MU plugin as a dependency.

// ./buildSrc/build.gradle.kts

plugins {
  `kotlin-dsl`
}

repositories {
  mavenCentral()
  gradlePluginPortal()
}

dependencies {
  // add the *Maven coordinates* of the bcv-MU plugin, not the plugin ID, as a dependency
  implementation("dev.adamko.kotlin.binary-compatibility-validator:bcv-gradle-plugin:$bcvMuVersion")
}

Next, create a convention plugin. This is where any shared configuration can be defined.

// buildSrc/src/main/kotlin/binary-compatibility-validator-convention.gradle.kts

plugins {
  id("dev.adamko.kotlin.binary-compatibility-validator") // no version needed - it's defined in buildSrc/build.gradle.kts
}

binaryCompatibilityValidator {
  ignoredClasses.add("com.company.BuildConfig")
}

Finally, apply the convention plugin to subprojects. This will automatically re-use the same configuration.

// ./some/subproject/build.gradle.kts
plugins {
  id("binary-compatibility-validator-convention")
  kotlin("jvm")
}

Settings plugin

There is experimental support for applying BCV-MU as a Settings plugin.

This allows for applying BCV-MU to all subprojects in a Gradle-friendly way. All subprojects are included by default, and can be excluded using BCV-MU config.

// settings.gradle.kts

buildscript {
  dependencies {
    // BCV-MU requires the Kotlin Gradle Plugin classes are present
    classpath("org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.10")
  }
}

plugins {
  id("dev.adamko.kotlin.binary-compatibility-validator") version "$bcvMuVersion"
}

binaryCompatibilityValidator {
  ignoredProjects.addAll(

    ":",                // ignore root project
    ":some-subproject", // ignore subprojects explicitly

    // or ignore using a glob pattern
    ":internal-dependencies:*",
    ":*-tasks:**",
  )

  // set the default values for all targets in all enabled-subprojects 
  defaultTargetValues {
    enabled.convention(true)
    ignoredClasses.set(listOf("com.package.MyIgnoredClass"))
    ignoredMarkers.set(listOf("com.package.MyInternalApiAnnotationMarker"))
    ignoredPackages.set(listOf("com.package.my_ignored_package"))
  }
}

include(
  // these projects will have BCV-MU automatically applied
  ":common",
  ":internal-dependencies:alpha:nested",
  ":internal-dependencies:alpha:nested",
  ":a-task",

  // this subproject is explicitly excluded from BCV
  ":some-subproject",

  // these subprojects will be excluded by glob pattern
  ":internal-dependencies",
  ":internal-dependencies:alpha",
  ":internal-dependencies:beta",
  ":x-tasks",
  ":x-tasks:sub1",
  ":x-tasks:sub1:sub2",
  ":z-tasks",
  ":z-tasks:sub1",
  ":z-tasks:sub1:sub2",
)

License

The code in this project is based on the code in the Kotlin/binary-compatibility-validator project.