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

笑着哭i 提交于 2019-11-27 10:39:09

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.

stigkj

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
    }
}

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

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
aloksahoo

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

I needed to the same thing you asked, and used this method. you may not need a custom configuration declaration, but i needed to separate the locally used jar files from those declared in a super-build file.

configurations{
    //declare custom config if necessary, otherwise just use compile
    myLibs
}
dependencies {
    //add lib/*.jar files to myLibs
    myLibs fileTree(dir: 'lib', include: '*.jar')
    compile {
        //set compile configuration to extend from myLibs
        extendsFrom myLibs
    }
}
// task to copy libs to output/lib dir
task copyToLib(type: Copy) {
    into "$buildDir/output/lib"
    from configurations.myLibs
}

jar {
    //include contents of output dir
    from "$buildDir/output"
    manifest {
        //...
    }
}

//set build task to depend on copyToLib
build.dependsOn(copyToLib)

I had the same problem. I solved it like this:

Copy the files into the lib folder with copyToLib and reference the dependency with the Class-Path

ext.mainClass = 'test.main'

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.google.code.gson:gson:2.8.2'
    //....
}

jar {
    from "$buildDir/libs/lib"
    manifest {
        attributes 'Main-Class': 'test.main',
        'Class-Path': configurations.compile.collect { 'lib/'+it.getName() }.join(' ')
    }
}

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

build.dependsOn(copyToLib)

In my case I needed to include a contents of the root project Jar into subproject Jar. So, to make it work, one can use this template:

jar{
  manifest{
    attributes 'Main-Class':'<main class>'
  }
  def conf= configurations.find {it.name.equals('compile') }
  File jar= conf.files.find {it.name.contains('<name or part of the name of produced Jar>')}

  FileTree fileTree=zipTree(jar)
  from fileTree
}

My example:

jar{
   manifest{
       attributes 'Main-Class':'alexiy.jace.Jace'
   }
   description='Make a runnable API Jar'
   def conf= configurations.find {it.name.equals('compile') }
   File tools= conf.files.find {it.name.contains('Tools')}

   FileTree fileTree=zipTree(tools)
   from fileTree
}
Pawan Mishra
task <taskname>(type: Jar) {
    archiveName 'nameofjar.jar'
    doFirst {
    manifest {
            attributes 'Class-Path': configurations.compile.files.collect{ project.uri(it) }.join(' ')
        }
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!