Почему я не могу использовать Gradle DSL в прикладных файлах

В нашей команде много проектов, созданных с помощью Gradle. Некоторые части в файлах Gradle одинаковы. Например, мы используем Java 11 во всех наших проектах. Итак, моя идея заключалась в том, чтобы разделить мои файлы build.gradle на общую часть, которая затем синхронизируется из центрального репозитория в каждый проект Gradle, в то время как конкретные части проекта остаются в build.gradle.

построить.градле:

plugins {
    id 'java'
    //...
}

apply from: "common.gradle.kts"

dependencies {
  // ...
}

обыкновенный.градле.ктс

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }
}

test {
    useJUnitPlatform()
}

Теперь я получаю сообщение об ошибке от Gradle

* Where:
Script '/Users/.../common.gradle.kts' line: 4

* What went wrong:
Script compilation errors:

  Line 04:     java {
               ^ Expression 'java' cannot be invoked as a function. The function 'invoke()' is not found

  Line 04:     java {
               ^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
                   public val PluginDependenciesSpec.java: PluginDependencySpec defined in org.gradle.kotlin.dsl

  Line 05:         toolchain {
                   ^ Unresolved reference: toolchain

  Line 06:             languageVersion = JavaLanguageVersion.of(11)
                       ^ Unresolved reference: languageVersion

  Line 09:     test {
               ^ Unresolved reference: test

  Line 10:         useJUnitPlatform()
                   ^ Unresolved reference: useJUnitPlatform

6 errors

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

tasks.withType<JavaCompile> {
    options.release.set(11)
}

Итак, остается вопрос: почему я не могу использовать функции DSL java или test в моем внешнем файле common.gradle.kts?

Кажется, это должно что-то делать с использованием сценария Kotlin, по крайней мере, если я использую Groovy для своего внешнего сценария, он работает.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
35
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем common.gradle.kts, java { } создается вспомогательная функция Kotlin DSL. Gradle не знает о помощниках Kotlin DSL, если только

  1. это часть сборки (не использующая apply(from = "...")
  2. применяется java-плагин

Понимание того, когда доступны методы доступа к моделям с типобезопасностью

Only the main project build scripts and precompiled project script plugins have type-safe model accessors. Initialization scripts, settings scripts, script plugins do not. These limitations will be removed in a future Gradle release.

Реакция на плагины

https://docs.gradle.org/current/userguide/implementing_gradle_plugins.html#reacting_to_plugins

Все еще возможно иметь свой common.gradle.kts, но для этого необходимо настроить плагин Java без DSL Kotlin.

// common.gradle.kts
plugins.withType(JavaBasePlugin::class).configureEach {
    // the project has the Java plugin
    project.extensions.getByType<JavaPluginExtension>().apply {
        toolchain {
            languageVersion.set(JavaLanguageVersion.of(11))
        }
    }
    tasks.withType<Test>().configureEach {
        useJUnitPlatform()
    }
}

Это немного более неуклюже, потому что помощники Kotlin DSL недоступны.

Плагины соглашения buildSrc

Если вы хотите создать соглашения для одного проекта, то стандартным способом является создание подключаемых модулей соглашений buildSrc.

https://docs.gradle.org/current/userguide/organizing_gradle_projects.html#sec:build_sources

Это лучше всего подходит для проектов, которые имеют много подпроектов.

// $projectRoot/buildSrc/src/main/kotlin/java-convention.gradle.kts
plugins {
    java
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }
}

test {
    useJUnitPlatform()
}

См. ответ здесь для более подробной информации: https://stackoverflow.com/a/71892685/4161471

Совместное использование плагинов между проектами

https://docs.gradle.org/current/userguide/implementing_gradle_plugins.html

Можно обмениваться подключаемыми модулями соглашений между проектами, если у вас есть репозиторий Maven для развертывания ваших подключаемых модулей.

Можно даже создать свой собственный дистрибутив Gradle, поэтому плагины включены вместе с оболочкой Gradle! https://docs.gradle.org/current/userguide/organizing_gradle_projects.html#sec:custom_gradle_distribution

Однако я бы посоветовал против этих подходов. Как правило, время, потраченное на создание общих плагинов, никогда не будет меньше, чем просто копирование и вставка плагинов соглашения buildSrc. И что еще более важно, лучше всего, чтобы проекты были независимыми. Хотя обмен соглашениями о сборке кажется хорошей идеей, он вводит зависимости, которые затрудняют отслеживание проблем, и затрудняет обновление общих плагинов, поскольку вы не уверены, какие могут быть последствия. В этой статье объясняется больше https://phauer.com/2016/dont-share-libraries-среди микросервисов/

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