How to set variable according to gradle flavors
Asked Answered
S

2

34

I want to pass a variable test that I set differently per flavor as a define to the NDK. But for some reason he always passes the value of the last flavor.

Here is the build.gradle:

apply plugin: 'com.android.library'

def test

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"
    defaultPublishConfig "flavorARelease"
    publishNonDefault true

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 17

        ndk {
            moduleName "test"
            ldLibs "log"
        }
    }

    productFlavors {    
        flavorA {
            test = 1
        }

        flavorB {
            test = 2
        }    
    }

    buildTypes {    
        debug {
            ndk {
                if (cFlags == null) { cFlags = "" }
                cFlags = cFlags + " -DLOGGING=1 -DTEST="+test+" "
            }
            minifyEnabled false
        }
        release {
            ndk {
                if (cFlags == null) { cFlags = "" }
                cFlags = cFlags + " -DLOGGING=0 -DTEST="+test+" "
            }
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
}

And here are the CFLAG lines from the generated Android.mk

build/intermediates/ndk/flavorA/debug/Android.mk:

LOCAL_CFLAGS :=  -DLOGGING=1 -DTEST=2

I expected -DTEST=1 here

build/intermediates/ndk/flavorB/debug/Android.mk:

LOCAL_CFLAGS :=  -DLOGGING=1 -DTEST=2

So where is my mistake? Or how can I achieve my goal? Please also consider that the real problem is more complex and I want to make those defines in the "buildTypes" segment if possible.

Steger answered 16/3, 2016 at 13:26 Comment(0)
S
19

I found the solution:

First instead of def test specify a new field for all productFlavors

productFlavors.all {
    ext.dTest = null
}

Then this field is set in each flavor (code unchanged)

productFlavors {    
    flavorA {
        dTest = 1
    }

    flavorB {
        dTest = 2
    }    
}

And finally you can do this in the buildTypes

buildTypes {    
    all {
         productFlavors {
            all {
                ndk {
                    if (cFlags == null) { cFlags = "" }
                    cFlags = cFlags + " -DTEST="+dTest+" "
                }
            }
        }
    }
    debug {           
        minifyEnabled false
        ndk {
            if (cFlags == null) { cFlags = "" }
            cFlags = cFlags + " -DLOGGING=1 "
        }
    }
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        ndk {
            if (cFlags == null) { cFlags = "" }
            cFlags = cFlags + " -DLOGGING=0 "
        }
    }
}

Here the full file:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"
    defaultPublishConfig "flavorARelease"
    publishNonDefault true

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 17

        ndk {
            moduleName "dTest"
            ldLibs "log"
        }
    }

    productFlavors.all {
        ext.dTest = null
    }

    productFlavors {    
        flavorA {
            dTest = 1
        }

        flavorB {
            dTest = 2
        }    
    }


    buildTypes {    
        all {
            productFlavors {
                all {
                    ndk {
                        if (cFlags == null) { cFlags = "" }
                        cFlags = cFlags + " -DTEST="+dTest+" "
                    }
                }
            }
        }
        debug {           
            minifyEnabled false
            ndk {
                if (cFlags == null) { cFlags = "" }
                cFlags = cFlags + " -DLOGGING=1 "
            }
        }
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            ndk {
                if (cFlags == null) { cFlags = "" }
                cFlags = cFlags + " -DLOGGING=0 "
            }
        }
    }

}
Steger answered 16/3, 2016 at 16:31 Comment(7)
Test extends ConventionTask. Therefore, your productFlavors wouldn't build since you are using a reserved keyword as variable.Angle
Am not sure if you refer to the question or the solution. In my real project it is not test, but a set of different variables. If this example is broken because of using test could you fix it? As I am really rusted with gradle again since I struggled with this problem way back. - Would changing all occurrences of test to dTest do the trick already?Steger
I was referring to the productFlavors, where you were declaring Test. I went ahead and renamed the variable. Thanks!Angle
@Steger What is the variable cFlags here?Caco
i also need to achieve the same thing without ndk and dtest directly in debug and release respectivelyCaco
cFlags is a NDK variable. Basically these are compiler flags for the C compiler. You can ignore the NDK stuff. should also work right in release/debug. the dTest extension variable is not part of the NDK in this example only used there.Steger
how to do this but using the new variable on dependencies?Lilithe
S
26

