Рубрики
Без рубрики

Плагин Gradle для анализа зависимостей: Что такое ABI?

Использование плагина Gradle для анализа зависимостей для определения двоичного API вашей библиотеки. С тегами gradle, java, kotlin, android.

(С благодарностью Джек Дуглас на откреплении для изображения обложки)

Добро пожаловать в мою серию по анализу зависимостей с помощью плагина Dependency Analysis Gradle |/. Этот пост задуман как прямое продолжение предыдущего поста в этой серии, в котором обсуждалось обнаружение неиспользуемых зависимостей.

ABI библиотеки или двоичный интерфейс приложения , это то, что потребители компилируют против (а не то, против чего вы кодируете!). Мне нравится думать об этом как о библиотечном двоичном API . Знание ABI – это то, что позволяет использовать такие функции Gradle, как инкрементная компиляция и предотвращение компиляции. Вы можете думать об ABI библиотеки как о наборе ее общедоступных интерфейсов и зависимостей, необходимых для компиляции с ними: общедоступных методов и их возвращаемых значений и типов параметров, а также общедоступных полей/свойств. Чтобы понять, как это связано с анализом зависимостей, рассмотрим следующее:

fun newOkHttpClient(gson: Gson): OkHttpClient { … }

Это общедоступная функция, которая принимает Gson экземпляр в качестве параметра и возвращает экземпляр OkHttpClient . Это означает, что оба Gson и OkHttp являются частью вашего ABI! В терминах Gradle это означает, что вам нужно следующее в вашем сценарии сборки:

dependencies {
  api "com.google.code.gson:gson:2.8.6"
  api "com.squareup.okhttp3:okhttp:4.8.0"
}

Если вместо api вы использовали реализация , ваш проект все равно будет компилироваться, но вы создадите проблемы для нижестоящих потребителей. Без этих библиотек в их пути к классу компиляции они не смогут компилироваться. Критически важно чтобы авторы библиотек поняли это правильно. Пожалуйста, ознакомьтесь с Gradle documentation для подробного обсуждения этого разделения.

ABI библиотеки определяется с помощью Задачи анализа Abi . Он делегирует зависимостям abi и Общедоступный дамп Api , последний из которых был извлечен непосредственно из репозитория JetBrains | . Он выдает два выходных данных: один представляет собой JSON и предназначен для использования другими задачами, участвующими в анализе зависимостей, а второй представляет собой более понятный для человека текстовый вывод. Выдержки из каждого следуют (где <вариант> будет |/debug (и т.д.) для проекта Android и main для проекта JVM):

json: сборка/отчеты/анализ зависимостей/<вариант>/промежуточные звенья/api.json

[
  {
    "identifier": ":db",
    "configurationName": "implementation"
  },
  {
    "identifier": "androidx.appcompat:appcompat",
    "resolvedVersion": "1.1.0-rc01",
    "configurationName": "implementation"
  }
]

((Вышеизложенное указывает на то, что проект :db и внешняя зависимость androidx.appcompat:appcompat оба являются частью этого ABI проекта и в настоящее время объявлены — неправильно — в “реализации”.)

открытый текст: сборка/отчеты/анализ зависимостей/<вариант>/intermediates/abi-dump.txt

public abstract class com/seattleshelter/core/base/BaseActivity : androidx/appcompat/app/AppCompatActivity {
  public fun  ()V
  protected fun onCreate (Landroid/os/Bundle;)V
}

(Вышеизложенное указывает на то, что общедоступный BaseActivity класс анализируемого проекта расширяет AppCompatActivity и имеет функцию,/| onCreate , для этого требуется Bundle в качестве параметра.)

Плагин использует эту информацию, чтобы консультировать пользователей о том, как лучше всего объявить зависимости своего проекта.

Недавно я обновлял некоторые библиотеки, которые моя команда публикует для внутреннего потребления. Я пробежал build Health по ним и последовал совету. В частности, я сделал это:

(Примечание: номера версий отсутствуют, потому что я использую плагин Java Platform .)

Я подал заявку на пиар. Рецензент вполне резонно спросил, почему я меняю Dagger и RxJava с implementation на api . Где они были разоблачены? Вот что я ему сказал (с некоторыми путями и именами классов, измененными по причинам):

Если вы запустите ./gradlew build Health в этом проекте, а затем откройте hello/build/reports/dependency-analysis/debug/intermediates/abi-dump.txt , вы найдете 24 использование ввода-вывода|reactivex/| (из RxJava2). Вот один пример:

public final class com/hello/MyService {
    public final fun disableService (Landroid/content/Context;)Lio/reactivex/Completable;

Здесь у нас есть открытый класс с открытой функцией, которая возвращает Завершаемый . Таким образом, RxJava 2 является частью ABI этого проекта.

Я вижу 74 результаты для dagger. Вот один из них:

public final class com/hello/dao/DbOp {
    public fun  (Landroid/content/Context;Ldagger/Lazy;)V

А вот открытый класс, открытый конструктор которого принимает Dagger. Lazy в качестве параметра. Итак, Кинжал тоже является частью ABI.

Мне приходилось делать это достаточно часто — то есть удивляться результатам моего собственного плагина, утомительно проверять их вручную, наконец, следовать советам, — что теперь я просто пропускаю первые два шага и следую совету. Это не значит, что плагин всегда прав — есть раздражающие угловые случаи , которые я еще не разрешил, но это правильно более чем в 99% случаев. [требуется проверка] Тем не менее, я рад, что можно проверить результаты вручную, хотя и утомительно.

Я надеюсь, что утомительная часть скоро исчезнет, благодаря новой захватывающей функции, над которой я работаю, под названием ” происхождение “, которая автоматизирует этот процесс объяснения. Вот пример вывода при использовании этой черновой функции в другом проекте

$ ./gradlew db:reasonDebug --id io.reactivex.rxjava2:rxjava
You asked about the dependency io.reactivex.rxjava2:rxjava. You have been advised to add this dependency.

Shortest path to io.reactivex.rxjava2:rxjava from the current project:
:db
\--- androidx.room:room-rxjava2
     \--- io.reactivex.rxjava2:rxjava

Dependency io.reactivex.rxjava2:rxjava provides the following:
- 1651 classes
- 141 public constants

And this project exposes the following classes provided by this dependency:
- io.reactivex.Flowable

Please see abi-dump.txt for more information.

🎉

В этом посте мы узнали, что такое ABI, как он связан с анализом зависимостей и как проверить, выдает ли плагин Dependency Analysis Gradle точные рекомендации по этому вопросу. Пожалуйста, присоединяйтесь ко мне в следующий раз, когда я надеюсь рассказать об основах использования ANTLR для анализа исходного кода.

Оригинал: “https://dev.to/autonomousapps/dependency-analysis-gradle-plugin-what-s-an-abi-3l2h”