所以我们有了这个构建,在这里我们使用了一些库,无论出于什么原因,这些库已经作为不同的jar文件分发给了不同的本机操作系统.

当然,这些图书馆已经安排好了,如果我们同时包括所有的图书馆,事情就会爆炸.

很好,我们只需确保包含正确的内容,如下所示:

if (isWindows()) {
    runtimeOnly(libraries.nd4j.windows)
    runtimeOnly(libraries.openblas.windows)
} else if (isMacOS()) {
    runtimeOnly(libraries.nd4j.macos)
    runtimeOnly(libraries.openblas.macos)
} else if (isLinux()) {
    runtimeOnly(libraries.nd4j.linux)
    runtimeOnly(libraries.openblas.linux)
}

现在,我当然可以对高尔夫进行一些编码.在函数调用中碰撞条件,然后将条件移动到libraries,这样就没有人看到它,诸如此类的事情.但这不是问题所在.

问题是,当我发布这个项目时,根据我运行构建时使用的操作系统,发布的项目的POM会说它取决于那些JAR的Windows变体.然后,其他人试图在macOS上构建我的项目,但它不起作用.

Had Gradle认识到概要文件的存在并支持它,这些项目可以声明它们有多个概要文件,这些概要文件取决于您运行构建的平台.我们的构建可以做同样的事情,并将其放入POM中.下游项目会看到这一点,一切都会好起来.

然而,Gradle确实有not个支持Maven概要文件来读取或编写POM,因此,将此拆分的唯一方法似乎是将我的项目分为四个子项目——公共部分、windows部分、macos部分和linux部分,以便每个子项目都具有不同的依赖性.然后,我的所有代码都位于公共目录中,大多数依赖关系声明位于公共子项目中,然后每个特定于平台的子项目都将依赖于这两个讨厌的依赖关系的公共版本和相应的特定于平台的版本.

而现在I'm是产生问题的那个,因为任何想使用my库的人都会遇到同样的问题,并对此进行投诉.等等

Is there no better way to go about this?

我知道Kotlin/Multiplatform是一种东西,并且已经看到了这些构建是如何构造的,但是这个项目根本没有使用Kotlin(这是一个Java项目,尽管构建脚本正在被重写为Kotlin DSL),所以它不会从中受益,除非我能够以某种方式将其转换为我们不太相同的用例.

推荐答案

允许以不同方式解析单个依赖关系模块的渐变特性是variant-aware dependency resolution.

有了它,模块可以提供其工件的多个变体,以及多组可传递的依赖项,消费者可以从满足某些属性的依赖项中请求内容,这将导致匹配的依赖项变体.

然而,您的依赖项是已经存在的第三方库,它们当然不会提供您可以通过请求属性来 Select 的变体.

在您这方面,您可以通过执行以下操作之一来解决此问题:

  • 指定component metadata rules,插入到构建的依赖项解析中,并修改特定第三方依赖项的组件元数据adding the Native JAR variants to them.

  • 构建并发布您自己的"伞形"库,这些库将具有依赖于第三方库的平台特定部分的变体.然后使用"伞形"模块作为依赖项,请求与当前平台匹配的属性.

    为此,您需要配置一个没有自己代码的库的构建,但它仍然应该公开具有不同属性的多个变体.在这些变体中,您可以指定不同的依赖项,例如Windows变体中的依赖项nd4j.windows和针对Linux的变体中的依赖项nd4j.linux.

    • 或者让您分发的库成为"多平台",这样就没有单独的"伞形"库,而是您的库具有针对不同平台的多种变体.如果您想简化发布和分发管道,即使以主库构建的复杂性为代价,这也是可取的.

然后,在构建中,需要请求与当前主机对应的属性.

Gradle API中可用于区分操作系统和体系 struct 的常见属性是OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTEMachineArchitecture.ARCHITECTURE_ATTRIBUTE

根据您的 Select ,发布的库将具有原始依赖项或对"伞形"库的依赖项,但无论主机平台如何,它都将具有相同的依赖项.

另一方面,both approaches impose the responsibility on the consumers of your publication也可以通过指定正确的操作系统属性,并可能添加相同的组件元数据规则来调整其构建.这两项都可以通过Gradle插件完成,您可以分发该插件,也可以手动完成.


由于您提到了Kotlin/Multiplatform,您可能会感兴趣的是,上述内容大致上也是Kotlin如何支持指定对多平台库的单个依赖关系.您可以在已发布的Kotlin库中找到特定于平台的变体,例如,在Gradle *.module metadata file of kotlinx.coroutines:

"variants": [
    ...
    {
      "name": "iosArm32MetadataElements-published",
      "attributes": {
        "org.gradle.category": "library",
        "org.gradle.usage": "kotlin-metadata",
        "org.jetbrains.kotlin.native.target": "ios_arm32",
        "org.jetbrains.kotlin.platform.type": "native"
      },
      "available-at": { ... }
    },
    {
      "name": "iosArm64ApiElements-published",
      "attributes": {
        "org.gradle.category": "library",
        "org.gradle.usage": "kotlin-api",
        "org.jetbrains.kotlin.native.target": "ios_arm64",
        "org.jetbrains.kotlin.platform.type": "native"
      },
      "available-at": { ... }
    },
    ...
]

在Kotlin/Multiplatform的情况下,是Kotlin Gradle插件根据消费者的目标平台在消费者端设置了正确的属性.

Java相关问答推荐

Springdoc Whitelabel Error Page with Spring V3

有没有一种方法使保持活动设置专用于java.net.http.HttpClient的一个实例

JPanel透支重叠的JComcoBox

为什么S的文档中说常量方法句柄不能在类的常量池中表示?

支持MySQL 5.6的最新Hibernate版本

在Java 15应用程序中运行Java脚本和Python代码

在Frege中,我如何将一个字符串安全地转换为一个可能的Int?

有没有可能在时间范围内得到多种解决方案?

Java Telnet客户端重复的IAC符号

buildDir:File!&#的getter解决方案是什么?39.被抛弃

垃圾回收器是否真的删除超出作用域的对象?

我可以在@Cacheable中使用枚举吗

如何处理两个几乎相同的XSD文件?

HBox内部的左对齐按钮(如果重要的话,在页码内)

如何通过gradle命令行从build.gradle获得Java targetCompatibility

设置背景时缺少Android编辑文本下划线

MapStruct记录到记录的映射不起作用

在JPanel上使用GridBagLayout并将JButton放在里面时出现问题

Vaadin Flow:设置密码显示按钮属性

for 循环中的第三条语句与主体中的第三条语句之间的区别