有没有办法定义要在 gradle 6.0 的 settings.gradle.kts 和项目/子项目 build.gradle.kts 中使用的属性?

fer*_*ini 11 gradle gradle-kotlin-dsl

我们有使用 gradle kotlin dsl 编写的构建逻辑的多模块 android 应用程序。我们使用 buildSrc 来提取常见逻辑,例如依赖项版本。我们有类似的东西:

buildSrc/src/main/kotlin/Dependencies.kt

object Versions {
    const val fooVersion = "1.2.3"
    const val barVersion = "4.5.6"
}

object Libraries {
    val foo = "com.example.foo:foo:$fooVersion"
    val bar = "com.example.bar:bar:$barVersion"
}

object Modules {
    const val app = ":app"
    const val base = ":base"
    const val baz = ":baz"
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以在模块的dependencies块中使用这些来避免硬编码/重复值:

app/build.gradle.kts

dependencies {
    implementation(Libs.foo)
    implementation(Libs.bar)

    implementation(project(Modules.base))
    implementation(project(Modules.baz))
}
Run Code Online (Sandbox Code Playgroud)

我们也在 settings.gradle.kts 中使用它:

settings.gradle.kts

include(
    Modules.app,
    Modules.base,
    Modules.baz
)
Run Code Online (Sandbox Code Playgroud)

这适用于 gradle 5.6。当我升级到 6.0 时,我进入Unresolved reference: Modulessettings.gradle.kts 文件。我发现它在迁移指南中提到:

以前,buildSrc 项目是在应用项目的设置脚本之前构建的,并且它的类在脚本中可见。现在, buildSrc 是在设置脚本之后构建的,它的类对它不可见。buildSrc 类对项目构建脚本和脚本插件保持可见。

通过声明外部依赖项,可以从设置脚本中使用自定义逻辑。

所以我知道是什么破坏了构建,我可以通过在 settings.gradle.kts 中使用硬编码值来修复构建:

include(
    ":app",
    ":base",
    ":baz"
)
Run Code Online (Sandbox Code Playgroud)

是否可以使用 gradle 6.0 避免这种重复?

jan*_*nis 5

请参阅票证 #11090“使用 gradle 6.0-rc-1 在 settings.gradle.kts 中找不到来自 buildSrc/ 的定义”

正如您已经注意到的,这最近发生了变化:

这在 6.0 中发生了变化,并在 5.6 中被弃用。请参阅:https : //docs.gradle.org/current/userguide/upgrading_version_5.html#buildsrc_usage_in_gradle_settings

-- https://github.com/gradle/gradle/issues/11090#issuecomment-544473179

其中一位维护者描述了该决定背后的原因:

不幸的是,这两种安排(settings-then-buildSrcbuildSrc-then-settings)各有利弊,我们在考虑后选择了前者。

(……)

迫使我们做出改变的优点:

  1. 设置插件可以影响 buildSrc 和主构建(即对两者应用构建插件)
  2. 构建缓存配置应用于 buildSrc
  3. buildSrc 的行为更像是一个常规的包含构建

-- https://github.com/gradle/gradle/issues/11090#issuecomment-545697268

最后是一些坏消息:

我们不会将行为改回 Gradle 6 之前的安排。如果您想了解更多关于如何使用一种在设置脚本中使用复杂逻辑的替代机制的详细信息,请告诉我们。

-- https://github.com/gradle/gradle/issues/11090#issuecomment-545697268

解决方法

在上述帖子中,作者提出了一些解决方法:

这样做的弊端正是您所遇到的。现在在设置脚本中使用复杂逻辑不太方便。现在,您必须:

  1. 将逻辑内联到设置文件中
  2. 将逻辑移至可在需要的地方使用的共享脚本
  3. 将逻辑移动到您在设置文件中加载的预构建二进制文件(即设置插件)

-- https://github.com/gradle/gradle/issues/11090#issuecomment-545697268

#1 非常简单,但我只能假设 #2 和 #3 的意思。我来自 Groovy 世界,最近才开始与 Kotlin DSL 交朋友。话虽如此,让我们试一试。

在 #3 中,作者可能正在谈论开发外部插件并将其应用到两个脚本中。我不确定这是否对实现有意义(尽管它为您提供了强输入)。

“#2 将逻辑移至可在需要的地方使用的共享脚本”

我认为这是关于拥有一个通用脚本插件并将其包含在settings.gradlebuild.gradle文件中。该插件会把静态信息中ExtraPropertiesExtensionExtensionAware范围(Settings在的情况下,settings.gradle脚本插件,并Project在以下情况下build.gradle)。这在“Include scripts with Gradle Kotlin DSL”的答案中有所描述:

如何将所有常见常量(例如依赖项版本)放入单独的文件中以仅通过使用诸如 springBootVersion 或 Constants.springBootVersion 之类的内容进行编译时检查来包含它们?

目前没有好的方法可以做到。您可以使用额外的属性,但它不能保证编译时检查。类似的东西:

// $rootDir/dependencies.gradle.kts

// this will try to take configuration from existing ones
val compile by configurations
val api by configurations
dependencies {
  compile("commons-io:commons-io:1.2.3")
  api("some.dep")
}

// This will put your version into extra extension
extra["springBootVersion"] = "1.2.3"
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

// $rootDir/build.gradle.kts
subprojects {
  apply {
    plugin<JavaLibraryPlugin>()
    from("$rootDir/dependencies.gradle.kts")
  }
Run Code Online (Sandbox Code Playgroud)

在你的模块中:

// $rootDir/module/build.gradle.kts
// This will take existing dependency from extra
val springBootVersion: String by extra
dependencies {
  compile("org.spring:boot:$springBootVersion")
}
Run Code Online (Sandbox Code Playgroud)

--在 Gradle Kotlin DSL 中包含脚本

  • 您能否提供解决方法(第 2 点和第 3 点)? (2认同)