2

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

Richard
  • 1,087
  • 18
  • 52

1 Answers1

3

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
    }
Emanuel Moecklin
  • 28,488
  • 11
  • 69
  • 85
  • Sorry, I forgot to add it, but it is defined – Richard Oct 14 '21 at 15:18
  • Added it in the question – Richard Oct 14 '21 at 15:25
  • 1
    I could reproduce the issue and found a workaround @Richard – Emanuel Moecklin Oct 14 '21 at 15:32
  • Why my application is built like this is because there are 3 different flavors and backend_host depends on which flavor was being built with. I do not think I can create a static backend host like that. But if you say that you got the same error and static backendhost resolved the issue then I will look into that, thank you. – Richard Oct 14 '21 at 15:39
  • It seems I misunderstood your answer. In my `BuildConfig` i can see that `BACKEND_HOST` is defined and variables that are under it are working and the ones above it are not. Not sure how to get the ones from `defaultConfig` under the `BACKEND_HOST` in gradle file. Because In the `defaultConfig` I have actually around 10 variables that use the `BACKEND_HOST` and 3 of them are going above it in `BuildConfig.java` and the other 7 that are going under it are working but not sure what it is that determines their order there. But you have helped me a lot, thank you. – Richard Oct 14 '21 at 15:47
  • @Richard defining the BACKEN_HOST by flavor is no problem. I added some sample code. I don't see why this shouldn't work with your setup. I'm not sure why you define the BACKEND_HOST in the `applicationVariants.all {` part if it should be flavor specific. – Emanuel Moecklin Oct 14 '21 at 15:53
  • In your BuildConfig is the BACKEND_HOST under APPLICATION_LIST_URL or above – Richard Oct 14 '21 at 15:59
  • @Richard it's in the flavor declaration since you wanted it defined by flavor but even if it's defined in the `defaultConfig` the order of the declarations doesn't matter because the reference to BACKEND_HOST from APPLICATION_LIST_URL is now `BuildConfig.BACKEND_HOST` and thus static meaning Java can forward reference it. – Emanuel Moecklin Oct 14 '21 at 16:05
  • Weird.. in my BuildConfig, if i move BACKEND_HOST above the variables, it works – Richard Oct 14 '21 at 16:05
  • @Richard I modified your original code to compile. It's basically just adding the `BuildConfig` prefix to `BACKEND_HOST` references, that's all. See my updated answer. – Emanuel Moecklin Oct 14 '21 at 16:19
  • Ah forgive me, I failed to notice that... Tank you. – Richard Oct 14 '21 at 16:25