gradle - how do I build a jar with a lib dir with other jars in it?

99,608

Solution 1

If you have all the jars inside a directory (lets call it libs) in your project, you only need this:

jar {
    into('lib') {
        from 'libs'
    }
}

I guess it is more likely that these jars are dependencies of some sort. Then you could do it like this:

configurations {
    // configuration that holds jars to copy into lib
    extraLibs
}
dependencies {
    extraLibs 'org.something:something-dep1:version'
    extraLibs 'org.something:something-dep2:version'
}

jar {
    into('lib') {
        from configurations.extraLibs
    }
}

Solution 2

Lifted verbatim from: http://docs.codehaus.org/display/GRADLE/Cookbook#Cookbook-Creatingafatjar

Gradle 0.9:

jar {
    from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}

Gradle 0.8:

jar.doFirst {
    for(file in configurations.compile) {
        jar.merge(file)
    }
}

The above snippets will only include the compile dependencies for that project, not any transitive runtime dependencies. If you also want to merge those, replace configurations.compile with configurations.runtime.

EDIT: only choosing jars you need

Make a new configuration, releaseJars maybe

configurations {
    releaseJars
}

Add the jars you want to that configuration

dependencies {
    releaseJars group: 'javax.mail', name: 'mail', version: '1.4'
    //etc
}

then use that configuration in the jar task outlined above.

Solution 3

simple:

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

jar { dependsOn copyToLib }

run it:

$ gradle jar
...
$ tree build/libs

build/libs
├── your-project-0.0.1.BUILD-SNAPSHOT.jar
└── lib
    ├── akka-actor-2.0.jar
    ├── akka-camel-2.0.jar
    ├── ... ... ...
    ├── spring-expression-3.1.0.RELEASE.jar
    └── zmq-2.1.9.jar

1 directory, 46 files

Solution 4

I also needed to do something similar and wasn't quite able to get what Guus and stigkj suggested working, but got close enough with their help to get this working (Guus' example blew up on the dependencies { compile { extendsFrom myLibs }} closure for me.

apply plugin: 'groovy'

repositories {
    mavenCentral()
}

configurations {
    // custom config of files we want to include in our fat jar that we send to hadoop
    includeInJar
}

dependencies {
    includeInJar 'org.codehaus.groovy:groovy:1.8.6'

    configurations.compile.extendsFrom(configurations.includeInJar)
}

jar {
    into('lib') {
        println "includeInJar: " + configurations.includeInJar.collect { File file -> file }
        from configurations.includeInJar
    }

}

Then running gradle jar and examining the created jar gives me this output, showing that I get the jar file to have groovy as well as all jars that it's dependent on inside the "fat jar":

%  gradle jar                                                                                                                         
includeInJar: [/Users/tnaleid/.gradle/caches/artifacts-8/filestore/org.codehaus.groovy/groovy/1.8.6/jar/553ca93e0407c94c89b058c482a404427ac7fc72/groovy-1.8.6.jar, /Users/tnaleid/.gradle/caches/artifacts-8/filestore/antlr/antlr/2.7.7/jar/83cd2cd674a217ade95a4bb83a8a14f351f48bd0/antlr-2.7.7.jar, /Users/tnaleid/.gradle/caches/artifacts-8/filestore/asm/asm/3.2/jar/9bc1511dec6adf302991ced13303e4140fdf9ab7/asm-3.2.jar, /Users/tnaleid/.gradle/caches/artifacts-8/filestore/asm/asm-tree/3.2/jar/cd792e29c79d170c5d0bdd05adf5807cf6875c90/asm-tree-3.2.jar, /Users/tnaleid/.gradle/caches/artifacts-8/filestore/asm/asm-commons/3.2/jar/e7a19b8c60589499e35f5d2068d09013030b8891/asm-commons-3.2.jar, /Users/tnaleid/.gradle/caches/artifacts-8/filestore/asm/asm-util/3.2/jar/37ebfdad34d5f1f45109981465f311bbfbe82dcf/asm-util-3.2.jar, /Users/tnaleid/.gradle/caches/artifacts-8/filestore/asm/asm-analysis/3.2/jar/c624956db93975b7197699dcd7de6145ca7cf2c8/asm-analysis-3.2.jar]
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar

BUILD SUCCESSFUL

Total time: 3.387 secs

%  jar tvf build/libs/gradletest.jar                                                                                                  
     0 Mon Mar 12 11:40:00 CDT 2012 META-INF/
    25 Mon Mar 12 11:40:00 CDT 2012 META-INF/MANIFEST.MF
     0 Mon Mar 12 11:40:00 CDT 2012 lib/
