djangofan
djangofan

Reputation: 29689

Can Gradle jar multiple projects into one jar?

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
}

Upvotes: 9

Views: 17842

Answers (4)

telebin
telebin

Reputation: 11

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.

Upvotes: 1

Paweł Grześ
Paweł Grześ

Reputation: 337

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

Upvotes: 4

lessthanoptimal
lessthanoptimal

Reputation: 2812

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

Upvotes: 8

CaTalyst.X
CaTalyst.X

Reputation: 1665

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
}

Upvotes: 8

Related Questions