androidgradleandroid-gradle-pluginbuildconfigandroid-buildconfig

buildConfigField not working after updating gradle to 7.0.3


I updated gradle 4.0.1 to 7.0.3 because I need the support of new gradle.

I let the auto updater run and after it was done, when I run the code I get the following error:

C:\Users\me\Projects\proj\proj\proj\app\build\generated\source\buildConfig\stage\debug\proj\BuildConfig.java:22: error: illegal forward reference
public static final String APPLICATION_LIST_URL = BACKEND_HOST + "/page";

In build.gradle the buildConfigField is declared like this:

defaultConfig {
    applicationId "my.app.id"
    minSdkVersion 21
    versionCode getBuildTimestamp()
    versionName "2.0.0"

    buildConfigField 'String', 'APPLICATION_LIST_URL', 'BACKEND_HOST + "/page"'

}

I tried Invaldiate cache/restart and I do not know what else I can try.

EDIT BACKEND_HOST is also defined:

productFlavors {
    local {
        dimension "type"
        targetSdkVersion 30
        buildConfigField 'String', 'APK_DOWNLOAD_RESOLVE_URL', 'BACKEND_HOST + "DOES_NOT_EXIST"'
        ...
    }

    remote {
        dimension "type"
        targetSdkVersion 30
        applicationIdSuffix ".remote"
        buildConfigField 'String', 'APK_DOWNLOAD_RESOLVE_URL', 'BACKEND_HOST + "/remote/download"'
    }

    def backendRemote= '"https://myUrl"'

    android.applicationVariants.all {
        variant ->
            def appName = "myApp"
            def backendHost = backendRemote
            variant.resValue "string", "app_name", appName
            resValue "string", "app_version", "${appName} ${variant.versionName}"
            variant.buildConfigField "String", "AUTH_HOST", backendHost
            variant.buildConfigField "String", "BACKEND_HOST", backendHost
    }
}

And I was building it with remote flavor


Solution

  • It's unclear how the build tools determine the order of the field declarations in the BuildConfig. What works though is this (note the BuildConfig.BACKEND_HOST instead of just BACKEND_HOST):

    buildConfigField 'String', 'BACKEND_HOST', 'my.backend.host.com'
    buildConfigField 'String', 'APPLICATION_LIST_URL', 'BuildConfig.BACKEND_HOST + "/page"'
    

    Chapter 8.3.3 of https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html explains what forward references are legal and which ones are illegal.

    Here's a minimal code sample showing how the BACKEND_HOST can be defined in each flavor:

        defaultConfig {
            applicationId "com.example.myapplication"
            minSdk 30
            targetSdk 31
            versionCode 1
            versionName "1.0"
    
            buildConfigField 'String', 'APPLICATION_LIST_URL', 'BuildConfig.BACKEND_HOST + "/page"'
        }
    
        flavorDimensions "version"
        productFlavors {
            free {
                dimension "version"
                buildConfigField "String", "BACKEND_HOST", '"www.free.com"'
            }
            paid {
                dimension "version"
                buildConfigField "String", "BACKEND_HOST", '"www.paid.com"'
            }
        }
    

    This works because more specific BuildConfig fields (flavors) are evaluated first before the less specific ones (defaultConfig).

    This code is copied from the OP's question and modified to compile by making the references to BACKEND_HOST static:

        defaultConfig {
            applicationId "my.app.id"
            minSdkVersion 21
            versionCode getBuildTimestamp()
            versionName "2.0.0"
    
            buildConfigField 'String', 'APPLICATION_LIST_URL', 'BuildConfig.BACKEND_HOST + "/page"'
            buildConfigField "String", "BACKEND_HOST", '"www.paid.com"'
        }
    
    
        flavorDimensions "type"
        productFlavors {
            local {
                dimension "type"
                targetSdkVersion 30
                buildConfigField 'String', 'APK_DOWNLOAD_RESOLVE_URL', 'BuildConfig.BACKEND_HOST + "DOES_NOT_EXIST"'
            }
    
            remote {
                dimension "type"
                targetSdkVersion 30
                applicationIdSuffix ".remote"
                buildConfigField 'String', 'APK_DOWNLOAD_RESOLVE_URL', 'BuildConfig.BACKEND_HOST + "/remote/download"'
            }
        }
    
        def backendRemote= '"https://myUrl"'
    
        android.applicationVariants.all {
            variant ->
                def backendHost = backendRemote
                variant.buildConfigField "String", "AUTH_HOST", backendHost
                variant.buildConfigField "String", "BACKEND_HOST", backendHost
        }