We’re having some trouble updating our build environment for Android using Gradle 3.5 using the Android Gradle plugin 2.3.0.
Our project structure is pretty straightforward - we have a main application module and several library modules. These library modules can also include other library modules.
One of the requirements is to be able to choose between locally checked out sources and snapshots (generated by continuous integration).
We define our dependencies of all company modules in settings.gradle
of each application:
// Define all locally checked out modules
gradle.ext.localModules = [
"com.company:SomeModule",
"com.company:CommonModule",
] as String[]
// Define all snapshot modules
gradle.ext.snapshotModules = [
"com.company:NonLocalModule"
] as String[]
def subp(... names) {
names.each { fullName ->
def name = fullName.split(":")[1]
include 'Libs:' + name
project(':Libs:' + name).projectDir = new File(settingsDir, '../' + name)
}
}
subp(gradle.localModules)
In this example SomeModule
and CommonModule
should be compiled with the local sources and NonLocalModule
should be compiled with the latest.integration
from our snapshot repository. subp()
creates projects for each local module so they appear in our IDE (Android Studio) and are defined as projects (later we replace all snapshots of local modules with these projects).
In our build.gradle
file we compile our modules as a project or an artifact depending on the configuration, and we add a custom resolutionStrategy to replace all the artifacts of one of the localModules with the project:
dependencies.ext.compileModules = {
gradle.localModules.each {
dependencies.compile dependencies.project(path: ':Libs:' + it.split(':')[1])
}
gradle.snapshotModules.each {
dependencies.compile group + ':' + it.split(':')[1] + ':latest.integration'
}
}
dependencies {
compileModules()
/* Other non-company dependencies */
}
configurations {
all {
resolutionStrategy {
dependencySubstitution {
if (gradle.hasProperty('localModules')) {
gradle.localModules.each {
substitute module(it + ":latest.integration") with project(":Libs:" + it.split(':')[1])
}
}
}
}
}
}
To check whether this all worked, we ran gradlew dependencies
and it seemed to work correctly. For this example this means that:
-
SomeModule
is included as a project and depends onCommmonModule
as a project -
CommonModule
is included as a project -
NonLocalModule
is included as an artifact and depends onCommonModule
as a project
And it looks something like this:
+--- project :Libs:CommonModule
+--- project :Libs:SomeModule
| \--- com.company:CommonModule -> project :Libs:CommonModule
+--- com.company:NonLocalModule:latest.integration -> 1234
\ \--- com.company.CommonModule -> project :Libs:CommonModule
Now the issue is that when we add a method in CommonModule
and try to use it in SomeModule
(or NonLocalModule
) the symbol is not found, so for some reason it is still using the artefact.
What did we do wrong, or is there another better way to do this?