5546084 Mon Mar 05 13:13:32 CST 2012 lib/groovy-1.8.6.jar
445288 Mon Mar 05 13:13:38 CST 2012 lib/antlr-2.7.7.jar
 43398 Mon Mar 05 13:13:40 CST 2012 lib/asm-3.2.jar
 21878 Mon Mar 05 13:13:40 CST 2012 lib/asm-tree-3.2.jar
 33094 Mon Mar 05 13:13:40 CST 2012 lib/asm-commons-3.2.jar
 36551 Mon Mar 05 13:13:40 CST 2012 lib/asm-util-3.2.jar
 17985 Mon Mar 05 13:13:40 CST 2012 lib/asm-analysis-3.2.jar

Solution 5

Below code could be tried. It depends on the jar task and is of Type Jar

task createJobJar(dependsOn:jar,type:Jar) {
    manifest {
        attributes(
                "Implementation-Title": 'Job '
                ,"Implementation-Version": version
        )
    }
    classifier 'job'
    destinationDir new File("$buildDir")
    into('libs'){
         from configurations.compile
    }
    into('classes'){
        from "$buildDir/classes"
    }
    into('resources'){
        from "$projectDir/src/main/resources"
    }
    into('scripts'){
        from "$projectDir/src/main/scripts"
    }
}

The above code would pack different content inside different directories. Tested on gradle 2.2

Share:
99,608
phil swenson
Author by

phil swenson

Updated on July 05, 2022

Comments

  • phil swenson
    phil swenson almost 2 years

    In gradle - how can I embed jars inside my build output jar in the lib directory (specifially the lib/enttoolkit.jar and lib/mail.jar)?

  • phil swenson
    phil swenson almost 14 years
    I am on 0.9rc1. so tried your first suggestion. Pulled in all sorts of stuff I didn't want.....
  • phil swenson
    phil swenson almost 14 years
    closer I think...problem is I need the jars in a lib directory. This pulls in the classes from the jars. I want lib/mail and lib/enttoolkit in the output jar
  • phil swenson
    phil swenson almost 14 years
    this works... sort of: sourceSets { main { java { srcDir "$wepTrunk/osgi/mycompany.osgi.server/src" } resources { srcDir "/Users/phil/dev/trunk/osgi/mycompany.osgi.server/lib" } } } it puts the jars from my /users/phil/dev/trunk/osgi/mycompany.osgi.server/lib in my output jar, but not in a "lib" directory. Any ideas how to get them in a lib dir?
  • Basil Musa
    Basil Musa almost 13 years
    I know this didn't answer the question, but a wonderful wonderful tip. Thanks lucas.
  • Sebastian Ganslandt
    Sebastian Ganslandt almost 11 years
    Great tip, but completely misses the pretty pretty specific question.
  • TheOperator
    TheOperator about 8 years
    This copies the libraries into the output directory, but not into the JAR file itself -- which was the question.
  • Thunderforge
    Thunderforge almost 8 years
    If you want all the dependencies, you can also copy from configurations.runtime, which gives you the default compile dependencies, saving you the trouble of creating your own extraLibs configuration.
  • naXa stands with Ukraine
    naXa stands with Ukraine over 7 years
    Error: Could not find method jar() for arguments [build_bndovev91pu8trwrdngc8qh7i$_run_closure5@3be2321e] on project ':app' of type org.gradle.api.Project.
  • naXa stands with Ukraine
    naXa stands with Ukraine over 7 years
    The link is not available due to "All Codehaus services have been terminated"
  • radistao
    radistao over 7 years
    pls, update the answer since "from" requires curly braces: see stackoverflow.com/a/4894308/907576
  • omikron
    omikron about 7 years
    Ok, I've done what is described here but I'm still getting Exception in thread "main" java.lang.NoClassDefFoundError: com/rabbitmq/client/ConnectionFactory. Should I setup classpath somehow?
  • Tom
    Tom almost 7 years
    A bit of an explanation about what this code does might help explain some of the specific bits?
  • Steve Pitchers
    Steve Pitchers over 5 years
    @Thunderforge To get all dependencies, I had to copy from configurations.runtimeClasspath rather than configurations.runtime, while avoiding the need for the extraLibs definition.
  • Lokesh Singal
    Lokesh Singal about 4 years
    We just need to add resource after srcDirs processResources{ from(zipTree("src/main/resources/lib/local-jar-name.jar")) }