Как использовать "платформы" Gradle для выравнивания версий зависимостей в многопроектной настройке?
Я пытаюсь научиться использовать "платформы" для выравнивания версий зависимостей между проектами в многопроектной настройке. Пока я видел:
- https://docs.gradle.org/6.2.1/userguide/platforms.html
- https://docs.gradle.org/6.2.1/userguide/dependency_management_terminology.html
- https://docs.gradle.org/6.2.1/userguide/dependency_version_alignment.html
- https://docs.gradle.org/6.2.1/userguide/dependency_constraints.html
- https://docs.gradle.org/6.2.1/userguide/java_platform_plugin.html
- • и еще несколько внешних сайтов, пытающихся найти примеры, например https://dzone.com/articles/gradle-goodness-use-bill-of-materials-bom-as-depen
Я понимаю, как я могу объявлять ограничения в проекте. Думаю, я также понимаю, как использовать спецификации для этой цели. Однако я хотел бы использовать для этой цели "проект принудительной платформы", и я не понимаю здесь некоторых вещей:
- Должен ли я использовать плагин "java platform" или нет? У нас есть не-Java проекты. Наши конфигурации не совсем вписываются в ведра "api" и "время выполнения".
- Даже если бы мы все были Java, для любого одного проекта у нас не могло бы быть отдельных версий для его "api" и для его "времени выполнения". Хотя я понимаю уровень контроля, который это может предложить в некоторых случаях, я не понимаю, как они должны работать вместе, чтобы гарантировать, что проект получит указанную зависимость.
- Как 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 .