Why does Gradle build my module in Release mode when the app is in Debug
Asked Answered
S

4

47

I'm making a new Android project, with the standard 'app' module, as well as a library project (let's call it 'custom_lib'). In the app's build.gradle file, I link the module as such :

dependencies {
    compile project(':custom_lib')
}

When I trigger the build process (Menu Build > Make Project), I get the following output in the Gradle console

Executing tasks: [clean, :app:compileDebugSources, :custom_lib:compileDebugSources]

Configuration on demand is an incubating feature.
:app:clean
:custom_lib:clean
:app:preBuild
:app:preDebugBuild
:app:checkDebugManifest
:app:preReleaseBuild
:custom_lib:compileLint
:custom_lib:copyReleaseLint UP-TO-DATE
:custom_lib:mergeReleaseProguardFiles UP-TO-DATE
:custom_lib:preBuild
:custom_lib:preReleaseBuild
:custom_lib:checkReleaseManifest
:custom_lib:prepareReleaseDependencies
:custom_lib:compileReleaseAidl
:custom_lib:compileReleaseRenderscript
:custom_lib:generateReleaseBuildConfig
:custom_lib:generateReleaseAssets UP-TO-DATE
:custom_lib:mergeReleaseAssets
:custom_lib:generateReleaseResValues UP-TO-DATE
:custom_lib:generateReleaseResources
:custom_lib:packageReleaseResources
:custom_lib:processReleaseManifest
:custom_lib:processReleaseResources
:custom_lib:generateReleaseSources
:custom_lib:compileReleaseJava
:custom_lib:processReleaseJavaRes UP-TO-DATE
:custom_lib:packageReleaseJar
:custom_lib:compileReleaseNdk
:custom_lib:packageReleaseJniLibs UP-TO-DATE
:custom_lib:packageReleaseLocalJar UP-TO-DATE
:custom_lib:packageReleaseRenderscript UP-TO-DATE
:custom_lib:bundleRelease
:app:prepareComAndroidSupportAppcompatV72102Library
:app:prepareComAndroidSupportSupportV42102Library
:app:prepareTestDoubleBuildCustom_libUnspecifiedLibrary
:app:prepareDebugDependencies
:app:compileDebugAidl
:app:compileDebugRenderscript
:app:generateDebugBuildConfig
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources
:app:mergeDebugResources
:app:processDebugManifest
:app:processDebugResources
:app:generateDebugSources
:app:compileDebugJava
:app:compileDebugNdk
:app:compileDebugSources
:custom_lib:preDebugBuild
:custom_lib:checkDebugManifest
:custom_lib:prepareDebugDependencies
:custom_lib:compileDebugAidl
:custom_lib:compileDebugRenderscript
:custom_lib:generateDebugBuildConfig
:custom_lib:generateDebugAssets UP-TO-DATE
:custom_lib:mergeDebugAssets
:custom_lib:generateDebugResValues UP-TO-DATE
:custom_lib:generateDebugResources
:custom_lib:packageDebugResources
:custom_lib:processDebugManifest
:custom_lib:processDebugResources
:custom_lib:generateDebugSources
:custom_lib:compileDebugJava
:custom_lib:compileDebugNdk
:custom_lib:compileDebugSources

BUILD SUCCESSFUL

Total time: 2.184 secs

What puzzles me is that the build mechanism triggers a Debug build (as the first line says), but almost immediately, Gradle uses the task :app:preReleaseBuild which make my custom_lib module to be built with the Release configuration.

And then, after the app is fully built, Gradle compiles my module with the Debug configuration.

So my questions are :

  • Why is it doing this double build which seems incoherent ?
  • How can I make sure that the library is built with debug configuration when I launch a Debug build process ?

EDIT :

app/build.gradle :

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.1"

    defaultConfig {
        applicationId "com.deezer.testdoublebuild"
        minSdkVersion 8
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    buildTypes {
        debug{
            debuggable true
        }
        release {
            debuggable false
            minifyEnabled false
        }
    }
}

dependencies {
    compile project(':custom_lib')
}

