Skip to content

Build checks Gradle plugin#

This plugin verifies common build problems with environment and project configuration.

Getting started#

Apply the plugin in a root build script or in an Android application module:

plugins {
    id("com.avito.android.build-checks")
}
Setup plugins

In the settings.gradle:

pluginManagement {
    repositories {
        mavenCentral()
    }
    resolutionStrategy {
        eachPlugin {
            String pluginId = requested.id.id
            if (pluginId.startsWith("com.avito.android")) {
                def artifact = pluginId.replace("com.avito.android.", "")
                useModule("com.avito.android:$artifact:$avitoToolsVersion")
            }
        }
    }
}

avitoToolsVersion could be exact version, or property in project's gradle.properties. The latest version could be found on project's release page.

build.gradle.kts

buildChecks {
    androidSdk {
        compileSdkVersion = 29
        revision = 5
    }
    javaVersion {
        version = JavaVersion.VERSION_1_8
    }
}

build.gradle

buildChecks {
    androidSdk {
        compileSdkVersion = 29
        revision = 5
    }
    javaVersion {
        version = JavaVersion.VERSION_1_8
    }
    uniqueRClasses {
        enabled = false
    }
}

That's all for a configuration. Run it manually to verify that it works:

./gradlew checkBuildEnvironment

The plugin will run it automatically on every build.

Configuration#

Enable single check#

build.gradle.kts

buildChecks {
    enableByDefault = false

    androidSdk {
        compileSdkVersion = 29
        revision = 5
    }
}

build.gradle

buildChecks {
    enableByDefault = false

    androidSdk {
        compileSdkVersion = 29
        revision = 5
    }
}

Disable single check#

build.gradle.kts

buildChecks {
    androidSdk {
        enabled = false
    }
}

build.gradle

buildChecks {
    androidSdk {
        enabled = false
    }
}

Disable all checks#

build.gradle.kts

buildChecks {
    enableByDefault = false
}

build.gradle

buildChecks {
    enableByDefault = false
}

Disable plugin#

To completely disable the plugin add a Gradle property:

avito.build-checks.enabled=false

Checks#

Common build checks#

These checks are available in a root project's buildscript.
See also Android application checks.

Java version#

The Java version can influence the output of the Java compiler. It leads to Gradle remote cache misses due to Java version tracking.
This check forces the same major version for all builds.

build.gradle.kts

buildChecks {
    javaVersion {
        version = JavaVersion.VERSION_1_8
    }   
}

build.gradle

buildChecks {
    javaVersion {
        version = JavaVersion.VERSION_1_8
    }   
}

Android SDK version#

Android build tools uses android.jar ($ANDROID_HOME/platforms/android-<compileSdkVersion>/android.jar).
The version can be specified only without a revision (#117789774). Different revisions lead to Gradle remote cache misses. This check forces the same revision:

build.gradle.kts

buildChecks {
    androidSdk {
        compileSdkVersion = 29
        revision = 5
    }
}

build.gradle

buildChecks {
    androidSdk {
        compileSdkVersion = 29
        revision = 5
    }
}

macOS localhost lookup#

On macOs java.net.InetAddress#getLocalHost() invocation can last up to 5 seconds instead of milliseconds (thoeni.io/post/macos-sierra-java). Gradle has a workaround but it works only inside Gradle's code.

To diagnose the problem manually use thoeni/inetTester.

To fix the problem use this workaround:

  1. Find your computer's name - Find your computer's name and network address
  2. Add it to /etc/hosts config:
127.0.0.1        localhost <your_host_name>.local
::1              localhost <your_host_name>.local
  1. Reboot the computer
  2. Check again by thoeni/inetTester

This check automatically detects the issue:

build.gradle.kts

buildChecks {
    macOSLocalhost { }
}

build.gradle

buildChecks {
    macOSLocalhost { }
}

Gradle properties#

Disclaimer

The text below contains Avito specific details

This check detects if you override Gradle project property by command-line. It sends mismatches to statsd. This information helps to see frequently changed propeties that can lead to remote cache misses.

build.gradle.kts

buildChecks {
    gradleProperties { 
        enabled = true // disabled by default
    } 
}

build.gradle

buildChecks {
    gradleProperties { 
        enabled = true // disabled by default
    } 
}

Android application checks#

These checks are available in an Android application's buildscript.
Each application can have specific settings.

Unique R classes#

If two Android libraries use the same package, their R classes will be merged. While merging, it can unexpectedly override resources (#175316324). It happens even with android.namespacedRClass.

To forbid merged R files use this check:

build.gradle.kts

plugins {
    id("com.avito.android.build-checks")
}

buildChecks {
    uniqueRClasses { } // enabled by default
}

build.gradle

plugins {
    id("com.avito.android.build-checks")
}

buildChecks {
    uniqueRClasses { } // enabled by default
}

See also android.uniquePackageNames check. In AGP 4.1 it provides similar but less complete contract.

You can suppress errors for a specific package:

build.gradle.kts

buildChecks {
    uniqueRClasses {
        allowedNonUniquePackageNames.addAll(listOf(
            "androidx.test", // Default from ManifestMerger #151171905
            "androidx.test.espresso", // Won't fix: https://issuetracker.google.com/issues/176002058
            "androidx.navigation.ktx" // Fixed in 2.2.1: https://developer.android.com/jetpack/androidx/releases/navigation#2.2.1
        ))
    }
}

Unique application resources#

From Android library - considerations:

The build tools merge resources from a library module with those of a dependent app module. 
If a given resource ID is defined in both modules, the resource from the app is used.

If conflicts occur between multiple AAR libraries, then the resource from the library listed first in the dependencies list is used.

uniqueAppResources ensures that resources in application are unique and won't be overridden implicitly.

build.gradle.kts

Root module:

plugins {
    id("com.avito.android.impact")
}

Application module:

plugins {
    id("com.avito.android.build-checks")
}

buildChecks {
    uniqueAppResources {} // disabled by default
}

build.gradle

Root module:

plugins {
    id("com.avito.android.impact")
}

Application module:

plugins {
    id("com.avito.android.build-checks")
}

buildChecks {
    uniqueAppResources {} // disabled by default
}

To avoid resource conflicts, consider using a prefix (android.resourcePrefix) or other consistent naming scheme.

Ignoring duplicates#
buildChecks {
    uniqueAppResources {
        // Resource types: string, dimen, bool, layout, drawable, ...
        ignoredResourceTypes.add("string")
        // Specific resources
        ignoredResource("string", "title")
        ignoredResource("dimen", "max_height")
    }
}
Known issues#
  • Requires impact analysis that slows project configuration
  • Disabled by default due to possible false positive cases. Usually, it requires to configure ignored resources.
  • Don't compare values, only resource identifiers. Reported duplicates can have the same content.
  • Detects only project modules without binary dependencies. Don't know how to deal with massive false positive duplicates for widely used libraries (androidx and similar ones).
  • Some resource types are not supported because the issue is not confirmed for them. These are id, attr, styleable.