Resolving dependency between modules

android

(Oleksii Chekanin) #1

Hello. I have next project

java/

  • module A
  • module B
  • module C
  • module D

Each module is Android Library by itself.

Module A is like ‘core’ library, containing one class and one interface implemented by module B, C and D which in turn are utility libraries. To build module B I added a dependency on module A for the configuration compile. The same will be done for modules C and D.

It’s supposed to test module A (‘core’) with one of another module, but only with one. I tried to add product flavors for each case, but
it results in the error message:
> Error:Cannot change dependencies of configuration ':moduleB:default’
after it has been included in dependency resolution.

What is my goal: build test APK with next libraries as dependencies:

  • module A library + module B library
  • module A library + module C library
  • module A library + module D library

Thank you in advance.

All build scripts are listed below

root project build.gradle

buildscript {

repositories {
    jcenter()
}
dependencies {
    classpath 'com.android.tools.build:gradle:2.3.3'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

}

ext.libraryNameExtension = ‘.aar’

project(’:moduleA’) {

ext.libraryName = 'moduleA-core.aar'

}

project(’:moduleB’) {

ext.libraryName = 'moduleB-impl.aar'

}

project(’:moduleC) {

ext.libraryName = 'moduleC-impl.aar'

}

// set properties common for all subprojects
subprojects {

// all modules are treated as subprojects and built as Android libraries
apply plugin: 'com.android.library'
def subproject = it
println "subproject name: " + subproject.name
android {
    compileSdkVersion 22
    buildToolsVersion "25.0.0"
    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 22
        archivesBaseName = subproject.ext.libraryName
    }
    buildTypes.all { type ->
        type.minifyEnabled = false
        type.debuggable = !(type.name == "release")
    }
    // default output file name is ${archivesBaseName}-buildVariantName
    // change this behaviour to next:
    // inside buildDir (by default 'build/') directory with library variant name is created
    // and artifact is placed inside this directory
    // all subprojects are libraries, thus libraryVariants used. It doesn't affect non-library modules
    libraryVariants.all { variant ->
        def variantOutputDir = "${project.buildDir}/" + variant.name + '/'
        println "variant: ${variant.name}; output: ${variantOutputDir}"
        mkdir variantOutputDir
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith(rootProject.ext.libraryNameExtension)) {
                output.outputFile = new File(variantOutputDir + subproject.ext.libraryName)
            }
        }
    }
}

}

Module A build.gradle

android {

defaultConfig {
    // TODO investigate difference between debug and release builds
    defaultPublishConfig 'debug'
    publishNonDefault true
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
// Flavors required to build test APK with different libraries
// TODO investigate how to resolve circular dependency
// Source set for 'debug' and 'release' build types is the same
sourceSets.debug.setRoot('main')
sourceSets.release.setRoot('main')
productFlavors {
    moduleBFlavor {
        description "Test APK with 'moduleA' and 'moduleB' libraries"
        
        // possible solution
        //useLibrary('moduleB.aar', true)
        testApplicationId 'com.sec.android.moduleA-test.moduleB-impl'
    }
}

}

dependencies {

// add JNI libraries from jniLibs/ to APK
compile fileTree(include: ['*.so'], dir: 'jniLibs')
// Required for instrumented tests
// must match version from the compileSdkVersion property
androidTestCompile 'com.android.support:appcompat-v7:22.0.0'
androidTestCompile 'com.android.support:support-annotations:22'
androidTestCompile 'com.android.support.test:runner:0.5'
// project 'moduleB' already added this project as a dependency
// must investigate how to build test apk with moduleB.aar library
//    androidTestModuleBFlavorCompile project(':moduleB')
// Required for local unit tests (JUnit 4 framework)
testCompile 'junit:junit:4.12'

}

Module B build.gradle

android {
defaultConfig {
publishNonDefault true
}

// Source set for 'debug' and 'release' build types is the same
sourceSets.debug.setRoot('main')
sourceSets.release.setRoot('main')

}

dependencies {

// !!! required to build module B library, otherwise classes from
// module A sources are not imported during compilation
compile project(path: ':moduleA')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
})
testCompile 'com.android.support:appcompat-v7:22.0.0'
testCompile 'junit:junit:4.12'

}