Shlublu Shlublu - 1 month ago 8
Android Question

Workaround to link a shared library in debug mode with Android Studio (v2+)

Long ago, a Google Code ticket was opened as the Gradle plugin does not propagate whether you are doing a debug build or a release build to a dependent android library:


DESCRIPTION:

Gradle plugin does not propagate whether you are doing a
debug build or a release build to a dependent android library.

VERSION INFORMATION:

gradle plugin: 0.3 gradle: 1.4


This is a problem, especially when the
release
configuration of the library prevents the edition of the code or the debug process to occur normally (red highlighting of native methods as the IDE does not find any longer while they link normally, broken Java step-by-step debugging...).

This was quite thoroughly discussed on Google Code and here on Stack Overflow, and it happened that Kane O'Riley proposed a really interesting (and clean) workaround:


Put this in your app:

dependencies {
debugCompile project(path: ':custom_lib', configuration: "libraryDebug")
releaseCompile project(path: ':custom_lib', configuration: "libraryRelease")
}



and in your library's build.gradle add:

defaultPublishConfig 'release'
publishNonDefault true
productFlavors {
library {
}
}



I gave a try, but I have the following message at Gradle sync time:

Error:Configuration with name 'libraryDebug' not found.


I tried with just "
debug
" and "
release
" (which are the build config names I use in my lib) but the result is the same.

Any idea to make this interesting workaround working? (I'm running Android Studio 2.0 beta 2)

APPENDIX:


  • my lib's
    build.gradle
    file (including the ugly workaround I'm currently using):


    apply plugin: 'com.android.library'

    android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    // THIS IS WHERE I INSERT THE THREE STATEMENTS PERTAINING
    // TO THE LIB FROM Kane O'Riley'S WORKAROUND ABOVE

    defaultConfig {
    minSdkVersion 16
    targetSdkVersion 21
    }

    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
    }

    buildTypes {
    /*
    release {
    // UNCOMMENT BEFORE MAKING AN ACTUAL RELEASE !!! (duh...)
    ndk {
    moduleName "mylib"
    ldLibs "log"
    cFlags "-fvisibility=hidden -g0 -DSHLUBLU_ACTUAL_RELEASE -O3"
    }

    buildConfigField "boolean", "actualRelease", "true"
    debuggable false
    jniDebuggable false
    minifyEnabled false
    }
    */

    release {
    // COMMENT THIS WHOLE BLOCK BEFORE MAKING AN ACTUAL RELEASE !!!
    // (this is a copy of the "debug" config below... did I say 'duh' ?)
    ndk {
    moduleName "mylib"
    ldLibs "log"
    cFlags "-g"
    }

    buildConfigField "boolean", "actualRelease", "false"
    debuggable true
    jniDebuggable true
    minifyEnabled false
    }

    debug {
    // IF ONLY THIS ONE WAS USED WHEN DEBUGGING!
    // (Only the IDE uses that, but the release build is actually linked,
    // see https://code.google.com/p/android/issues/detail?id=52962 )
    ndk {
    moduleName "mylib"
    ldLibs "log"
    cFlags "-g"
    }

    buildConfigField "boolean", "actualRelease", "false"
    debuggable true
    jniDebuggable true
    minifyEnabled false
    }
    }
    }

    dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    }

  • my project's
    build.gradle
    file:


    apply plugin: 'com.android.application'

    android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
    minSdkVersion 16
    targetSdkVersion 21
    versionCode 27
    versionName "1.4"
    }

    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
    }

    buildTypes {
    release {
    debuggable false
    jniDebuggable false
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-android-shlublu.txt'), 'proguard-rules.pro'
    }

    debug {
    debuggable true
    jniDebuggable true
    minifyEnabled false
    }
    }
    }

    dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(':mylib')
    // THE LINE ABOVE IS WHAT I REPLACE BY Kane O'Riley's WORKAROUND
    // DESCRIBED AT THE BEGINNING OF THIS POST
    }

  • my Gradle config:



My Gradle config

Answer

For this to work, the twobuild.gradle files must not be modified at the same time before syncing once for all. I had to follow the following steps:

  • Step 1: modify the lib's build.gradle, exactly as Kane said:

    // "android" section:
    defaultPublishConfig 'release' 
    publishNonDefault true 
    productFlavors {
        library {
            /* This strange empty flavour is actually needed 
               for the step 3 to be successful               */
        } 
    }
    
  • Step 2: clean/rebuild

  • Step 3: modify the app's build.gradle, also as Kane said:

    dependencies {
        debugCompile project(path: ':custom_lib', configuration: "libraryDebug")
        releaseCompile project(path: ':custom_lib', configuration: "libraryRelease") 
    }
    
  • Step 4: Gradle sync.

So it was just a matter of changing the library first, and then cleaning before modifying the app.

I checked the APK produced by the debug and release build modes, and each of them contains the proper variant of the lib, unlike before applying this workaround, so it does work (thanks Kane !).