Android - Gradle - How to force Gradle to build only a specific configuration when two flavors have the same dependency

We are developing an Android library with two flavors called "armv7" and "x86", each of which depends on the platform specific (NDK) libraries, and they are shipped separately.

We also have an Android test app that uses the library project mentioned earlier as a dependency, also built as two different flavors. This app also depends on the Android compatibility library (appcompat).

The problem is that when I try to create just one flavor of the app, it still creates both library flavors (see examples below), which makes the build in Android studio very long (our NDK phase is quite long) and blocks us from splitting scent assemblies at our Jenkins deployment workstations.

To demonstrate this problem, I created a demo project which you can see here: https://bitbucket.org/siltus/gradlebug/src

Basically, you have android skeletons and android library, both have two options: armv7 and x86, and the app also depends on appcompat.

App build.gralde

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.0"

    defaultConfig {
        applicationId "com.test.test1"
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        debug {}
        release {}
    }

    productFlavors {
        armv7 {}
        x86 {}
    }
}

dependencies {
    armv7Compile 'com.android.support:appcompat-v7:20.0.0'    
    armv7Compile project(path: ':lib', configuration: 'armv7Debug')

    x86Compile 'com.android.support:appcompat-v7:20.0.0'
    x86Compile project(path: ':lib', configuration: 'x86Debug')

} 

      

Build.gradle library

apply plugin: 'com.android.library'


android {
    compileSdkVersion 25
    buildToolsVersion "25.0.0"

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 25

        versionCode 1
        versionName "1.0"

        defaultPublishConfig "debug"
        publishNonDefault true
    }

    buildTypes {
        debug {}
        release {}
    }

    productFlavors {
        armv7 {}
        x86 {}
    }

} 

      

When I run this command (note that I ran it as dry, but you can skip the -m flag):

$ ./gradlew -m assembleArmv7Debug

      

This is the output I get (note the tasks for the lib with X86 in their name):

