Как использовать "платформы" Gradle для выравнивания версий зависимостей в многопроектной настройке?

Я пытаюсь научиться использовать "платформы" для выравнивания версий зависимостей между проектами в многопроектной настройке. Пока я видел:

  1. https://docs.gradle.org/6.2.1/userguide/platforms.html
  2. https://docs.gradle.org/6.2.1/userguide/dependency_management_terminology.html
  3. https://docs.gradle.org/6.2.1/userguide/dependency_version_alignment.html
  4. https://docs.gradle.org/6.2.1/userguide/dependency_constraints.html
  5. https://docs.gradle.org/6.2.1/userguide/java_platform_plugin.html
  6. • и еще несколько внешних сайтов, пытающихся найти примеры, например https://dzone.com/articles/gradle-goodness-use-bill-of-materials-bom-as-depen

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

  1. Должен ли я использовать плагин "java platform" или нет? У нас есть не-Java проекты. Наши конфигурации не совсем вписываются в ведра "api" и "время выполнения".
  2. Даже если бы мы все были Java, для любого одного проекта у нас не могло бы быть отдельных версий для его "api" и для его "времени выполнения". Хотя я понимаю уровень контроля, который это может предложить в некоторых случаях, я не понимаю, как они должны работать вместе, чтобы гарантировать, что проект получит указанную зависимость.
  3. Как Gradle узнает, какие ограничения конфигурации должны соответствовать между проектом, использующим платформу, и спецификациями платформы? Я думаю, что видел примеры, определяющие "api" и другие ограничения в платформе, и я "понимаю", что проекты будут ссылаться на это, объявляя платформу api (project(':platform')). Я надеюсь, что Gradle не пытается сопоставить "api" с "api" простым сопоставлением имен. Мне нужно несколько разных конфигураций зависимостей, чтобы все они были согласованы с одной и той же "конфигурацией" единой платформы, как бы она ни называлась.

В общем, я не нашел достаточно информации, чтобы быть уверенным в том, что это делает или как это работает. Может ли кто-нибудь заполнить пробелы или указать мне какой-нибудь документ, в котором будет больше примеров и деталей, чем указано выше? В настоящее время я не понимаю, что я должен написать для этого проекта платформы (егоbuild.gradle) и / или как мне правильно ссылаться на него из текущих проектов, которые у нас есть.

Спасибо!

ОБНОВЛЕНИЕ 1: опубликовал минимальный эксперимент для проверки моего (отсутствия) понимания этого на https://discuss.gradle.org/t/can-someone-tell-me-what-i-am-doing-wrong-to-align-dependency-versions-across-projects/35601...

2 ответа

Должен ли я использовать плагин "java platform" или нет?

Нет. Если у вас есть проекты, отличные от Java, вам не следует использовать подключаемый модуль платформы Java. Как видно из названия плагина, он предназначен для Java-проектов.

Gradle предлагает официальный плагин платформы для проектов Java, но что-либо помимо этого, например C++/Swift, вам нужно будет развернуть свой собственный плагин / реализацию платформы. Вы можете обратиться к исходному коду, чтобы помочь с вашей реализацией.

Даже если бы мы все были Java, для любого одного проекта у нас не могло бы быть отдельных версий для его "api" и для его "времени выполнения".

Вам не нужно иметь отдельные версии для каждой конфигурации. api расширяет implementation а также runtimeClasspath (runtimeOnly) простирается от implementation. Итак, объявив зависимости дляapiдолжно быть достаточно. См. Диаграмму зависимостей здесь.

Как Gradle узнает, какие ограничения конфигурации должны соответствовать между проектом, использующим платформу, и спецификациями платформы?

По тому, как вы указываете это в своем проекте и реализации платформы плагином платформы Java. Например, учитывая следующую платформу:

// my-platform

plugins {
    `java-platform`
}

dependencies {
    constraints {
        api("commons-httpclient:commons-httpclient:3.1")
    }
}

В проекте я могу выполнять любое из следующих действий:

dependencies {
    api(platform(":my-platform"))
    implementation(platform(":my-platform"))
    annotationProcessor(platform(":my-platform"))
}

Я надеюсь, что Gradle не пытается сопоставить "api" с "api" простым сопоставлением имен

Сопоставление выполняется на основе использования. Смотрите эту строку и эти строки.api- это просто имя конфигурации, выбранное Gradle для своего плагина, см. здесь. Они могли выбрать буквально любое имя, но, скорее, выбралиapi/runtime чтобы вещи были похожи на то, что у них есть.

Большая часть документации, которую вы найдете по платформам, ориентирована на разработчиков Java. Я считаю, что это в первую очередь из-за концепции платформы, в значительной степени вдохновленной спецификацией Maven.

Если вы действительно хотите знать, как Gradle делает что-то с платформой, либо мучительно изучите исходный код, либо напишите простой плагин Gradle, который использует платформу, а затем напишите тест с использованием GradleRunner и выполните отладку с точками останова. Пример плагина может быть:

public class ExamplePlatformPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {
        project.getRepositories().mavenCentral();

        DependencyHandler dependencies = project.getDependencies();

        // api(platform(""org.springframework.boot:spring-boot-dependencies:2.2.6.RELEASE"")
        Dependency springBootPlatform = dependencies.platform("org.springframework.boot:spring-boot-dependencies:2.2.6.RELEASE");
        dependencies.add(JavaPlugin.API_CONFIGURATION_NAME, springBootPlatform);

        // api("org.apache.commons:commons-lang3")
        dependencies.add(JavaPlugin.API_CONFIGURATION_NAME, "org.apache.commons:commons-lang3");
    }
}

Альтернативой использованию «платформ» является использование каталога версий. Это более легкий метод определения набора версий зависимостей в центральном месте, но не требует наличия всех этих зависимостей для всего, что на них ссылается.

Каталог версий может быть простым.tomlфайл в вашем проектеgradleподпапку, или он также может быть взят из репозитория плагинов. Вы можете использовать его для создания коллекций зависимостей, которые вы можете называть единым объектом, называемым «пакетом». Например, обратитесь как к API, так и к файлам реализации для чего-то вроде JAXB.

Пример может выглядеть так:

      [versions]
json-b        = "3.0.0"
yasson        = "3.0.2"

[libraries]
json-b-api  = { module = "jakarta.json.bind:jakarta.json.bind-api", version.ref = "json-b" }
json-b-impl = { module = "org.eclipse:yasson", version.ref = "yasson" }

[bundles]
json-b = [
    "json-b-api",
    "json-b-impl",
]

на который вы бы ссылались в своемbuild.gradleфайл так:

      dependencies {
    // JSON Binding (api and implementation)
    implementation libs.bundles.json.b
}

См. последнюю документацию по адресу:https://docs.gradle.org/current/userguide/platforms.html#sub:platforms-vs-catalog .

Другие вопросы по тегам