custom_lib/build.gradle :

apply plugin: 'com.android.library'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.1"

    defaultConfig {
        applicationId "com.deezer.mylibrary"
        minSdkVersion 8
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
}

Note : I'm using Android Studio 1.0 RC 1 / Gradle 2.2, and reproduced this issue by creating a new project from scratch, add an empty Android Library module, and "voila"

Sterling answered 3/12, 2014 at 17:0 Comment(6)
Can you provide your entire build.gradle?Obfuscate
@PaulLammertsma Gradle outpus this with any build.gradle AFAIK. I guess it's just a step it goes through and get out of it immediately after...Site
It's not just a step that does nothing as it compiles my library code : I'll add the full gradle outputSterling
Gradle does a lot of "pre/check/prepare/...Release" tasks in my projects too, but my final code is definitely in DEBUG mode.Site
@Sterling You should not have a build type for your android library. Especially, you will not run Proguard on your library before using it in your app. Android libs default to release.Gault
@JaredBurrows the library is destined to be published at some point, and some part of it are gonna be obfuscated with proguard, but as I develop it I need it to be in Debug locally.Sterling
M
22

In the "Build Variants" panel window on the left, you should see both of your modules, and next to them the current "active" variants. For instance

app          debug
custom_lib   debug

When calling Build > Make Project we are building every modules in the project in their current variant.

However, due to a current Gradle limitation (https://code.google.com/p/android/issues/detail?id=52962), building app in debug will require building the release variant of custom_lib, and so you end up building both.

I would recommend to not use Make Project but instead use the option below that says Make Module app. This option will change from app to lib based on the current selection in the Project panel or based on the current editor, and will always do only what's needed to build the current module.

(Looking into this, we noticed that there isn't a shortcut for it, so we're adding one).

Mancunian answered 3/12, 2014 at 17:50 Comment(4)
Very interesting, thanks for the insight! I, too, was wondering why libraries appeared to be built twice. Would this mean that if issue 52962 is resolved, builds with module dependencies will be faster?Obfuscate
It won't be faster because you could get in the opposite issue, where you have the custom_lib's active variant be release, which would make Make Project still build both.Mancunian
The right way to build faster is to only build the module you want (rather than the whole project), and let it build its dependencies.Mancunian
@XavierDucrohet unfortunately from Android Studio there's no convenient way to 'only build module you want', you need to 1. select module; 2. navigate ti Build -> Make module_name every time.Rattray
S
65

Put this in your app dependencies:

dependencies {
    debugCompile project(path: ':custom_lib', configuration: "debug")
    releaseCompile project(path: ':custom_lib', configuration: "release")
}

and in your library's build.gradle add:

android {

    defaultConfig {
        defaultPublishConfig 'release'
        publishNonDefault true
    }

}

Then the library will be built in the same mode as the app. Contrary to previous revisions of this answer, I've confirmed a flavor is not required on the library (this may be due to Gradle or Android plugin versions - I'm using Gradle 2.14 and Android plugin 2.1.0 and did not require it).

Edit: You may have trouble if you don't clean/rebuild after modifying the gradle files, as outlined in this answer here.

Shrewish answered 9/5, 2015 at 1:16 Comment(13)
This is the only clean solution in this page.Annecorinne
Looks really intersting. Exactly what I need actually. However, 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 ? (I'm running Android Studio 2.0 beta 2.)Campanulaceous
@Campanulaceous I haven't needed to do this for some time, but if you post your gradle files for the app + library I can see if there's anything obvious wrongCathey
@KaneO'Riley Thanks a lot Kane. Here it is: #35313243Campanulaceous
So, it works. I just needed to do a "clean" as explained here: #35313243. And I also checked, the productFlavour {} statement is actually needed. Thanks !Campanulaceous
Glad you got it working, I updated the answer to include your findingsCathey
Great :) I did the same in my own aswer. This is really cool to have this working, it helps a lot!Campanulaceous
https://mcmap.net/q/263414/-different-dependencies-for-debug-and-release-in-gradle-and-android-studio provides an alternate solution without the mysterious library product flavor.Sisely
That looks like the same answer without the flavor. I wasn't sure it was needed but someone confirmed that it was. I might have to revisit this and update my answer if it turns out to be unnecessary now (which is what it looks like according to the answer you linked).Cathey
I've recently implemented this again and can confirm the flavor is no longer required. I have a feeling that a newer Gradle or Android plugin version has relaxed that requirement.Cathey
Great answer. Deserves the green checkmark. Thanks for sharingKyrstin
how this work with if you have multiple product flavoursFlied
adding publishNonDefault true in gradle-4.10.2 gives the following warning publishNonDefault is deprecated and has no effect anymore. All variants are now published. and looking at the source code it seems to be useless, however, the warning message seems to be wrong as I still use the debug variant can't public void setPublishNonDefault(boolean publishNonDefault) { logger.warn("publishNonDefault is deprecated and has no effect anymore. All variants are now published."); }Breadwinner
M
22