:app:preBuild SKIPPED
:app:preArmv7DebugBuild SKIPPED
:app:checkArmv7DebugManifest SKIPPED
:app:preArmv7ReleaseBuild SKIPPED
:app:preX86DebugBuild SKIPPED
:app:preX86ReleaseBuild SKIPPED
:lib:preBuild SKIPPED
:lib:preArmv7DebugBuild SKIPPED
:lib:checkArmv7DebugManifest SKIPPED
:lib:prepareArmv7DebugDependencies SKIPPED
:lib:compileArmv7DebugAidl SKIPPED
:lib:compileArmv7DebugNdk SKIPPED
:lib:compileLint SKIPPED
:lib:copyArmv7DebugLint SKIPPED
:lib:mergeArmv7DebugShaders SKIPPED
:lib:compileArmv7DebugShaders SKIPPED
:lib:generateArmv7DebugAssets SKIPPED
:lib:mergeArmv7DebugAssets SKIPPED
:lib:mergeArmv7DebugProguardFiles SKIPPED
:lib:packageArmv7DebugRenderscript SKIPPED
:lib:compileArmv7DebugRenderscript SKIPPED
:lib:generateArmv7DebugResValues SKIPPED
:lib:generateArmv7DebugResources SKIPPED
:lib:packageArmv7DebugResources SKIPPED
:lib:processArmv7DebugManifest SKIPPED
:lib:generateArmv7DebugBuildConfig SKIPPED
:lib:processArmv7DebugResources SKIPPED
:lib:generateArmv7DebugSources SKIPPED
:lib:incrementalArmv7DebugJavaCompilationSafeguard SKIPPED
:lib:compileArmv7DebugJavaWithJavac SKIPPED
:lib:processArmv7DebugJavaRes SKIPPED
:lib:transformResourcesWithMergeJavaResForArmv7Debug SKIPPED
:lib:transformClassesAndResourcesWithSyncLibJarsForArmv7Debug SKIPPED
:lib:mergeArmv7DebugJniLibFolders SKIPPED
:lib:transformNative_libsWithMergeJniLibsForArmv7Debug SKIPPED
:lib:transformNative_libsWithSyncJniLibsForArmv7Debug SKIPPED
:lib:bundleArmv7Debug SKIPPED
:lib:preX86DebugBuild SKIPPED
:lib:checkX86DebugManifest SKIPPED
:lib:prepareX86DebugDependencies SKIPPED
:lib:compileX86DebugAidl SKIPPED
:lib:compileX86DebugNdk SKIPPED
:lib:copyX86DebugLint SKIPPED
:lib:mergeX86DebugShaders SKIPPED
:lib:compileX86DebugShaders SKIPPED
:lib:generateX86DebugAssets SKIPPED
:lib:mergeX86DebugAssets SKIPPED
:lib:mergeX86DebugProguardFiles SKIPPED
:lib:packageX86DebugRenderscript SKIPPED
:lib:compileX86DebugRenderscript SKIPPED
:lib:generateX86DebugResValues SKIPPED
:lib:generateX86DebugResources SKIPPED
:lib:packageX86DebugResources SKIPPED
:lib:processX86DebugManifest SKIPPED
:lib:generateX86DebugBuildConfig SKIPPED
:lib:processX86DebugResources SKIPPED
:lib:generateX86DebugSources SKIPPED
:lib:incrementalX86DebugJavaCompilationSafeguard SKIPPED
:lib:compileX86DebugJavaWithJavac SKIPPED
:lib:processX86DebugJavaRes SKIPPED
:lib:transformResourcesWithMergeJavaResForX86Debug SKIPPED
:lib:transformClassesAndResourcesWithSyncLibJarsForX86Debug SKIPPED
:lib:mergeX86DebugJniLibFolders SKIPPED
:lib:transformNative_libsWithMergeJniLibsForX86Debug SKIPPED
:lib:transformNative_libsWithSyncJniLibsForX86Debug SKIPPED
:lib:bundleX86Debug SKIPPED
:app:prepareComAndroidSupportAppcompatV72000Library SKIPPED
:app:prepareComAndroidSupportSupportV42000Library SKIPPED
:app:prepareGradlebugLibUnspecifiedArmv7DebugLibrary SKIPPED
:app:prepareArmv7DebugDependencies SKIPPED
:app:compileArmv7DebugAidl SKIPPED
:app:compileArmv7DebugRenderscript SKIPPED
:app:generateArmv7DebugBuildConfig SKIPPED
:app:generateArmv7DebugResValues SKIPPED
:app:generateArmv7DebugResources SKIPPED
:app:mergeArmv7DebugResources SKIPPED
:app:processArmv7DebugManifest SKIPPED
:app:processArmv7DebugResources SKIPPED
:app:generateArmv7DebugSources SKIPPED
:app:incrementalArmv7DebugJavaCompilationSafeguard SKIPPED
:app:compileArmv7DebugJavaWithJavac SKIPPED
:app:compileArmv7DebugNdk SKIPPED
:app:compileArmv7DebugSources SKIPPED
:app:mergeArmv7DebugShaders SKIPPED
:app:compileArmv7DebugShaders SKIPPED
:app:generateArmv7DebugAssets SKIPPED
:app:mergeArmv7DebugAssets SKIPPED
:app:transformClassesWithDexForArmv7Debug SKIPPED
:app:mergeArmv7DebugJniLibFolders SKIPPED
:app:transformNative_libsWithMergeJniLibsForArmv7Debug SKIPPED
:app:processArmv7DebugJavaRes SKIPPED
:app:transformResourcesWithMergeJavaResForArmv7Debug SKIPPED
:app:validateSigningArmv7Debug SKIPPED
:app:packageArmv7Debug SKIPPED
:app:assembleArmv7Debug SKIPPED
:lib:compileArmv7DebugSources SKIPPED
:lib:assembleArmv7Debug SKIPPED

BUILD SUCCESSFUL

Total time: 1.631 secs

      

To have a clear idea of ​​who is adding the x86 flavor task dependencies, I used the Visteg gradle plugin to generate a DOT file that I passed to PNG with this command:

$ dot -T png build/reports/visteg.dot -o visteg.dot.png

      

And this is what I have:

dependency graph

If you look closely, you can see that the ": lib: bundleX86Debug" task that effectively starts all other X86 build tasks is a dependency of the ": app: prepeareComAndroidSupportAppcompatV72000Library" task.

Not understanding what the relationship is between these two unrelated dependencies (since the library does NOT depend on Appcompat).

Things I tried to change and it didn't matter:

  • Gradle plugin versions android + gradle versions
  • Tool assembly version
  • Settings / compilation settings / Android SDK minimum settings
  • Use other maven library dependencies other than Appompap dependency

The only thing that worked was when I used two different versions for appcompat. For example:

armv7Compile 'com.android.support:appcompat-v7:20.0.0'    
armv7Compile project(path: ':lib', configuration: 'armv7Debug')

x86Compile 'com.android.support:appcompat-v7:21.0.0'
x86Compile project(path: ':lib', configuration: 'x86Debug')

      

When I did this, it was the output of the same gradle command:

