fat-aar-android
fat-aar-android copied to clipboard
Add ability to embed debug versions of aar
Currently plugin only declares "embed" configuration (and variants like debugEmbed), which can only consume "default" configuration of other projects.
To work around this, user have to write this amount of code:
// In project being consumed
configurations {
debugEmbedElements {
attributes {
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.EMBEDDED))
attribute(BuildTypeAttr.ATTRIBUTE, project.objects.named(BuildTypeAttr, "release"))
// /*for flavors*/ attribute(Attribute.of("pricingDimension", ProductFlavorAttr), project.objects.named(ProductFlavorAttr, "paid"))
}
canBeConsumed = true
canBeResolved = false
}
// etc
}
afterEvaluate {
// instead of afterEvaluate android.libraryVariants.all can be used
artifacts {
debugEmbedElements tasks.named("bundleDebugAar")
releaseEmbedElements tasks.named("bundleReleaseAar")
}
}
// And in consuming project
dependencies {
debugEmbed project(path: ":some-feature", configuration: "debugEmbedElements")
releaseEmbed project(path: ":some-feature", configuration: "releaseEmbedElements")
}
This can be done automatically using variant aware matching, that uses attributes. For example "debugEmbedClasspath" will automatically match to project(":someFeature").debugEmbedElements, because each have the same Buldling and BuildTypeAttr attribute values.
So "embed" should only be used for declaring dependencies, "debugEmbedElements" for consuming and "debugEmbedClasspath" for resolving. For example, in simplest case:
- (canBeResolved=false, canBeConsumed=false)
- "embed"
- "debugEmbed" extendsFrom "embed"
- "releaseEmbed" extendsFrom "embed"
- (canBeResolved=false, canBeConsumed=true)
- "debugEmbedElements" extendsFrom "debugEmbed" (with attributes and artifact)
- "releaseEmbedElements" extendsFrom "releaseEmbed" (with attributes and artifact)
- (canBeResolved=true, canBeConsumed=false)
- "debugEmbedClasspath" extendsFrom "debugEmbed" (with attributes)
- "releaseEmbedClasspath" extendsFrom "releaseEmbed" (with attributes)
For variant aware matching to work, there are these things must be done to plugin:
- Add "***EmbedElements" and "***EmbedClasspath" configurations with right attributes
- Resolve artifacts against "***EmbedClasspath", instead of against "embed"
- Somehow add "**EmbedElements" configurations to projects, that are being embedded - either create them directly if they are absent, or add some miniature plugin to these project that just adds "**EmbedElements" configurations.
I've tested this approach with Gradle 5.6.4 and AGP 3.5.3, and don't know if it will work on versions below that
This would also resolve problems with AmbiguousConfigurationSelectionException which happens to me when I try to embed an kotlin multipatform project, it contains so many configurations and the embed configuration must choose between them.
@aasitnikov EmbedElements configuration is not needed, because EmbedClasspath should have attributes that match the artifiacts in the existing android variants configurations of the consumed projects (releaseRuntimeElements, debugRuntimeElements). or am I wrong?
EmbedElements could be discarded, if AGP would expose configurations with aar artifacts for every variant. And it looks like starting from AGP 3.6.0 they added a lot of configurations with aar artifacts (runtimePublication and apiPublication to name a few), and components for every variant through which these configurations should probably be consumed. But I'm not sure those will be enough to perform attribute matching, because they lack BuildTypeAttr and VariantAttr attributes.
All the new configurations are not accessible, so they cannot be used.
config.setCanBeResolved(false);
config.setVisible(false);
config.setCanBeConsumed(false);