You can use buildConfigField

productFlavors {
    demo {
        buildConfigField "int", "FOO", "1"
        buildConfigField "String", "FOO_STRING", "\"foo1\""
    }
    full {
        buildConfigField "int", "FOO", "2"
        buildConfigField "String", "FOO_STRING", "\"foo2\""
    }
}
Socher answered 19/9, 2017 at 7:16 Comment(4)
And how would you access this from C in #ifdef? This only works for Java AFAIK.Steger
How do you use this in Java?Waynant
@Waynant Just call like BuildConfig.FOO or BuildConfig.FOO_STRING in Java.Dovetailed
How can you make different buildConfigField per flavor and also per buildType ?Submediant
S
19

I found the solution:

First instead of def test specify a new field for all productFlavors

productFlavors.all {
    ext.dTest = null
}

Then this field is set in each flavor (code unchanged)

productFlavors {    
    flavorA {
        dTest = 1
    }

    flavorB {
        dTest = 2
    }    
}

And finally you can do this in the buildTypes

buildTypes {    
    all {
         productFlavors {
            all {
                ndk {
                    if (cFlags == null) { cFlags = "" }
                    cFlags = cFlags + " -DTEST="+dTest+" "
                }
            }
        }
    }
    debug {           
        minifyEnabled false
        ndk {
            if (cFlags == null) { cFlags = "" }
            cFlags = cFlags + " -DLOGGING=1 "
        }
    }
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        ndk {
            if (cFlags == null) { cFlags = "" }
            cFlags = cFlags + " -DLOGGING=0 "
        }
    }
}

Here the full file:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"
    defaultPublishConfig "flavorARelease"
    publishNonDefault true

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 17

        ndk {
            moduleName "dTest"
            ldLibs "log"
        }
    }

    productFlavors.all {
        ext.dTest = null
    }

    productFlavors {    
        flavorA {
            dTest = 1
        }

        flavorB {
            dTest = 2
        }    
    }


    buildTypes {    
        all {
            productFlavors {
                all {
                    ndk {
                        if (cFlags == null) { cFlags = "" }
                        cFlags = cFlags + " -DTEST="+dTest+" "
                    }
                }
            }
        }
        debug {           
            minifyEnabled false
            ndk {
                if (cFlags == null) { cFlags = "" }
                cFlags = cFlags + " -DLOGGING=1 "
            }
        }
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            ndk {
                if (cFlags == null) { cFlags = "" }
                cFlags = cFlags + " -DLOGGING=0 "
            }
        }
    }

}
Steger answered 16/3, 2016 at 16:31 Comment(7)
Test extends ConventionTask. Therefore, your productFlavors wouldn't build since you are using a reserved keyword as variable.Angle
Am not sure if you refer to the question or the solution. In my real project it is not test, but a set of different variables. If this example is broken because of using test could you fix it? As I am really rusted with gradle again since I struggled with this problem way back. - Would changing all occurrences of test to dTest do the trick already?Steger
I was referring to the productFlavors, where you were declaring Test. I went ahead and renamed the variable. Thanks!Angle
@Steger What is the variable cFlags here?Caco
i also need to achieve the same thing without ndk and dtest directly in debug and release respectivelyCaco
cFlags is a NDK variable. Basically these are compiler flags for the C compiler. You can ignore the NDK stuff. should also work right in release/debug. the dTest extension variable is not part of the NDK in this example only used there.Steger
how to do this but using the new variable on dependencies?Lilithe

© 2022 - 2024 — McMap. All rights reserved.