In the "Build Variants" panel window on the left, you should see both of your modules, and next to them the current "active" variants. For instance

app          debug
custom_lib   debug

When calling Build > Make Project we are building every modules in the project in their current variant.

However, due to a current Gradle limitation (https://code.google.com/p/android/issues/detail?id=52962), building app in debug will require building the release variant of custom_lib, and so you end up building both.

I would recommend to not use Make Project but instead use the option below that says Make Module app. This option will change from app to lib based on the current selection in the Project panel or based on the current editor, and will always do only what's needed to build the current module.

(Looking into this, we noticed that there isn't a shortcut for it, so we're adding one).

Mancunian answered 3/12, 2014 at 17:50 Comment(4)
Very interesting, thanks for the insight! I, too, was wondering why libraries appeared to be built twice. Would this mean that if issue 52962 is resolved, builds with module dependencies will be faster?Obfuscate
It won't be faster because you could get in the opposite issue, where you have the custom_lib's active variant be release, which would make Make Project still build both.Mancunian
The right way to build faster is to only build the module you want (rather than the whole project), and let it build its dependencies.Mancunian
@XavierDucrohet unfortunately from Android Studio there's no convenient way to 'only build module you want', you need to 1. select module; 2. navigate ti Build -> Make module_name every time.Rattray
H
3

Gradle now supports Flavor-buildType-Compile directive, so KaneORiley's answer can now be enhanced as follows:

library's build.gradle:

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

app's build.gradle:

configurations {
    devDebugCompile
    devReleaseCompile
    storeDebugCompile
    storeReleaseCompile
}

android {
    .....
}

dependencies {
    (...)
    devDebugCompile    project(path: ':path:to:lib', configuration: 'devDebug')
    devReleaseCompile  project(path: ':path:to:lib', configuration: 'devRelease')
    storeDebugCompile  project(path: ':path:to:lib', configuration: 'storeDebug')
    storeReleaseCompile project(path: ':path:to:lib', configuration: 'storeRelease') 
}
Haimes answered 3/3, 2016 at 0:34 Comment(0)
O
2

This is closely related to this question.

It appears that Gradle builds all referenced modules of a project in release mode. Since custom_lib is only a library, its configuration is overridden by the module that references it. I wouldn't be too concerned about the library being built with the "release" label.

You'll note that in your gradle output, your project is correctly being compiled with the debug configuration.

Obfuscate answered 3/12, 2014 at 17:23 Comment(4)
I did as you suggested, but I still get the same output. Besides, if you look at the last part of my gradle console output, you'd see that it manages to find the debug tasks in the custom_lib, even though the debug type is not explicitely declaredSterling
The debug and release build types are built-in; you don't have to explicitly specify them to get them.Adust
Good point, Scott. I believe the Gradle build is always executed as "release" for referenced libraries. It's the app module itself that takes on the relevant configuration.Obfuscate
Yes, by default it uses the release version of libraries, though I think you can change that via the build scripts (or perhaps you can only map flavor-flavor relationships between modules; I forget). It doesn't answer the question about why it builds both build types, which I'm not sure about.Adust

© 2022 - 2024 — McMap. All rights reserved.