Gradle 和 Shadow 插件 - 在 shadowJar 任务之后将附加文件(.jar 文件)复制到最终 jar

Posted

技术标签:

【中文标题】Gradle 和 Shadow 插件 - 在 shadowJar 任务之后将附加文件(.jar 文件)复制到最终 jar【英文标题】:Gradle and Shadow plugin - copy additional files (.jar files) to final jar after shadowJar task 【发布时间】:2019-03-02 20:16:24 【问题描述】:

问题描述: 我正在使用 Gradle Shade 插件,一切正常,并将资源文件复制到最终的 jar 中。但是,正如docs 所说,它不能将其他.jar 文件包含为资源,因为它无法将它们与依赖项区分开来。它会解开它们而不是。

我想做的事: 我想将tools 文件夹(位于我的build.gradle 旁边)中的额外.jar 文件复制到由shadowJar 任务生成的最终jar 中。

问题: 如何扩展任务 (shadowJar) 以将其他文件复制到生成的 jar 文件中。

【问题讨论】:

我认为您需要更准确地提出问题。您想将其他 JAR 按原样 复制到影子 JAR(即 JAR 中的 JAR 文件)还是要将其他 JAR 的 内容 复制到影子 JAR ? 我认为这个问题准确地说明了我能够复制任何其他资源,除了 jar 文件。 “jar 文件的内容”算作“其他资源”。问题是关于在一个胖罐子里复制额外的罐子。 我了解您的问题“是关于在胖罐中复制额外的罐子”。关键是,您可以通过两种方式将 JAR(例如 j)复制到 Uber JAR(例如 u)中:将 j 的内容解压缩并复制到 u(通常保留文件夹结构,此外还可能合并META-INF/services 文件),或者j按原样 复制到u 中(即文件本身以解压缩的方式)。 @twwt 这就是我想告诉你的。用你的术语来说,我想将一个 jar J 复制到 uber jar U 按原样(不拆包)。问题的“问题描述”部分也说明了这一点 - 它说 shadowJar 解压罐子,而不是逐字复制。我希望 shadowJar 任务将 jar example.jarsome/path/example.jar varbatim 复制到 target/app-uberjar.jar 【参考方案1】:

Gradle shadow 插件的文档Embedding Jar Files Inside Your Shadow Jar 部分对此进行了回答:

[...] shadow 无法区分配置为依赖项的 jar 文件和资源文件夹中包含的 jar 文件。这意味着在资源目录中找到的任何 jar 都将像任何其他依赖项一样合并到影子 jar 中。如果您打算将 jar 嵌入其中,则必须在影子任务开始之前将 jar 重命名为不以 .jar 结尾。

不幸的是,这既适用于作为依赖项配置一部分的 JAR,也适用于使用 from 复制规范复制 JAR(因为 shadowJar 任务扩展了 @ 987654324@ 任务;这又是一个复制任务,因此支持复制规范)。

因此,只能通过重命名来嵌入 JAR。如果必须在 Uber JAR 中将其命名为 .jar,我认为唯一的选择是三步解决方法:

    创建 Uber JAR 并通过重命名嵌入 JAR;例如,使用后缀 *.zip
shadowJar

    from("$dirThatContainsSomeJARs")
    
        include '*.jar'
        rename '(.+).jar', '$1.zip'
    

    解压 Uber JAR 并将所有已嵌入的 JAR 重命名为 *.zip 重新命名为 *.jar。 使用jarzip 任务重新打包所有内容。

【讨论】:

以上是关于Gradle 和 Shadow 插件 - 在 shadowJar 任务之后将附加文件(.jar 文件)复制到最终 jar的主要内容,如果未能解决你的问题,请参考以下文章

如何使用gradle任务运行shadow jar?

使用Gradle Application Plugin插件自动生成可执行.sh和.bat启动脚本

无法在 Intellij 中为 Gradle 导入 ShadowJar 插件

安卓插件化框架Shadow原理分析

jenkins+gradle/maven+sonar+pipline

如何在android studio中查看当前使用的gradle版本和gradle插件版本