当前位置: 首页 > 知识库问答 >
问题:

是否有方法定义两种设置中使用的属性。格拉德尔。kts和项目/子项目构建。格拉德尔。带gradle 6.0的kts?

百里杰
2023-03-14

我们有多模块的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。格拉德尔。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时,我会在设置中获得未解析的引用:模块。格拉德尔。kts文件。我发现《迁移指南》中提到了:

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

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

所以我知道是什么破坏了构建,我可以通过使用设置中的硬编码值来修复构建。格拉德尔。kts:

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

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

共有2个答案

漆雕伟志
2023-03-14

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

我可以想象一些古怪的变通方法——只是为了科学,但在真正的项目中,它会闻起来很糟糕,依我看,不值得。

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

蓟捷
2023-03-14

请参阅票证#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然后buildSrcbuildSrc然后settings),我们在考虑后选择了前者。

(...)

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

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

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

最后是一些坏消息

我们不会将行为改变回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中,作者可能会谈论开发一个外部插件并在两个脚本中应用它。我不太确定这是否是实现起来有意义的东西(尽管它给了你很强的打字能力)。

我认为这是关于拥有一个通用的脚本插件,并将其包含在两个设置中。渐变构建。gradle文件。该插件将把静态信息放入范围内扩展软件ExtraPropertiesExtension设置如果是设置.gradle脚本插件,而项目如果是构建.gradle)。这在“使用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"

您可以这样使用它:

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

在您的模块中:

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

--使用Gradle Kotlin DSL包含脚本

 类似资料:
  • 我有一个由gradle建造的战争项目。我有一个字符串gradle.build文件:编译'log4j: log4j: 1.2.17'但没有任何log4j.jar结果WEB-INF/lib目录在myproject.war文件。 但“compile”配置中定义的所有其他lib都存在。为什么会有如此奇怪的行为,它是一个bug还是某种功能?如何将其包含在我的网络档案中? Eclipse在项目的“网络应用程序

  • 我正在尝试让我现有的Android项目与渐变和智能J 12一起工作。以前,我曾让它与maven一起工作,但这似乎不像gradle那样灵活,而且据我所知,我需要的子文件夹更少。 我的Android项目分为干净的java库(:core)和实际的应用程序(:Android)。这两个项目都在我的主项目文件夹中。 我认为,用这个实现gradle工作的理想解决方案是将(:core)和(:android)项目视

  • 我试图用我的gradle项目运行junit测试,但不管是什么测试,它们都会抛出以下堆栈跟踪 我已经看到了一些建议的解决方案,但似乎没有一个奏效。当我在ant中运行它们时,我的测试运行良好。我已经确保xerces使用的是最新版本,我还添加了建议的版本 对于JVM,但似乎什么都不起作用。 任何建议都将不胜感激。我可以根据要求提供更多信息。 **更新** 做了以下更改- 但现在的结果如图所示 **更新2

  • 我被困在Android Studio中的Eclipse项目的导入。我试图导入它,但gradle.properties文件丢失。所以当我同步项目时,它说以下错误。 错误:无法启动守护进程:无法为对象堆保留足够的空间。请在项目的gradle.properties文件中为Gradle分配更多内存。例如,gradle.properties文件中的以下行将最大Java堆大小设置为1,024 MB:org.g

  • 谷歌刚刚开源了它的构建工具Bazel。这个工具和Gradle有什么不同?它能做什么是Gradle做不到的,它做什么更好,Gradle做什么更好?

  • 我正试图用quarkus运行简单的“入门”型gradle项目,每次我的单元测试都会因为这个错误而失败 按照这里的指示https://quarkus.io/guides/gradle-tooling对正在发生的事情有什么建议或想法吗?