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

2

2

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

Gan answered 10/2, 2016 at 10:32 Comment(3)
Please update the gradle code above to show exactly what it looks like after you've implemented my fix. Will make it easier to see what might be going wrong.Kelson
@KaneO'Riley I have it working now, with some issues with JNI though. I'm going to post an answer right now.Gan
related: #8674934Jelene
G
8

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 !).

Gan answered 11/2, 2016 at 11:46 Comment(0)
S
1

Shlublu's solution didn't work for me, no matter what steps I used.

After much digging, found out that one can define available configurations (at least using experimental gradle), and this in turn avoided having to clean/rebuild in hope of fixing all errors.

Using latest gradle with AS2.1, I was able to solve this issue with a very simple dependency content:

Lib's build.gradle (uses experimental gradle 0.7.0):

model {
  android {
...
    productFlavors {
       create('all') {
         ...
       }
    }
    publishNonDefault true
  }
}
configurations {
  allDebug
  allRelease
}

App's build.gradle (uses standard gradle 2.1.0):

debugCompile project(path: ':lib', configuration: 'allDebug')
releaseCompile project(path: ':lib', configuration: 'allRelease')

I'm pretty sure the productFlavors in the lib's gradle is not needed if using debug/release configurations only, like this:

Lib's build.gradle (uses experimental gradle 0.7.0):

model {
...
}
configurations {
  debug
  release
}

App's build.gradle (uses standard gradle 2.1.0):

debugCompile project(path: ':lib', configuration: 'debug')
releaseCompile project(path: ':lib', configuration: 'release')
Sandoval answered 21/5, 2016 at 22:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.