本文由 简悦SimpRead 转码,原文地址 blog.gradle.org
Gradle模块元数据在Gradle 5.3中达到1.0,这里我们解释了为什么你应该像......。
Gradle模块元数据在Gradle 5.3中达到了1.0,在此我们解释一下为什么你应该像我们一样兴奋!"。
Gradle模块元数据的创建是为了解决多年来困扰依赖性管理的许多问题,特别是在Java生态系统中,但不限于此。它特别重要,因为POM文件(或Ivy文件)根本不足以描述现在的软件现实,在这种情况下,你可能需要区分不同平台的二进制文件,或者在有多个API可用时选择一个特定的实现。
我们将在本帖后面描述更多的例子。有些问题可能有变通办法,但这些变通办法是黑客式的,甚至是容易出错的。例如,你是否意识到这些是有问题的:为不同的Java版本使用分类器,为避免特定的记录器绑定而使用排除法,或者仅仅因为你需要覆盖一个特定的版本而添加第一层依赖关系?
Gradle模块元数据1.0是对这些问题的一个回答,也是我们整个行业向更好的依赖管理迈出的第一步。
它在实践中允许什么?
当你在classpath上同时拥有guava-jdk5和guava-jdk8时,你是否曾经咒骂过,而你的应用程序只是因为幸运的排序而运行?你有没有遇到过这样的问题:有不同的SLF4J绑定,但在运行时才发现?那是因为这些库有不同的_变体,无法用现有的元数据格式正确描述。一个构建工具怎么能理解 "jdk8 "JAR、"sources "JAR、甚至 "all "JAR之间的区别?Gradle模块元数据的设计是为了以这样一种方式来解释区别,即消费者可以表达更精确的需求。例如,消费者可以特别要求他们能在JDK 8上使用的东西。而在SLF4J的情况下,构建工具会识别出Log4J的绑定与java.util.logging的绑定是互斥的。
整个想法是支持变体感知的依赖管理,这是基于对组件变体的描述--如主二进制文件、源码包、平台特定二进制文件等--以及它们相应的依赖关系。
我们的一些合作伙伴已经使用Gradle元数据好几个月了。例如,Kotlin native正在使用Gradle模块元数据来表示在将一个Kotlin项目编译到不同的架构时可以得到的不同二进制文件。Google正在使用variant-aware dependency management,但缺乏一个 "外部模型"。Gradle模块元数据就是那个外部模型,并将允许正确发布Android档案(AAR)。
这些只是例子,但这些问题以及更多的问题都可以通过利用Gradle元数据来解决。随着更多的库作者采用Gradle模块元数据,我们的行业将从整体上解决更多的问题。
Gradle Module Metadata如何影响你
Gradle Module Metadata 1.0为所有Gradle用户实现了细粒度的依赖解决。从Gradle 5.3开始,如果你是一个消费者,并且你使用的库有Gradle元数据发布,Gradle将自动消费任何发布到Maven或Ivy仓库的Gradle元数据。
然而,Gradle 5.3默认不会自动 发布 --这将在6.0中出现。你现在就可以发布Gradle模块元数据,但你必须通过使用Maven Publish或Ivy Publish插件来选择发布,并通过在设置脚本中添加以下一行来启用实验性发布功能。
settings.gradle(.kts)
enableFeaturePreview("GRADLE_METADATA")
Gradle模块元数据对Maven或Ant+Ivy的构建有何影响?
对于Maven和Ivy消费者来说,没有什么变化:如果你选择了发布Gradle模块元数据,相应的文件会与POM文件(如果你发布到Maven资源库)或Ivy文件(如果你发布到Ivy资源库)一起发布。请注意,从构建组件到Maven和Ivy元数据的映射是 lossy 的:例如,你不知道用什么Java版本来构建什么东西,所以这使得消费者无法事先知道它们是否兼容。另一个例子是当你使用Gradle的特定功能,如丰富的版本。我们尽力将它们映射到Maven或Ivy中的概念,但由于它们的元数据格式的限制,信息还是会在这个过程中丢失。
请注意,Gradle 5.2引入了发布插件的警告,当它知道映射对其他构建工具来说是有损失或有问题时,会发出警告。
链接和参考文献
Gradle模块元数据是一个JSON文件,其扩展名为.module。每个文件都描述了一个具有零个或多个变体的单一软件组件。下面是一个 "com.acme:client:1.0-SNAPSHOT "组件的元数据文件示例的内容,其中有几个变体。
{
"formatVersion": "1.0",
"component": {
"group": "com.acme",
"module": "client",
"version": "1.0-SNAPSHOT",
"attributes": {
"org.gradle.status": "integration"
}
},
"createdBy": {
"gradle": {
"version": "5.3",
"buildId": "4wqjtkcv2fbmjjsewyu66wbvfq"
}
},
"variants": [
{
"name": "apiElements",
"attributes": {
"org.gradle.dependency.bundling": "external",
"org.gradle.jvm.version": 11,
"org.gradle.usage": "java-api-jars"
},
"dependencies": [
{
"group": "com.mycompany",
"module": "core",
"version": {
"requires": "2.5"
}
}
],
"files": [
{
"name": "client-1.0-SNAPSHOT.jar",
"url": "client-1.0-SNAPSHOT.jar",
"size": 539,
"sha1": "1f94fe53d33babdc9de537bb3a0108dbc0e25e4b",
"md5": "6364cdd9923e1eda9b328bc80f93969c"
}
]
},
{
"name": "runtimeElements",
"attributes": {
"org.gradle.dependency.bundling": "external",
"org.gradle.jvm.version": 11,
"org.gradle.usage": "java-runtime-jars"
},
"dependencies": [
{
"group": "org.apache.commons",
"module": "commons-lang3",
"version": {
"requires": "3.8"
}
},
{
"group": "com.mycompany",
"module": "core",
"version": {
"requires": "2.5"
}
}
],
"files": [
{
"name": "client-1.0-SNAPSHOT.jar",
"url": "client-1.0-SNAPSHOT.jar",
"size": 539,
"sha1": "1f94fe53d33babdc9de537bb3a0108dbc0e25e4b",
"md5": "6364cdd9923e1eda9b328bc80f93969c"
}
]
},
{
"name": "shadowApiElements",
"attributes": {
"org.gradle.dependency.bundling": "shadowed",
"org.gradle.usage": "java-api"
},
"files": [
{
"name": "client-1.0-SNAPSHOT-all.jar",
"url": "client-1.0-SNAPSHOT-all.jar",
"size": 601730,
"sha1": "9b70e54ffdce0541701d8f855bf75e059857eb0c",
"md5": "3499bb6d9ccf86283854a5550135ea4a"
}
]
},
{
"name": "shadowRuntimeElements",
"attributes": {
"org.gradle.dependency.bundling": "shadowed",
"org.gradle.usage": "java-runtime-jars"
},
"files": [
{
"name": "client-1.0-SNAPSHOT-all.jar",
"url": "client-1.0-SNAPSHOT-all.jar",
"size": 601730,
"sha1": "9b70e54ffdce0541701d8f855bf75e059857eb0c",
"md5": "3499bb6d9ccf86283854a5550135ea4a"
}
]
}
]
}
这个文件声明了4个变体,而属性让构建工具知道它们的用途。特别是你会看到这里有2个 "API "的变体和2个 "运行时 "的变体,而通常你只看到每个变体的一个。原因是这个特殊的组件声明了一个额外的变体,其中的依赖关系是 shadowed(胖jar)。这使消费者有机会决定它是否需要单独的jar,或者只是库的fatjar变体。
如果你对更多技术细节感兴趣,请参考Gradle模块元数据规范1.0
欢迎早期采用者,请随时给出你的反馈!