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

是否有方法定义要在settings.gradle.kts和带有gradle 6.0的项目/子项目build.gradle.kts中使用的属性?,gradle,gradle-kotlin-dsl,Gradle,Gradle Kotlin Dsl,我们有多模块android应用程序,其构建逻辑是用gradle kotlin dsl编写的。我们使用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 =

我们有多模块android应用程序,其构建逻辑是用gradle kotlin dsl编写的。我们使用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"
}
然后,我们可以在模块的依赖项块中使用这些值,以避免硬编码/重复值:

app/build.gradle.kts

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

    implementation(project(Modules.base))
    implementation(project(Modules.baz))
}
include(
    Modules.app,
    Modules.base,
    Modules.baz
)
我们还在settings.gradle.kts中使用它:

include(
    ":app",
    ":base",
    ":baz"
)
settings.gradle.kts

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

    implementation(project(Modules.base))
    implementation(project(Modules.baz))
}
include(
    Modules.app,
    Modules.base,
    Modules.baz
)
这在gradle 5.6中运行正常。当我升级到6.0时,我在settings.gradle.kts文件中得到
未解析的引用:Modules
。我发现它在:

以前,buildSrc项目是在应用项目的设置脚本之前构建的,其类在脚本中可见。现在,buildSrc是在设置脚本及其类不可见之后构建的。buildSrc类对于项目构建脚本和脚本插件仍然可见

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

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

include(
    ":app",
    ":base",
    ":baz"
)

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

AFAIK-不,前面提到的迁移指南就是这么说的:settings.gradle是第一个被评估的,因此,在那个阶段,buildSrc中定义的对象甚至还不存在

我可以想象一些骇人的解决方法——只是为了科学,但在实际项目中,它闻起来太难闻了,在我看来,不值得这么做

注:我想你们可以把它颠倒过来,通过检查buildSrc代码中的子模块,尝试创建一些枚举的实例。但同样,实现这一点的方法可能非常奇特,只能用于证明这一点可行的唯一目的)

请参见

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

这在6.0中有所更改,在5.6中被弃用。请参阅:

--

描述做出决定的原因:

不幸的是,这两种安排都有利弊(
settings然后buildSrc
buildSrc然后settings
),我们在考虑后选择了前者

(……)

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

  • 设置插件会影响buildSrc和主构建(即,将构建插件应用于两者)
  • 生成缓存配置应用于buildSrc
  • buildSrc的行为更像一个常规的包含构建
  • --

    最后是一些坏消息:

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

    --

    权变措施 在上述文章中,作者提出了一些解决办法:

    这个骗局正是你碰到的。现在在设置脚本中使用复杂的逻辑就不那么方便了。现在,您必须:

  • 将逻辑内联到设置文件中
  • 将逻辑移动到一个共享脚本,该脚本可以在需要时使用
  • 将逻辑移到您加载到设置文件中的预构建二进制文件(即设置插件)
  • --

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

    在#3中,作者可能会讨论开发一个外部插件并将其应用于两个脚本中。我真的不确定这是否是一个有意义的实现(尽管它给了你强大的输入)

    “#2将逻辑移到可在需要时使用的共享脚本” 我认为这是关于拥有一个通用的,并将其包含在
    settings.gradle
    build.gradle
    文件中。该插件将把静态信息放在范围内(如果是
    settings.gradle
    script插件,如果是
    build.gradle
    )。这在以下章节中进行了描述:

    如何将所有常用常量(如依赖项版本)放入单独的文件中,仅通过使用类似于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"
    
    您可以这样使用它:

    // $rootDir/build.gradle.kts
    subprojects {
      apply {
        plugin<JavaLibraryPlugin>()
        from("$rootDir/dependencies.gradle.kts")
      }
    
    --


    您能否提供解决方案(第2点和第3点)的外观?