How to .jar all .class output from all sub-projects into one jar?


(Jon Austen) #1

How can I .jar all .class output from all sub-projects into one jar? I want to find a solution that does not require OneJar or fatJar , or any similar 3rd party projects/plugins.

Looking for a pure Groovy script, or Gradle script, solution.

Here is the code that looked hopeful to me but it doesn’t work. I get an error in multiple places in this block are all similar to : “Could not find property ‘build’ on project” . I tried various things and always get a similar error.

subprojects.each { subproject -> evaluationDependsOn(subproject.path)}
  task allJar( type: Jar, dependsOn: subprojects.build ) {
    baseName = 'allJar'
    subprojects.each { subproject ->
        from subproject.configurations.archives.allArtifacts.files.collect {
            zipTree(it)
        }
    }
}
  artifacts {
    archives allJar
}

My project structure is like this:

Root project 'CoreProject'
\--- Project ':core'
     +--- Project ':core:bing'
     \--- Project ':core:google'

In this case I want to build a “root subproject” called “core” that contains classes that the other subprojects share, just like a shared project.

The difference is that “core” is a parent project of all the sub-projects.

So, as a result, I need to build a distibution .jar that contains class files from the “core” project as well as all the classes from sub-projects.

Because I think the answer to this question may rely on this information, here is how I was able to get this project to compile in a hierarchy like this:

project(':core') {
    project.ext.projTitle = 'WebDriver On Gradle'
    project.ext.projVersion = '0.99.0'
}
      project(':core:google') {
    dependencies {
        compile project(':core')
    }
    project.ext.projVersion = '0.99.2'
    project.ext.projTitle = 'WebDriver on Google'
}
  project(':core:bing') {
    dependencies {
        compile project(':core')
    }
    project.ext.projVersion = '0.99.2'
    project.ext.projTitle = 'WebDriver on Bing'
}

Create single JAR for all subproject test classes (Java)
Better out of the box behavior for multiprojects
(Tye Howard) #2

replace

task allJar( type: Jar, dependsOn: subprojects.build ) {

with

task allJar( type: Jar, dependsOn: subprojects.tasks[“build”] ) {


(Jon Austen) #3

Thanks! That mostly resolved the problem except that it doesn’t include the test classes. Do you know how to add the test classes to the allJar archive?

Is there a way with Filetree or CopySpec?

Here is a snippet from my now mostly working build file:

subprojects {
    test {
        testLogging {
            exceptionFormat "full"
            events "started", "passed", "skipped", "failed", "standardOut", "standardError"
        }
    }
    }
subprojects.each { subproject -> evaluationDependsOn( subproject.path ) }
task allJar(type: Jar, dependsOn: subprojects.tasks['classes'] ) {
    baseName = 'allTests'
    subprojects.each { subproject ->
        from subproject.configurations.archives.allArtifacts.files.collect {
            zipTree(it)
        }
    }
}
   artifacts {
    archives allJar
}
project(':core') {
    project.ext.projTitle = 'WebDriver On Gradle'
    project.ext.projVersion = '0.99.0'
}
    project(':core:google') {
    evaluationDependsOn(':core')
    dependencies {
        compile project(':core')
    }
    project.ext.projVersion = '0.99.2'
    project.ext.projTitle = 'WebDriver on Google'
}
  project(':core:bing') {
    evaluationDependsOn(':core')
    dependencies {
        compile project(':core')
    }
    project.ext.projVersion = '0.99.2'
    project.ext.projTitle = 'WebDriver on Bing'
}

(Tye Howard) #4

replace

task allJar(type: Jar, dependsOn: subprojects.tasks['classes'] ) {

with

task allJar(type: Jar, dependsOn: subprojects.tasks['testClasses'] ) {

(The ‘classes’ task doesn’t create the test classes)

and replace

from subproject.configurations.archives.allArtifacts.files.collect {
            zipTree(it)
        }

with

from subproject.configurations.archives.allArtifacts.files.collect {
            zipTree(it)
        }
        from files(subproject.tasks["test"].testClassesDir)

(Add the classess generated from the test task to your jar.)


(Jon Austen) #5

You nailed it! That was exactly the answer.

I will remember you as someone who knows their stuff. Thank you, thank you!

Here is my build.gradle for anyone who is interested: https://gist.github.com/4108725


(Jon Austen) #6

So, this was working for me but now it no longer works, most likely because I re-arranged how I do my subprojects in my Gradle build script. ( see https://github.com/djangofan/WebDriverTestingTemplate )

Now, I have a project layout like this: ’ Eclipse Root

±-- Project ‘:root’ (an ‘includeFlat’ alias to Eclipse project-root-dir)

±-- Project ‘:bing’

±-- Project ‘:commonlib’

±-- Project ‘:google’ ’

If I can figure this out I will post the solution but for now I am totally stuck again.

The exceptions I now get (when I introduce the methods previously discussed in this thread) are really obscure and difficult to debug. It almost seems like some functionality got deprecated or something.

To summarize: I want a .zip file that contains a complete google.jar , bing.jar, (basically a separate .jar of each subproject) but with all the shared 3rd party dependencies in a single contained ‘/lib’ directory.

Then, after unzipping the distribution, I can launch tests from the command line with something like: java -cp lib/* -jar google.jar .


(Sabah Irfan) #7

Hi,

can you please advise me on this: http://forums.gradle.org/gradle/topics/how_to_jar_all_class_output_from_all_sub_projects_into_one_jar


(Sabah Irfan) #8

Can you please advise me on this question please? http://forums.gradle.org/gradle/topics/how_to_jar_all_class_output_from_all_sub_projects_into_one_jar

Thanks Sabah