9

Can Gradle jar multiple projects into one jar ?

I know you can do it for a single project using a method like this:

task packageTests(type: Jar) {
  from sourceSets.test.classes
}

But how does a person zip up multiple sub-projects into one jar?

I tried this and it doesn't work:

task packageTests(type: Jar) {
  from project(':core').sourceSets.main.classes
  from project(':core:google').sourceSets.test.classes
  from project(':core:bing').sourceSets.test.classes
}
djangofan
  • 28,471
  • 61
  • 196
  • 289
  • You can use [fatJar](https://github.com/musketyr/gradle-fatjar-plugin), OneJar, or [application zip](http://gradle.org/docs/current/userguide/application_plugin.html). – Ben Manes Dec 08 '12 at 23:11
  • All 3 of those are 1 project specific. None of them will zip up a root project and all of its sub-projects. – djangofan Dec 09 '12 at 00:59
  • All of them work based on the model that the project applied to has the others as dependencies. – Ben Manes Dec 09 '12 at 02:32
  • OneJar is clearly a project that zips up a single project and includes all the dependencies in the .jar. It does not solve this particular problem for me. "application zip" wont work because GitHub already does that for me. I tried fatJar but the instructions didnt't work and Gradle can't compile my script. – djangofan Dec 09 '12 at 17:29
  • [Gist](https://gist.github.com/4248735) of the changes needed to apply fatJar to your project. Just run `gradle fatJar`. – Ben Manes Dec 10 '12 at 06:05
  • The only problem with the code is `.classes` is not a member of `main` or `test`. From IDE you can see `output` from the drop down. – Leon Oct 13 '17 at 13:50

4 Answers4

8

This should work for what you want to do. This should be in the root gradle build file.

subprojects.each { subproject -> evaluationDependsOn(subproject.path)}

task allJar(type: Jar, dependsOn: subprojects.assemble) {
   baseName = 'your-base-name'
   subprojects.each { subproject -> 
      from subproject.configurations.archives.allArtifacts.files.collect {
         zipTree(it)
       }
    }
 }

You can publish this by adding it as an archive:

artifacts {
   archives allJar
}
CaTalyst.X
  • 1,645
  • 13
  • 16
  • This answer almost answered my question. It gave me a great number of ideas I tried but I never solved it. The gradle compiler gives me the error: Could not find property 'assemble' on project . I tried to work around it in various ways but couldn't. I'm using Gradle 1.2. I'm still hopeful through and still trying. – djangofan Dec 11 '12 at 03:44
  • You might try reading the documentation on Gradle. It sounds like you are sort of copying and pasting and nothing is working. 'assemble' is a property that the java plugin gives you. If one of your subprojects doesnt have the java plugin, then you will get the error you mentioned. – CaTalyst.X Dec 11 '12 at 04:36
  • I have the java plugin added within the "allprojects" section. Shouldn't that work for all my subprojects? In any case I added the java plugin specifically to the project that was complaining and it didn't help. I'll try to put a simpler example on GitHub tonight to get better help. – djangofan Dec 11 '12 at 16:32
  • Hi I am new to gradle. The gradle compiler gives me the error when I tried this. Could not find method archives() for arguments [task ':allJar'] on root project 'Gradle-Root'. Please help – Captain Buck Jan 21 '16 at 08:00
  • I have a task called `buildRepackage` , I think this is what does the task but I can't make a jar to be runnable with the whole dependency. Do you know how they work together and how I can get this done for a spring boot application? – Dimitri Kopriwa Aug 23 '20 at 15:00
8

Here's my solution, which is a little bit simpler:

// Create a list of subprojects that you wish to include in the jar.  
def mainProjects = [':apps',':core',':gui',':io']
task oneJar( type: Jar , dependsOn: mainProjects.collect{ it+":compileJava"}) {
    baseName = 'name of jar'
    from files(mainProjects.collect{ project(it).sourceSets.main.output })
}

Code has been tested on Gradle 1.12

lessthanoptimal
  • 2,722
  • 2
  • 23
  • 25
  • I have a task called `buildRepackage` , I think this is what does the task but I can't make a jar to be runnable with the whole dependency. Do you know how they work together and how I can get this done for a spring boot application? – Dimitri Kopriwa Aug 23 '20 at 15:01
4

The following solution is quite similar to the proposed by CaTalyst.X but uses jar task directly.

subprojects.each { subproject -> evaluationDependsOn( subproject.path ) }
jar.dependsOn subprojects.tasks['classes']
jar {
  baseName = 'MyApp'
  manifest {
    attributes 'Main-Class': 'org.abc.App'
  }
  subprojects.each { subproject ->
    from subproject.sourceSets.main.output.classesDir
    from subproject.sourceSets.main.output.resourcesDir
  }
}

It was tested against Gradle 2.1 and 2.2.1

Community
  • 1
  • 1
Paweł Grześ
  • 337
  • 2
  • 4
1

I know that this has been answered, but since the answer is old (current Gradle version is few major versions newer - 6.2.2) and this thread shows up in search engines quite high I'll post solution that worked for me.

Generally my problem was similar to/same as the one stated in original post: I wanted to get classes from all subprojects and zip them into one jar (preferably using the most default settings as possible). Finally I've found that the following code does the trick:

jar {
  from subprojects.sourceSets.main.output
}

But while it builds jar properly, I also wanted to be able to publish this jar to Maven repository as single artifact which depends on everything that all subprojects do. To achieve this the main project has to dependent on subprojects dependencies which is done by:

subprojects.each { evaluationDependsOn(it.path) }
dependencies {
  api(externalSubprojectsDependencies('api'))
  implementation(externalSubprojectsDependencies('implementation'))
}
private externalSubprojectsDependencies(String configuration) {
  subprojects.collect { it.configurations[configuration].allDependencies }.flatten()
      .findAll { !it.properties['dependencyProject'] } // this looks like hack, I'd love to see better solution
}

Only external dependencies are copied - we do not want internal (project) dependencies listed in pom.xml as all their classes are in jar anyway.

telebin
  • 11
  • 1
  • 3