Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependencies not copied into jar (in Gradle)

TL;DR I expected the dependencies of a module to be built into its .jar, but they don't appear to be.

I'm using Gradle to build a project. I have two subprojects, app (an Android module) and tests (a Java module), as created by IntelliJ.

Since I want to use the classes defined in app in the contents of tests, I've added the appropriate dependency. Inspired by this answer, I've got the following setup:

app/build.gradle:

...
task jarTask(type: Jar) {
    baseName ="${project.archivesBaseName}"
    from android.sourceSets.main.java
}

configurations {
    jarConfiguration
}

artifacts {
    jarConfiguration jarTask
}

tests/build.gradle

...
dependencies {
    ...
    testCompile project(path: ':app', configuration: 'jarConfiguration')
}

However, one of the classes in app imports org.json.JSONObject. Since this is provided by the Android SDK, app can find it fine - but when I try to run tests, I get (in :tests:compileTestJava) "package org.json does not exist". However, if I update tests/build.gradle to be

...
dependencies {
    ...
    testCompile project(path: ':app', configuration: 'jarConfiguration')
    testCompile 'org.json:json:20090211'
}

(See here) then the tests run correctly.

This wasn't what I expected - if a .jar doesn't package up its dependencies, then any project which depends on that .jar must also explicitly depend on the transitive dependencies - wouldn't this cause dependency definitions to rapidly increase?

like image 561
scubbo Avatar asked Oct 31 '22 19:10

scubbo


1 Answers

I came across the concept of a "fatJar" here and here, which seems to be synonymous with a "jar with dependencies" - but changing my app/build.gradle to read

...
task jarTask(type: Jar) {
    baseName ="test-${project.archivesBaseName}"
    from android.sourceSets.main.java
}

task fatJar(type: Jar) {
    baseName = project.name + "-all"
    from {configurations.compile.collect {it.isDirectory() ? it : zipTree(it)}}
    with jarTask
}

configurations {
    jarConfiguration
}

artifacts {
    jarConfiguration fatJar
}

still gives an error that package org.json does not exist. This appears to be because org.json is not explicitly called out as a dependency in the app/build.gradle file. With the following app/build.gradle, my project built and ran tests as expected:

...
dependencies {
    ...
    compile 'org.json:json:20090211'
}

task jarTask(type: Jar) {
    baseName ="${project.archivesBaseName}"
    from android.sourceSets.main.java
}

task fatJar(type: Jar) {
    baseName = project.name + "-all"
    from {configurations.compile.collect {it.isDirectory() ? it : zipTree(it)}}
    with jarTask
}

configurations {
    jarConfiguration
}

artifacts {
    jarConfiguration fatJar
}

(Note that if you just want the fatJar task, you can simply set from files({configurations.compile.collect {it.isDirector() ? it : zipTree(it)}}, android.sourceSets.main.java)

like image 168
scubbo Avatar answered Nov 09 '22 06:11

scubbo