我们有多模块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"
}
然后我们可以在模块的dependencies
块中使用它们,以避免硬编码/重复的值:
app/build.gradle.kts
:
dependencies {
implementation(Libs.foo)
implementation(Libs.bar)
implementation(project(Modules.base))
implementation(project(Modules.baz))
}
我们也在settings.gradle.kts中使用它:
settings.gradle.kts
:
include(
Modules.app,
Modules.base,
Modules.baz
)
使用gradle 5.6可以正常工作。升级到6.0时,我在settings.gradle.kts文件中得到Unresolved reference: Modules
。我发现它在migration guide中提到:
以前,buildSrc项目是在应用项目的设置脚本之前构建的,并且其类在脚本中可见。现在,在设置脚本及其类对它不可见之后,将构建buildSrc。 buildSrc类对于项目构建脚本和脚本插件仍然可见。
可以通过声明外部依赖项从设置脚本中使用自定义逻辑。
所以我知道是什么破坏了构建,并且可以通过使用settings.gradle.kts中的硬编码值来修复构建:
include(
":app",
":base",
":baz"
)
是否可以使用gradle 6.0避免这种重复?
答案 0 :(得分:4)
请参见ticket #11090 "Definitions from buildSrc/ not found in settings.gradle.kts using gradle 6.0-rc-1"。
您已经注意到最近发生了变化:
在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
One of the maintainers描述了做出此决定的原因:
不幸的是,这两种安排(
settings-then-buildSrc
和buildSrc-then-settings
)各有利弊,我们在考虑后选择了前者。(...)
迫使我们做出改变的专家:
- 设置插件可以影响buildSrc和主构建(即,将构建插件同时应用于两者)
- 将构建缓存配置应用于buildSrc
- buildSrc的行为更类似于常规包含的构建
-https://github.com/gradle/gradle/issues/11090#issuecomment-545697268
最后是一些坏消息:
我们不会将行为更改回Gradle 6之前的版本。请让我们知道,如果您想了解更多有关如何在设置脚本中使用一种使用复杂逻辑的替代机制的信息。
-https://github.com/gradle/gradle/issues/11090#issuecomment-545697268
在上述文章中,作者提出了一些解决方法:
这恰恰是您所遇到的问题。现在,在设置脚本中使用复杂的逻辑变得不那么方便了。现在,您必须:
- 将逻辑内联到设置文件中
- 将逻辑移动到可以在需要的地方使用的共享脚本
- 将逻辑移至您在设置文件(即设置插件)中加载的预构建二进制文件
-https://github.com/gradle/gradle/issues/11090#issuecomment-545697268
#1非常简单,但是我只能假设#2和#3是什么意思。我来自Groovy世界,直到最近才开始与Kotlin DSL交朋友。话虽如此,让我们尝试一下。
在#3中,作者可能正在谈论开发外部插件并将其应用于两个脚本中。我不太确定这是否可以实现(尽管它可以为您提供强类型的输入)。
我认为这是关于拥有一个公用的script plugin并将其同时包含在settings.gradle
和build.gradle
文件中。该插件会将静态信息放入范围为ExtraPropertiesExtension
的ExtensionAware
的范围内(如果是settings.gradle
脚本插件,则为Settings
;如果是{{ {1}})。 Project
中对此进行了描述:
如何仅通过使用springBootVersion或Constants.springBootVersion之类的东西进行编译时检查,将所有公共常数(例如依赖项版本)放入单独的文件中?
目前尚无好的方法。您可以使用其他属性,但不能保证编译时检查。像这样的东西:
build.gradle
您可以像这样使用它:
// $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") }
答案 1 :(得分:0)
AFAIK-不,这就是上述迁移指南所说的:settings.gradle是第一个要评估的,因此在那个阶段,buildSrc中定义的对象甚至还不存在。
我 可以想象一些骇人听闻的解决方法-仅出于科学目的,但是在实际项目中,它闻起来很难闻,以至于IMO,都不值得。
P。 S .:我想您可以反转它,并尝试通过buildSrc代码中的子模块来创建一些枚举的实例。但同样,实现这一目标的方法可能还很陌生,仅应用于证明其可行的唯一目的