My Question
I have defined a custom variant attribute in a Gradle Plugin I am developing which I will use to select the correct variant in the Gradle Module Metadata file .module for my library . I have it defined as an Integer and it is working correctly to match an exact value to section the current variant. However I would like to define a minimum value instead of requiring an exact value.
What I have done
My Gradle Plugin
Define a custom attribute called custom.compileSdkVersion
:
final myAttributeCompileSdkVersion = Attribute.of('custom.compileSdkVersion', Integer)
dependencies.attributesSchema {
attribute(myAttributeCompileSdkVersion)
}
configurations.all {
attributes {
attribute(myAttributeCompileSdkVersion, 31)
}
}
My Libraryâs .module file
Not the full file, just the relevant parts.
{
"formatVersion": "1.1",
"component": {
"group": "com.test.local",
"module": "liba",
"version": "1.1.0"
},
"variants": [
{
"name": "custom.compileSdkVersion_require_min_30",
"attributes": {
"org.gradle.category": "library",
"org.gradle.dependency.bundling": "external",
"org.gradle.libraryelements": "aar",
"org.gradle.usage": "java-runtime",
"custom.compileSdkVersion": 30
}
}
}
App Projectâs build.gradle
dependencies {
implementation 'com.test.local:liba:1.1.0'
}
Results
If I run ./gradlew -q app:dependencyInsight --dependency liba --configuration debugCompileClasspath
I get the following error:
com.test.local:liba:1.1.0 FAILED
Failures:
- Could not resolve com.test.local:liba:1.1.0.
- No matching variant of com.test.local:liba:1.1.0 was found. The consumer was configured to find an API of a component, preferably optimized for Android, as well as attribute 'custom.compileSdkVersion' with value '31', attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'debug' but:
- Variant 'custom.compileSdkVersion_require_min_30' capability com.test.local:liba:1.1.0 declares a runtime of a component:
- Incompatible because this component declares a component, as well as attribute 'custom.compileSdkVersion' with value '30' and the consumer needed a component, as well as attribute 'custom.compileSdkVersion' with value '31'
- Other compatible attributes:
- Doesn't say anything about com.android.build.api.attributes.BuildTypeAttr (required 'debug')
- Doesn't say anything about its target Java environment (preferred optimized for Android)
com.test.local:liba:1.1.0 FAILED
\--- debugCompileClasspath
However if I change myAttributeCompileSdkVersion
to 30
it correctly resolves com.test.local:liba:1.1.0.
, but I want it to also work when myAttributeCompileSdkVersion
is 31 or higher. I wasnât able to find an answer to this anyone in the Gradle doc or anyone else asking about this on the forums here.
Why this important
This is needed to pick the correct library based on the Android compileSdkVersion
selected by the appâs project. See more details here: Google Issue Tracker
Research
How org.gradle.plugin.api-version is defined
I found that this defines the attribute itself a class like this class GradlePluginApiVersion extends Named
and also defines a class GradlePluginVariantsSupport
to add a AttributeMatchingStrategy
.This seems like the way to do it however.
This sentence in the docs makes it sound very limiting and isnât correct since Integer
DOES work (only as exact values though). I didnât know what Named
was, should probably say org.gradle.api.Named
and link to something explaining it as well.
Currently, only attribute types of
String
, or anything extendingNamed
is supported. Attributes must be declared in the attribute schema found on thedependencies
handler:
Conclusion and probably the solution
Anyway the Attribute compatibility rules and Attribute disambiguation rules sections at the bottom explain from a high level what these are and how it can let you define a more flexible compare instead of just an exact value. It was just easy to overlook, and doesnât provide any examples, even pointing to GradlePluginVariantsSupport
would be a very helpful link in these docs!