Alix
Alix

Reputation: 2837

How to add conditional afterEvaluate on buildType in Gradle

I have this code at the end of my build.gradle file:

         project.afterEvaluate {

            // If you add/change build types, you have to add to/change
            // these task names.
            mergeDebugAssets.dependsOn project.tasks.getByName('downloadLicenses')
            mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')

        }

See: Copy generated third party licenses to assets for the full code

This used to work fine (regardless of which buildType was set) but if updating my dependencies to the latest version this triggers an exception (when building with buildType='debug'):

Could not get unknown property 'mergeReleaseAssets' for project ':application'

My thought was that maybe split this block in two and put them under the buildTypes configuration. This doesn't work though, as it tries to evaluate the code anyway and crashes.

Any ideas?

Update 1: Root cause? https://code.google.com/p/android/issues/detail?id=219732

Update 2: A horrible workaround:

try {
    mergeDebugAssets.dependsOn project.tasks.getByName('downloadLicenses')
} catch (Exception e) {
    // Expected when building variant Release
}
try {
    mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')
} catch (Exception e) {
    // Expected when building variant Debug
}

Upvotes: 3

Views: 8547

Answers (2)

Xargs
Xargs

Reputation: 779

The reason that you get an error referencing a release task in afterEvaluate is probably because Android Studio's Instant Run feature uses a special Android Gradle plugin feature to only build the debug application variant. This means that only the debug tasks are created, hence why the release tasks can't be found when you reference them.

There are several ways to deal with this:

  1. Search for the dependent task by name using a string. If the Android build system changes the task name in the future, your additional build rules won't run, but you might not even notice.

  2. To determine if release tasks exist, check for the existence of a task whose name is unlikely to change in the future. Maybe assembleRelease fits this bill.

  3. To determine if release tasks exist, check if the release application variant is built with something like:

    project.afterEvaluate {
        if (!android.applicationVariants.matching { it.buildType.name == 'release' }.isEmpty()) {
            mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')
        }
    }
    

The last option looks kind of gross, but hopefully it will fail-fast if the Android build system task names change in the future.

Upvotes: 8

Ivan Frolov
Ivan Frolov

Reputation: 1048

The reason you get exception in case of debug buildType is because mergeReleaseAssets task is not created. You can do the following instead:

project.tasks.findByName('mergeReleaseAssets')?.dependsOn project.tasks.getByName('downloadLicenses')

or even omit project:

tasks.findByName('mergeReleaseAssets')?.dependsOn tasks.getByName('downloadLicenses')

This uses safe navigation operator on nullable return type, so it's clearer than try/catch workaround.

Upvotes: 5

Related Questions