Matthew Critelli
Matthew Critelli

Reputation: 41

Android Studio - Set variables by variant?

I'm working in Android Studio 0.8.6

End Goal

Have 3 variants - Noopt, Debug, Release - that set a variable's value based on which variant is being built. For example, if I was building a Noopt build, the string mode should be equal to noopt.

Current Implementation

Here's what I'm trying right now.

buildTypes {
    release {
        debuggable false
        runProguard false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        signingConfig signingConfigs.packageRelease
        mode = "release"
        println("In RELEASE")
    }
    noopt {
        debuggable true
        jniDebugBuild true
        renderscriptDebugBuild false
        runProguard false
        zipAlign true
        mode = "noopt"
        println("In NOOPT")
    }

}

I declare mode outside of android by doing

def mode = ""

However, no matter what variant I build with, mode is always set to noopt. If I add more variants, the variable is always set to whatever the last variant is.

Is my understanding of how gradle works incorrect? I would have assumed that it would only run the code for the variant you're building, but it appears to run it for every variant - or at least any non-standard Android properties/code get run no matter what.

Is there some other way I should be doing this?

Edit:

To add some more context, here's what I want in the end:

task runCustomScript(type:Exec) {
    def mode = ""
    if (currentBuildType == debug)
        mode = "DEBUG=1"
    else if (currentBuildType == noopt)
        mode = "NOOPT=1"

    /* etc etc etc */


    executable "myExec"
    args "-C", "blahblahblah", mode
}

So what I need is a way to find the current variant or build type being run from within a task.

Upvotes: 4

Views: 3025

Answers (1)

CommonsWare
CommonsWare

Reputation: 1007320

Is my understanding of how gradle works incorrect?

Presumably, yes.

I would have assumed that it would only run the code for the variant you're building

No.

but it appears to run it for every variant

Yes, because the code that you are running is building a data structure that represents the task model. Only after build.gradle is interpreted are tasks run. Think of build.gradle as being like an XML file or a JSON file, but one that just happens to be implemented as a domain-specific language (DSL) on top of the Groovy scripting language.

Is there some other way I should be doing this?

Yes, though since it is unclear what mode is for, it is difficult to tell you how. You might consider asking a separate Stack Overflow question explaining what you are really trying to accomplish, so that we can help you determine a solution.

=====

You need to generate N tasks, one for each variant. For example, this snippet of a build.gradle file creates custom jar* tasks for all non-debug build variants:

// from http://stackoverflow.com/a/19484146/115145
android.libraryVariants.all { variant ->
  def name = variant.buildType.name
  if (name.equals(com.android.builder.core.BuilderConstants.DEBUG)) {
    return; // Skip debug builds.
  }
  def task = project.tasks.create "jar${name.capitalize()}", Jar
  task.dependsOn variant.javaCompile
  task.from variant.javaCompile.destinationDir
  task.archiveName = "cwac-${task.archiveName}"
}

I have not created a series of Exec tasks, but I assume it would translate into something like this:

android.libraryVariants.all { variant ->
  def name = variant.buildType.name
  def task = project.tasks.create "runCustomScript${name.capitalize()}", Exec
  // you probably need something here for task.dependsOn variant.javaCompile
  task.executable "myExec"
  // derive mode in here based on variant
  task.args "-C", "blahblahblah", mode
}

That would give you runCustomScriptNoopt, runCustomScriptDebug, and runCustomScriptRelease tasks.

Most likely, you will want to use task.dependsOn to determine what other task must be done first before this task can be run.

Upvotes: 2

Related Questions