:app:preBuild SKIPPED
:app:preArmv7DebugBuild SKIPPED
:app:checkArmv7DebugManifest SKIPPED
:app:preArmv7ReleaseBuild SKIPPED
:lib:preBuild SKIPPED
:lib:preArmv7DebugBuild SKIPPED
:lib:checkArmv7DebugManifest SKIPPED
:lib:prepareArmv7DebugDependencies SKIPPED
:lib:compileArmv7DebugAidl SKIPPED
:lib:compileArmv7DebugNdk SKIPPED
:lib:compileLint SKIPPED
:lib:copyArmv7DebugLint SKIPPED
:lib:mergeArmv7DebugShaders SKIPPED
:lib:compileArmv7DebugShaders SKIPPED
:lib:generateArmv7DebugAssets SKIPPED
:lib:mergeArmv7DebugAssets SKIPPED
:lib:mergeArmv7DebugProguardFiles SKIPPED
:lib:packageArmv7DebugRenderscript SKIPPED
:lib:compileArmv7DebugRenderscript SKIPPED
:lib:generateArmv7DebugResValues SKIPPED
:lib:generateArmv7DebugResources SKIPPED
:lib:packageArmv7DebugResources SKIPPED
:lib:processArmv7DebugManifest SKIPPED
:lib:generateArmv7DebugBuildConfig SKIPPED
:lib:processArmv7DebugResources SKIPPED
:lib:generateArmv7DebugSources SKIPPED
:lib:incrementalArmv7DebugJavaCompilationSafeguard SKIPPED
:lib:compileArmv7DebugJavaWithJavac SKIPPED
:lib:processArmv7DebugJavaRes SKIPPED
:lib:transformResourcesWithMergeJavaResForArmv7Debug SKIPPED
:lib:transformClassesAndResourcesWithSyncLibJarsForArmv7Debug SKIPPED
:lib:mergeArmv7DebugJniLibFolders SKIPPED
:lib:transformNative_libsWithMergeJniLibsForArmv7Debug SKIPPED
:lib:transformNative_libsWithSyncJniLibsForArmv7Debug SKIPPED
:lib:bundleArmv7Debug SKIPPED
:app:prepareComAndroidSupportAppcompatV72000Library SKIPPED
:app:prepareComAndroidSupportSupportV42000Library SKIPPED
:app:prepareGradlebugLibUnspecifiedArmv7DebugLibrary SKIPPED
:app:prepareArmv7DebugDependencies SKIPPED
:app:compileArmv7DebugAidl SKIPPED
:app:compileArmv7DebugRenderscript SKIPPED
:app:generateArmv7DebugBuildConfig SKIPPED
:app:generateArmv7DebugResValues SKIPPED
:app:generateArmv7DebugResources SKIPPED
:app:mergeArmv7DebugResources SKIPPED
:app:processArmv7DebugManifest SKIPPED
:app:processArmv7DebugResources SKIPPED
:app:generateArmv7DebugSources SKIPPED
:app:incrementalArmv7DebugJavaCompilationSafeguard SKIPPED
:app:compileArmv7DebugJavaWithJavac SKIPPED
:app:compileArmv7DebugNdk SKIPPED
:app:compileArmv7DebugSources SKIPPED
:app:mergeArmv7DebugShaders SKIPPED
:app:compileArmv7DebugShaders SKIPPED
:app:generateArmv7DebugAssets SKIPPED
:app:mergeArmv7DebugAssets SKIPPED
:app:transformClassesWithDexForArmv7Debug SKIPPED
:app:mergeArmv7DebugJniLibFolders SKIPPED
:app:transformNative_libsWithMergeJniLibsForArmv7Debug SKIPPED
:app:processArmv7DebugJavaRes SKIPPED
:app:transformResourcesWithMergeJavaResForArmv7Debug SKIPPED
:app:validateSigningArmv7Debug SKIPPED
:app:packageArmv7Debug SKIPPED
:app:assembleArmv7Debug SKIPPED
:lib:compileArmv7DebugSources SKIPPED
:lib:assembleArmv7Debug SKIPPED

BUILD SUCCESSFUL

Total time: 1.199 secs

      

And the dependency graph is much simpler without any X86 build tasks:

enter image description here

So, I suspect gradle prepares tasks for each dependency, but when it sees the same dependency (library AND version) for two separate flavors, it merges tasks so efficiently that it will run both options.

I couldn't find any documentation around this or the pre-existing error ticket, and one step before opening the error bit, I thought maybe someone reading this would have an idea how I can override this behavior or point out what is wrong with my config.

Thank!

+3


source to share





All Articles