Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gradle buildType/productFlavor using unexpected buildConfigField

Given the below configuration:

productFlavors {
  normal {
    applicationId "com.app"
  }

  mock {
    applicationId "com.app.mock"
  }
}

buildTypes {
  debug {
    productFlavors.normal.buildConfigField "boolean", "mockMode", "false"
    productFlavors.mock.buildConfigField "boolean", "mockMode", "true"
  }

  release {
    productFlavors.normal.buildConfigField "boolean", "mockMode", "false"
    // Release should never point to mocks. Ever.
    productFlavors.mock.buildConfigField "boolean", "mockMode", "false"
  }
}

enter image description here

I would have expected BuildConfig.mockMode = true;, however, this is the resultant build config:

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "*****";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "mock";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
  // Fields from product flavor: mock
  public static final boolean mockMode = false;
}

From a little investigation/debugging, I realised that if I change the value for the product flavour in the release buildType it actually updates the BuildConfig.mockMode value, despite having mockDebug selected as my build variant.

I already have a better solution for achieving what I want to do, so I'm just looking for an answer that helps me understand why Gradle is acting in this way based on the configuration, to help me understand more of what it is doing.

like image 222
Ben Pearson Avatar asked May 14 '15 09:05

Ben Pearson


2 Answers

You could extract the logic to decide on the actual value of the BuildConfig field into a method of its own. That way, the DSL configuration has a single line. It looks something like this (not tested - expect syntax errors):

buildTypes {
    applicationVariants.all { variant ->
        variant.buildConfigField "boolean", "mockMode", mockMode(variant)
    }
}

def mockMode(variant) {
    //Return true or false depending on variant.buildType and variant.productFlavors 
}
like image 89
curioustechizen Avatar answered Nov 07 '22 15:11

curioustechizen


Fairly easy to understand once you run with this configuration:

buildTypes {
    debug {
        println("debug!")
    }
    release {
        println("release!")
    }
}

What you'll see in the build log is:

Information:Gradle tasks [:app:assembleOneDebug]
debug!
release!
:app:preBuild UP-TO-DATE
...

This means that all 4 lines of your code is executed, thus the only effective lines are the last 2:

productFlavors.normal.buildConfigField "boolean", "mockMode", "false"
productFlavors.mock.buildConfigField "boolean", "mockMode", "false"

Which leads to your BuildConfig having:

public static final boolean mockMode = false;
like image 38
Simas Avatar answered Nov 07 '22 16:11

Simas