Question
In Gradle, given a custom dependency configuration, what's the simplest way to actually use/compile with it in Android? Alternatively, what's the best way to switch between 'local' and 'external' dependencies?
Problem
To make building easier and to make better use of multi-project builds, I've created a top-level "aggregator" project that others may or may not use. So any modifications to subprojects must be self-contained in the aggregator.
In the build process for this aggregator, I want to always use local versions of the subprojects (i.e. the source code I'm editing), rather than the compiled artifacts in our repository. Additionally, this aggregator will be used in our continuous integration environment, such that the unit tests of all subprojects are run on each code commit.
Details : partial solution
Given a flat folder structure similar to the following, where all projects/modules are decoupled such that children don't know anything about parents.
+ Parent Aggregator Project
|---- build.gradle
|---- settings.gradle
| + app
| |---- build.gradle
| + models
| |---- build.gradle
| + networking
| |---- build.gradle
| + utils
| |---- build.gradle
I've created the following build.gradle file in the top-most project:
allprojects {
configurations {
localProjects {
extendsFrom compile
}
}
}
project(':app') {
dependencies {
localProjects project(':models')
localProjects project(':networking')
}
}
project(':networking') {
dependencies {
localProjects project(':utils')
}
}
The localProjects
configurations are working properly and each has successfully replaced the existing dependencies (like 'com.mycompany:utils:1.0.0' and 'com.mycompany:models:1.0.0') with local projects. The only problem is I can't figure out how to get Android to use the 'localProjects' dependency set instead of the 'compile' one.
In pure java examples, I've seen people manually replace the classpath in the sourceSet but this doesn't work easily for the Android plugin.
Summary
How do you point an Android build to a custom dependency configuration such that it builds with those dependencies instead of the compile
, debugCompile
, releaseCompile
ones?
Ultimately, I just want incremental builds to work. For example, if I edit the 'models' source code then:
- The next time I build the app, it recompiles the 'models' project
- It does not recompile the 'networking' or 'utils' code
- These changes show up in the app, immediately, after building once (i.e. no more building in 3 or 4 places just to produce an APK with 'the latest')
- As I make code changes to any of these projects, all I ever have to do is run the build from the aggregator project and the right things compile and the APK that's produced reflects the latest code on my machine
- Similarly, I can run all unit tests just from the aggregator
- Last but not least, I cannot edit the existing projects to accomplish this. All changes must be self-contained in the aggregator because there are other engineers on the project who may not choose to use it.
This is a very common use case and the Gradle team has mentioned adding better support for this kind of thing in the future. In the meantime, how do we solve this?