如何在 gradle 中复制依赖库 JAR

Posted

技术标签:

【中文标题】如何在 gradle 中复制依赖库 JAR【英文标题】:how to copy the dependencies libraries JARs in gradle 【发布时间】:2013-01-18 03:40:34 【问题描述】:

我用这个 build.gradle 得到了一个可运行的 jar

apply plugin: 'java'
apply plugin: 'application'

manifest.mainAttributes("Main-Class" : "com.test.HelloWorld")

repositories 
    mavenCentral()


dependencies 
    compile (
        'commons-codec:commons-codec:1.6',
        'commons-logging:commons-logging:1.1.1',
        'org.apache.httpcomponents:httpclient:4.2.1',
        'org.apache.httpcomponents:httpclient:4.2.1',
        'org.apache.httpcomponents:httpcore:4.2.1',
        'org.apache.httpcomponents:httpmime:4.2.1',
        'ch.qos.logback:logback-classic:1.0.6',
        'ch.qos.logback:logback-core:1.0.6',
        'org.slf4j:slf4j-api:1.6.0',
        'junit:junit:4.+'
    )

但它运行失败,因为找不到依赖项。

然后我添加以下代码:

task copyToLib(type: Copy) 
    into "$buildDir/output/libs"
    from configurations.runtime

但没有任何改变...我找不到文件夹 output/libs...

如何将依赖库 jar 复制到指定的文件夹或路径?

【问题讨论】:

如何运行代码? @PeterNiederwieser Niederwieserfirst 我运行:gradle build,然后获取可运行的 jar 文件,运行 jar 文件:java -jar XXX.jar 您可能希望使用同步而不是复制。另见docs.gradle.org/current/userguide/… 【参考方案1】:

应用程序插件要求您像这样设置主类名称:

mainClassName = "com.test.HelloWorld"

您需要将其添加到您的构建脚本中。请记住,如果您尝试使用java 命令运行您的应用程序,您还需要使用-cp 设置类路径。

应用程序插件通过提供任务distZip 来简化此过程。如果您运行该任务,则会在build/distributions 下为您创建一个完整的分发版。该发行版包含启动脚本和所有依赖项。生成的启动脚本已经为您设置了类路径,因此您无需再处理它。

【讨论】:

【参考方案2】:

添加:

build.dependsOn(copyToLib)

gradle build 运行时,Gradle 构建任务以及任何依赖它的任务(由dependsOn 声明)。如果不设置build.dependsOn(copyToLib),Gradle 将不会将复制任务与构建任务关联起来。

所以:

apply plugin: 'java'
apply plugin: 'application'

manifest.mainAttributes('Main-Class': 'com.test.HelloWorld')

repositories 
    mavenCentral()


dependencies 
    compile (
        'commons-codec:commons-codec:1.6',
        'commons-logging:commons-logging:1.1.1',
        'org.apache.httpcomponents:httpclient:4.2.1',
        'org.apache.httpcomponents:httpclient:4.2.1',
        'org.apache.httpcomponents:httpcore:4.2.1',
        'org.apache.httpcomponents:httpmime:4.2.1',
        'ch.qos.logback:logback-classic:1.0.6',
        'ch.qos.logback:logback-core:1.0.6',
        'org.slf4j:slf4j-api:1.6.0',
        'junit:junit:4.+'
    )


task copyToLib(type: Copy) 
    into "$buildDir/output/libs"
    from configurations.runtime


build.dependsOn(copyToLib)

【讨论】:

在 SonarQube 分析中,在 Javacode AST 扫描期间,我收到 ERROR/WARN - Class xx.yy.zz not found。为了解决这个问题,我必须设置“sonar.java.libraries”,其中包含编译、testCompile、运行时所需的所有 jar(依赖项)。我添加了“来自configurations.compile from configurations.testCompile from configurations.runtime”。我在“build/dependent-jars”文件夹中得到了所有的 jars。设置 sonar.java.libraries=build/dependent-jars/*.jar 我没有收到错误。谢谢,因为 gradle 在工作区之外维护其缓存,但使用此代码我能够在构建文件夹中获取 .jar。【参考方案3】:

我发现应用程序插件在其输出中过于繁琐且过于冗长。以下是我最终获得满意设置的方法,即在子目录 /lib 中创建一个包含依赖 jar 的分发 zip 文件,并将所有依赖项添加到清单文件中的 Class-Path 条目:

apply plugin: 'java'
apply plugin: 'java-library-distribution'

repositories 
    mavenCentral()


dependencies 
    compile 'org.apache.commons:commons-lang3:3.3.2'


// Task "distZip" added by plugin "java-library-distribution":
distZip.shouldRunAfter(build)

jar 
    // Keep jar clean:
    exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'

    manifest 
        attributes 'Main-Class': 'com.somepackage.MainClass',
                   'Class-Path': configurations.runtime.files.collect  "lib/$it.name" .join(' ')
    
    // How-to add class path:
    //     http://***.com/questions/22659463/add-classpath-in-manifest-using-gradle
    //     https://gist.github.com/simon04/6865179

作为要点主持here。

结果可以在build/distributions找到,解压出来的内容是这样的:

lib/commons-lang3-3.3.2.jar MyJarFile.jar

MyJarFile.jar#META-INF/MANIFEST.mf的内容:

清单版本:1.0 主类:com.somepackage.MainClass 类路径:lib/commons-lang3-3.3.2.jar

【讨论】:

【参考方案4】:

从 Gradle 6.0 开始是:

tasks 
    val deps by registering(Copy::class) 
        from(configurations.runtimeClasspath)
        into("build/deps")
    

【讨论】:

【参考方案5】:

java 插件可以打包一个带有依赖项的 jar,并且不需要 application 插件。像下面这样的任务会做:

task buildWithDeps(type: Jar) 
    manifest 
        attributes "Main-Class": "com.test.HelloWorld"
    
    from  configurations.compile.collect  it.isDirectory() ? it : zipTree(it)  
    with jar

【讨论】:

这将创建一个胖 jar,问题更多是关于将所有依赖项复制到一个目录。【参考方案6】:

至少从 Gradle 5.6.4 开始,您会想要做一些更接近此的事情。

dependencies 
    implementation 'my.group1:my-module1:0.0.1'
    implementation 'my.group2:my-module2:0.0.1'


jar 
    from 
        configurations.compileClasspath.filter  it.exists() .collect  it.isDirectory() ? it : zipTree(it) 
    

【讨论】:

【参考方案7】:

之前所有答案的问题在于它们只从一个配置中收集依赖项。要获取所有依赖项,您应该使用这个:

task saveDependencies(type: Copy)
    configurations.each 
        if (it.isCanBeResolved())
            from it into "gradle_dependencies"
    
    from buildscript.configurations.classpath into "gradle_dependencies"

【讨论】:

以上是关于如何在 gradle 中复制依赖库 JAR的主要内容,如果未能解决你的问题,请参考以下文章

gradle - 如何在 jar 中声明 jar 的依赖关系

如何通过Gradle将所有依赖项复制到Maven存储库?

在 Android Gradle 构建中,如何从包含的 jar 文件中排除依赖项?

如何在我的 gradle java 项目中包含外部 .jar? [复制]

如何使用具有依赖关系的gradle构建jar文件

如何在Android Gradle中添加原生so文件依赖