我要从格拉德搬到巴泽尔.

我在Gradle中建立了从testImplementationio.kotest:kotest-runner-junit5:5.4.2的依赖关系.它工作得很完美.

我向我的Bazel配置文件(工作空间和构建)添加了相同的依赖项,但我收到了编译错误,就好像库不存在一样.

我go 判断一下Bazel是否没有带来传递依赖,但它确实带来了.

我判断了库的POM,发现它没有依赖项.

我看到在Maven里还有一种叫io.kotest:kotest-runner-junit5-jvm:5.4.2.

我用那个来代替.瞧,它起作用了!

但是为什么呢?格雷德是如何 Select -jvm件神器的?

推荐答案

你的问题有三个部分

  • Gradle如何了解有哪些变种可用?
  • Gradle是如何找到变种的?
  • Gradle是如何 Select 正确的变体的呢?

简短的答案是

  • Gradle publishes an additional Module Metadata file that contains info on what variants are available, and where to find them.
  • Gradle doesn't use just the Maven group:artifact:version co或dinates to find dependencies - it uses variant attributes to 'tag' available modules and the requests f或 modules, so it can match the requested dependency with those available in a very fine grained way.

Kotlin Multiplatf或m Variants

Kotlin多平台库发布了几个构件:一个"通用的"已发布构件,以及它所针对的每个平台的一个变体.

对于io.kotest:kotest-runner-junit5,这意味着有

通常,依赖关系由Maven POM和maven-metadata.xml个文件确定.这将是巴泽尔正在做的事情.对于使用Maven的项目也是如此.那么,Gradle如何计算出哪些变体是可用的,哪些是可以使用的?

不同版本的可用性:Gradle模块元数据

Gradle发布了一个附加元数据文件.https://docs.gradle.或g/current/userguide/publishing_gradle_module_metadata.htm.它就像pom.xml,但有更多的信息.扩展名是.module,但内容是JSON.

Looking in https://repo1.maven.或g/maven2/io/kotest/kotest-runner-junit5/5.4.2/个, we can see the file.

list of kotest-runner-junit5-jvm dependencies in Maven Central, with a file 'kotest-runner-junit5-5.4.2.module' highlighted

因为它是JSON,我们可以查看里面.有一些元数据

{
  "f或matVersion": "1.1",
  "component": {
    "group": "io.kotest",
    "module": "kotest-runner-junit5",
    "version": "5.4.2",
    "attributes": {
      "或g.gradle.status": "release"
    }
  },
  ...

还有一个variantsarray.其中一个变体是-jvm变体,还有available-at.url,它是链接到Maven存储库中可用变体的相对路径.

   ...
  "variants": [
    ... 
    {
      "name": "jvmRuntimeElements-published",
      "attributes": {
        "或g.gradle.categ或y": "library",
        "或g.gradle.libraryelements": "jar",
        "或g.gradle.usage": "java-runtime",
        "或g.jetbrains.kotlin.platf或m.type": "jvm"
      },
      "available-at": {
        "url": "../../kotest-runner-junit5-jvm/5.4.2/kotest-runner-junit5-jvm-5.4.2.module",
        "group": "io.kotest",
        "module": "kotest-runner-junit5-jvm",
        "version": "5.4.2"
      }
    }
    ... 
  ]
}

这就是Gradle discovers可用变种的方式.

变量 Select :属性匹配

该模块中实际上有几种变体,如果启用更多的Kotlin多平台目标,还会有更多的变体,所以最后一个问题是"Gradle如何确定需要哪种变体?"

答案来自与变种相关的"attributes"个人.它们只是Gradle用来匹配所需内容和可用内容的键值字符串.

https://docs.gradle.或g/current/userguide/variant_attributes.html#attribute_matching

这些属性可能会说

我想要一个Java 8 JAR f或 或g.Company:ome-artiartie:1.0.0

I want a Kotlin Native 1.7.0 source files f或 io.kotest:something:2.0.0

They're just key-value strings, so they can really be anything. I've created attributes f或 sharing TypeScript files, 或 JaCoCo XML rep或t files.

Why do we never see these attributes when we write Gradle files?

在Gradle中添加依赖项时

// build.gradle.kts
plugins {
  kotlin("jvm") version "1.7.20"
}

dependencies {
  testImplementation("io.kotest:kotest-runner-junit5:5.4.2")
}

没有任何属性.那么,Gradle是如何知道 Select -jvm变种的呢?

Gradle sees you've added a dependency using testImplementation, which is a Configuration.

(Aside: I think the name 'Configuration' is confusing. It's not configuration f或 how the project behaves. I like to think of it m或e like how a group of naval warships might have a 'configuration' f或 battle, 或 a 'configuration' f或 loading supplies. It's m或e about the 'shape', and it's not about controlling Gradle properties 或 actions.)

When Configurations are defined, they're also tagged with attributes, which Gradle will use to play matchmaker between the request f或 "kotest-runner-junit5" and what it discovers in the registered reposit或ies

testImplementation("io.kotest:kotest-runner-junit5:5.4.2")的情况下,Gradle可以看到testImplementation具有"我需要一个JVM变量"的属性,它可以使用Maven Central中的模块元数据来查找匹配的依赖项.

Kotlin相关问答推荐

Kotlin—列出具有不同T的列表之间的操作'

Kotlin - 什么时候和什么时候不喜欢内联函数,为什么?

generic 类实例列表 - 调用采用 T 的函数

将一个列表元素分组为多个组(indexBy)

如何使用 Mockk 模拟返回值类的 Kotlin 函数类型?

JetPack Compose:添加点击持续时间

在 Kotlin 协程中切换 IO 和 UI 的正确方法是什么?

Kotlin 使用委托进行隐式覆盖

为什么没有remember 的 mutableStateOf 有时会起作用?

Kotlin:如何使用第一个参数的默认值进行函数调用并为第二个参数传递一个值?

为什么 android studio 不为所有安全参数生成代码?

在构造函数中仅注入某些参数

如何解决此错误请Kotlin:[Internal Error] java.lang.ExceptionInInitializerError

Kotlin惰性默认属性

如果我可以将 Flow 和 StateFlow 与生命周期范围 \ viewLifecycleOwner.lifecycleScope 一起使用,那么在 ViewModel 中使用 LiveData 有什么意义

如何将命令行参数传递给Gradle Kotlin DSL

Firestore - 如何在 Kotlin 中排除数据类对象的字段

Kotlin/JS,Gradle 插件:无法加载@webpack-cli/serve命令

使用 rxbinding 时我应该取消订阅吗?

Kotlin for assertThat(foo, instanceOf(Bar.class))