Skip to content

Commit

Permalink
Add binary-compatibility-validator and API dumps for desktop (#803)
Browse files Browse the repository at this point in the history
https://github.com/Kotlin/binary-compatibility-validator

This plugin dumps all API for JVM modules to files (in the future - for
other targets). If API changed, we should call:
```
./gradlew desktopApiDump
```
to commit a new API, otherwise CI will fail (`./gradlew desktopCICheck`
will be called on CI`).

If you see that some strings are deleted in the API dump, most probably
it means an incompatible API change (the plugin doesn't check itself,
unfortunately).

See [the official workflow
guide](https://github.com/Kotlin/binary-compatibility-validator#workflow)
to understand it more.

Example of error:
```
Execution failed for task ':compose:material3:material3:desktopApiCheck'.
> API check failed for project material3.
  --- D:\Work\compose-multiplatform-core\compose\material3\material3\api\desktop\material3.api
  +++ D:\Work\compose-multiplatform-core\out\androidx\compose\material3\material3\build\api\desktop\material3.api
  @@ -552,6 +552,11 @@
   public abstract interface annotation class androidx/compose/material3/ExperimentalMaterial3Api : java/lang/annotation/Annotation {
   }

  +public final class androidx/compose/material3/FF {
  +     public static final field $stable I
  +     public fun <init> ()V
  +}
  +
   public final class androidx/compose/material3/FabPosition {
        public static final field Companion Landroidx/compose/material3/FabPosition$Companion;
        public static final synthetic fun box-impl (I)Landroidx/compose/material3/FabPosition;

   You can run :material3:apiDump task to overwrite API declarations
```

One disadvantage that error shows `apiDump` instead of `desktopApiDump`.
`apiDump` doesn't work because of the broken Android target, and to fix
it properly we need to do a lot of changes. Just disabling the tasks
doesn't work.

- Desktop API is constructed from desktopMain + skikoMain + commonMain
sourceSets

- Android API is constructed from desktopMain + commonMain. It is
disabled for now, because Android build is broken. The plan is to fix
the Android target, and dump Android API as well. It will help us to
track new API that we need to port more easily.

P.S. Jetpack Compose sources has its own API generator (Metalava), but
it won't be applicable to other Kotlin targets in the future, but
binary-compatibility-validator
[will](Kotlin/binary-compatibility-validator#149)

## Test
1. call desktopCICheck - it succeeds
2. change/add API
3. call desktopCICheck - it fails

---------

Co-authored-by: Ivan Matkov <[email protected]>
  • Loading branch information
igordmn and MatkovIvan authored Sep 13, 2023
1 parent 48ac2b8 commit 494405d
Show file tree
Hide file tree
Showing 27 changed files with 57,730 additions and 1 deletion.
32 changes: 32 additions & 0 deletions MULTIPLATFORM.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,38 @@ Run tests for UIKit:
./gradlew :mpp:testUIKit
```

### API checks
Compose Multiplatform stores all public API in *.api files. If any API is added/changed, `./gradlew checkDesktop` will fail with an error that API is changed (it runs on CI). Example:

```
Execution failed for task ':compose:material3:material3:desktopApiCheck'.
> API check failed for project material3.
--- D:\Work\compose-multiplatform-core\compose\material3\material3\api\desktop\material3.api
+++ D:\Work\compose-multiplatform-core\out\androidx\compose\material3\material3\build\api\desktop\material3.api
@@ -552,6 +552,11 @@
public abstract interface annotation class androidx/compose/material3/ExperimentalMaterial3Api : java/lang/annotation/Annotation {
}
+public final class androidx/compose/material3/FF {
+ public static final field $stable I
+ public fun <init> ()V
+}
+
public final class androidx/compose/material3/FabPosition {
public static final field Companion Landroidx/compose/material3/FabPosition$Companion;
public static final synthetic fun box-impl (I)Landroidx/compose/material3/FabPosition;
You can run :material3:apiDump task to overwrite API declarations
```

To fix this error:
1. Run `./gradlew desktopApiDump`
2. See what has changed in *.api files.
3. If there are only additions - there is no binary incompatible change.
4. If there are some removals - most probably there is a binary incompatible change and it needs to be fixed before merging it to the main branch.

Note that only desktop has API checks at the moment, but in the future it will be added for all targets.

### Publishing
Compose Multiplatform core libraries can be published to local Maven with the following steps:
1. Set `COMPOSE_CUSTOM_VERSION` environment variable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019 The Android Open Source Project
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -305,6 +305,9 @@ class AndroidXComposeImplPlugin : Plugin<Project> {
"multiplatformExtension is null (multiplatform plugin not enabled?)"
}

val androidXExtension = project.extensions.findByType(AndroidXExtension::class.java)
?: throw Exception("You have applied AndroidXComposePlugin without AndroidXPlugin")

/*
The following configures source sets - note:
Expand Down Expand Up @@ -336,6 +339,10 @@ class AndroidXComposeImplPlugin : Plugin<Project> {
if (multiplatformExtension.targets.findByName("desktop") != null) {
tasks.named("desktopTestClasses").also(::addToBuildOnServer)
}

if (androidXExtension.type == LibraryType.PUBLISHED_LIBRARY) {
project.apply(plugin = "org.jetbrains.kotlinx.binary-compatibility-validator")
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions buildSrc/shared-dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies {
implementation(libs.androidToolsRepository) // com.android.repository for Stable AIDL plugin
implementation(libs.androidToolsSdkCommon) // com.android.ide.common for Stable AIDL plugin
implementation(libs.kotlinGradlePluginz)
implementation(libs.kotlinBinaryCompatibilityValidatorGradlePlugin)

// variety of json parsers
implementation(libs.gson)
Expand Down
812 changes: 812 additions & 0 deletions compose/animation/animation-core/api/desktop/animation-core.api

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
public abstract interface annotation class androidx/compose/animation/graphics/ExperimentalAnimationGraphicsApi : java/lang/annotation/Annotation {
}

public final class androidx/compose/animation/graphics/vector/AnimatedImageVector {
public static final field $stable I
public static final field Companion Landroidx/compose/animation/graphics/vector/AnimatedImageVector$Companion;
public final fun getImageVector ()Landroidx/compose/ui/graphics/vector/ImageVector;
public final fun getTotalDuration ()I
}

public final class androidx/compose/animation/graphics/vector/AnimatedImageVector$Companion {
}

201 changes: 201 additions & 0 deletions compose/animation/animation/api/desktop/animation.api

Large diffs are not rendered by default.

353 changes: 353 additions & 0 deletions compose/foundation/foundation-layout/api/desktop/foundation-layout.api

Large diffs are not rendered by default.

1,719 changes: 1,719 additions & 0 deletions compose/foundation/foundation/api/desktop/foundation.api

Large diffs are not rendered by default.

1,018 changes: 1,018 additions & 0 deletions compose/material/material-icons-core/api/desktop/material-icons-core.api

Large diffs are not rendered by default.

41,640 changes: 41,640 additions & 0 deletions compose/material/material-icons-extended/api/desktop/material-icons-extended.api

Large diffs are not rendered by default.

31 changes: 31 additions & 0 deletions compose/material/material-ripple/api/desktop/material-ripple.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
public final class androidx/compose/material/ripple/RippleAlpha {
public static final field $stable I
public fun <init> (FFFF)V
public fun equals (Ljava/lang/Object;)Z
public final fun getDraggedAlpha ()F
public final fun getFocusedAlpha ()F
public final fun getHoveredAlpha ()F
public final fun getPressedAlpha ()F
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class androidx/compose/material/ripple/RippleKt {
public static final fun rememberRipple-9IZ8Weo (ZFJLandroidx/compose/runtime/Composer;II)Landroidx/compose/foundation/Indication;
}

public abstract interface class androidx/compose/material/ripple/RippleTheme {
public static final field Companion Landroidx/compose/material/ripple/RippleTheme$Companion;
public abstract fun defaultColor-WaAFU9c (Landroidx/compose/runtime/Composer;I)J
public abstract fun rippleAlpha (Landroidx/compose/runtime/Composer;I)Landroidx/compose/material/ripple/RippleAlpha;
}

public final class androidx/compose/material/ripple/RippleTheme$Companion {
public final fun defaultRippleAlpha-DxMtmZc (JZ)Landroidx/compose/material/ripple/RippleAlpha;
public final fun defaultRippleColor-5vOe2sY (JZ)J
}

public final class androidx/compose/material/ripple/RippleThemeKt {
public static final fun getLocalRippleTheme ()Landroidx/compose/runtime/ProvidableCompositionLocal;
}

Loading

0 comments on commit 494405d

Please sign in to comment.