Advice on cross-project dependency with non-default configuration?


(Guy Shefner) #1

I have a mostly working solution, but I’m wondering if there’s a better way to solve the following…

My problem is: I have an android project and a peer-level java project named “shared”. I would like the debugCompile configuration of the android project to depend on the testCompile configuration of the shared java project.

The following solution builds and runs okay. Is there a more proper way to accomplish this? One thing that doesn’t work with the below is source code navigation in my IDE (IntelliJ) from the android code that calls into the shared library code. Any suggestions for improvement would be much appreciated!

My shared/build.gradle:

apply plugin: 'java'
dependencies {
    compile 'com.google.guava:guava:19.0'
    testCompile 'junit:junit:4.12'
}
task testJar(type: Jar) {
    from sourceSets.test.output
}
configurations {
    testJarConfiguration
}
artifacts {
    testJarConfiguration testJar
}

And, my android/build.gradle:

apply plugin: 'com.android.application'
//...
dependencies {
    //...
    compile project(':shared')
    // This pulls in transitive testCompile dependencies like junit.
    debugCompile project(path: ':shared', configuration: 'testCompile')
    // This pulls in class files output by testCompile.
    debugCompile project(path: ':shared', configuration: 'testJarConfiguration')
}

(Stefan Oehme) #2

You forgot to add

configurations {
    testJarConfiguration {
     //this makes sure you get the correct dependencies when you depend on the testJar
      extendsFrom testRuntime 
    }
}

Then you can drop this line:

debugCompile project(path: ':shared', configuration: 'testCompile')

This should work fine in the IDE. Are you using IDEA or Android Studio?


(Guy Shefner) #3

Thanks for the suggestion Stefan! Your suggestion does indeed simplify my android/build.gradle dependencies.

Everything builds and runs fine. However, I still can’t get code completion or navigation to work seamlessly in my IDE (Android Studio 2.1.3). For example, when I add a new public method to a class in the shared project, the IDE won’t see it as a valid reference from the android project until I rebuild the shared testJar. If I run ./gradlew :shared:testJar, then the IDE will see it as a valid reference from the android project. This isn’t terrible, but would be nice to figure out. Any further suggestions would be appreciated!

So, including your suggestion and another line I forgot, my new shared/build.gradle is:

apply plugin: 'java'
dependencies {
    compile 'com.google.guava:guava:19.0'
    testCompile 'junit:junit:4.12'
}
task testJar(type: Jar) {
    from sourceSets.main.output  // added this line too
    from sourceSets.test.output
}
configurations {
    testJarConfiguration {
        extendsFrom testRuntime  // added your suggestion
    }
}
artifacts {
    testJarConfiguration testJar
}

And now my android/build.gradle is simplified to:

apply plugin: 'com.android.application'
//...
dependencies {
    //...
    compile project(':shared')
    debugCompile project(path: ':shared', configuration: 'testJarConfiguration')
}

(Stefan Oehme) #4

I’m afraid I’m not familiar enough with Android Studios internals to tell
why this doesn’t work. Seems like the project dependency is not correctly
mapped to an Idea module dependency. You might want to open a bug on the
Android bug tracker.

By the way I don’t think you should package the main sources into the test
jar.


(Guy Shefner) #5

Thanks for your help with the gradle portion! If I figure out the integration issue with Android Studio, I’ll update this thread.