Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gradle configuration with multi-module android library

Back history

I have this android library aar that devs can use normally with

compile 'com.companyname.sdk:android-sdk:2.x'

and now we're doing a re-write of the library from scratch to create V3.

On this re-organization we managed to break the lib into modules. So one could say that on V3 we would have the following artifacts

compile 'com.companyname.sdk:core:3.x'
compile 'com.companyname.sdk:extra_1:3.x'
compile 'com.companyname.sdk:extra_2:3.x'
compile 'com.companyname.sdk:extra_ ....

and this would give on the gradle structure the following modules:

root:
  |- test_app (apk just for testing, not deployed anywhere)
  |- sdk (aka: core)
  |- extra_1
  |- extra_2
  |- extra_ ... etc

for each extra module on their build.gradle there's a provided (':sdk') so that can use everything from the sdk module, but do not actually compile it inside themselves.

but I would like to also provide a easy migration path for existing host apps. Meaning, I would like on V3 to also have the following artifact that combines core and extra_1 (which it's basically what's currently on V2).

compile 'com.companyname.sdk:android-sdk:3.0.0'

That all sounds great on theory but I'm having a really hard time figuring it out a gradle structure to allow me to easily export all those.

What I want to achieve

So I would like to be able to during a build generate the following artifacts:

  • android-sdk that includes both core and extra_1
  • core
  • extra_1
  • ... all other extras

What have I tried

  • add an extra module named legacy, apply com.android.library without any code and add compile project for both other modules. It generates an empty aar

  • add core/legacy buildTypes with the sourceSets from both modules. Never generated 2 aar

  • add core/legacy productFlavours with sourceSets from both modules. Doesn't compile because it can't find the imports from sdk that are declared into extra_1 (some of which are generated during annotation processor, or lombok)

  • add core/legacy productFlavours with compile project('extra_1'). Doesn't compile because there's a cyclic dependency between sdk and extra_1.

Answer

Based on Gabrielle answer I ended up digging more and found that the option to create an extra module with the dependencies is the right one. It will generate an AAR with empty manifest and empty classes. But the important part is the POM file that it will generate that will include the right dependencies.

A caveat on the approach is on the configuration for the maven-publish plugin. Normally you need a publishing object with publications and a pom.withXml node. mine was like following:

   pom.withXml {
                def root = asNode()
                def license = root.appendNode('licenses').appendNode('license')
                license.appendNode('name', 'The Apache Software License, Version 2.0')
                license.appendNode('url', 'http://www.apache.org/licenses/LICENSE-2.0.txt')
                license.appendNode('distribution', 'repo')
                def dependenciesNode = asNode().appendNode('dependencies')
                configurations.compile.allDependencies.each { dependency ->
                    def dependencyNode = dependenciesNode.appendNode('dependency')
                    dependencyNode.appendNode('groupId', dependency.group)
                    dependencyNode.appendNode('artifactId', dependency.name)
                    dependencyNode.appendNode('version', dependency.version)
                }
            }

The issue with that approach is that dependency.version (at the end) is unspecified, and as such it generates a POM file with <version>unspecified</version>.

The solution there is simple thou, replace the late with some variable u have on the script with the right version number. Mine looked like:

dependencyNode.appendNode('version', "${rootProject.ext.SDK_VERSION}")
like image 738
Budius Avatar asked Jan 20 '17 10:01

Budius


People also ask

Can I have multiple build Gradle?

Java Prime Pack Small projects have a single build file and a source tree. It is very easy to digest and understand a project that has been split into smaller, inter-dependent modules. Gradle perfectly supports this scenario that is multi-project build.

What is subprojects in Gradle?

The subproject producer defines a task named buildInfo that generates a properties file containing build information e.g. the project version. You can then map the task provider to its output file and Gradle will automatically establish a task dependency.


1 Answers

You should do something like this:

root:
  |- test_app (apk just for testing, not deployed anywhere)
  |- core 
  |- extra_1
  |- extra_2
  |- extra_ ... etc
  |- android-sdk

In core/build.gradle:

apply plugin: 'com.android.library'
//...

In extra1/build.gradle:

apply plugin: 'com.android.library'
//...
dependencies {
   compile project(':core')
}

In android-sdk/build.gradle:

apply plugin: 'com.android.library'
//...
dependencies {
   compile project(':core')
   compile project(':extra')
}
like image 129
Gabriele Mariotti Avatar answered Nov 15 '22 00:11

Gabriele Mariotti