Include transitive dependencies in jar

I use gradle in Android studio so that my project can build an Android app and a cli executable (in the form of a fat jar file).

I have

  1. an app module, named “app”, which uses ‘the’ plugin
  2. a java module, named “cli”, that builds the jar and uses the java plugin
  3. a java module, “common” that uses the Java plugin and contains Java code used by the other modules.

app → common → GSON
cli → common → GSON

The “common” module depends on other libs such as GSON or even some other local module.

The “app” module builds fine and the resulting Android app works as expected.

The “cli” module uses the following gradle code, which I found in the forum, to create a fat .jar file:

jar {
    from {
        configurations.compileClasspath.filter{ it.exists() }.collect { it.isDirectory() ? it : zipTree(it) }

The generated fat .jar contains the code from “cli” and “common”. However, it does not contain the transitive dependencies declared in “common”, such as GSON.

Is there some way to configure the “cli” module so that it includes all dependencies in the resulting .jar file?

The compileClasspath configuration is going to only include dependencies that are put on the compilation classpath. If your projects have implementation dependencies, it will not include those. While the java-library plugin and api configuration dependencies could help here (if they’re really API dependencies), I think you actually want to be bundling your runtimeClasspath configuration, not the compileClasspath.

1 Like

Thank you so much! Using runtimeClasspath resulted in a .jar that contained everything that was needed.

I use the implementation for adding GSON as a dependency to the “common” module and I use implementation for adding the “common” module as a dependency to the “cli” module. Isn’t implementation the correct keyword for my case?

That’s not something that can be determined from the information about the structure. You need to consider the actual code in common. If common just uses GSON internally, implementation is the right configuration to use for the GSON dependency. However, if the public methods of common return or require as arguments some types provided by GSON, using the api configuration from the java-library plugin is more appropriate.