[Uber] Add fat_aar rule for bundling Android libraries into a distrib…#521
Open
oliviernotteghem wants to merge 3 commits into
Open
[Uber] Add fat_aar rule for bundling Android libraries into a distrib…#521oliviernotteghem wants to merge 3 commits into
oliviernotteghem wants to merge 3 commits into
Conversation
…utable SDK Introduces a new fat_aar rule that consolidates multiple android_library targets and their transitive dependencies into a single self-contained AAR file, complete with a companion fat_aar_pom rule for Maven POM generation. Motivation At Uber, shipping SDK artifacts to external partners (e.g., logistics, delivery, mapping capabilities distributed to third-party apps) requires packaging internal Android modules as a single distributable unit. Building those SDKs directly from the Bazel monorepo avoids the maintenance cost of maintaining a separate SDK project: the SDK AAR is produced as a build output of the same android_library graph that ships inside Uber's own apps, keeping the SDK and the app in lock-step with no extra integration layer. Dependency graph traversal via aspect A fat_aar_aspect walks the full transitive dependency graph and collects Android providers — resources (AndroidResourcesInfo / StarlarkAndroidResourcesInfo), assets (AndroidAssetsInfo), native libraries (AndroidNativeLibsInfo), manifests, and ProGuard specs (ProguardSpecInfo) — as (label, provider) tuples. Tracking labels alongside providers is what enables the filtering step that separates Uber's internal modules from external Maven dependencies. Selective bundling via exclude patterns The exclude attribute accepts label prefix patterns (e.g., "@maven//", "@@com_github_jetbrains_kotlin"). Any dependency whose label or file path matches a pattern is omitted from the bundled AAR. External dependencies excluded this way are tracked in a FatAarDependenciesInfo provider and written to an excluded_deps output group, which fat_aar_pom consumes to generate correct <dependency> entries in the POM. Partners are expected to provide those external dependencies themselves via the generated POM. Classes.jar All transitive runtime JARs from included android_library targets are merged into a single classes.jar using singlejar with --normalize for deterministic output. External Maven JARs are excluded from the merge via the same label-pattern filtering applied to resources. Resources and manifests Transitive resource files, R.txt files, and assets are collected from all included android_library providers, filtered by the exclude patterns, and passed to the AAPT2 resource bundler. Multiple AndroidManifest.xml files are merged using the Android manifest merger tool (APPLICATION merge type, dependency order) with a synthetic primary manifest pinning the minimum SDK version. Native libraries Native .so files from AndroidNativeLibsInfo are extracted from ZIP archives and converted from lib/ARCH/*.so layout (Bazel convention) to jni/ARCH/*.so layout (AAR spec) via add_native_libs.sh before being inserted into the final AAR. ProGuard rules Transitive ProGuard specs are merged and embedded in the AAR's proguard.txt, ensuring consumers applying R8 or ProGuard at the app level receive the correct keep rules for the bundled SDK. Optional R8 optimization An optional r8_config attribute accepts a .pro file. When provided, R8 runs in --classfile mode (outputting .class files rather than .dex, as required for AAR distribution) with --release optimization, using the user-provided config combined with all transitive ProGuard specs. This enables shrinking and obfuscation of the SDK surface before distribution. POM generation fat_aar_pom maps the excluded Bazel labels back to their Maven coordinates (group:artifact:version, with proper type handling for both 3-part and 4-part coordinate formats) and generates a well-formed POM file suitable for publishing the AAR to Maven/Artifactory. Special internal Bazel targets (jarinfer_, proguard_ prefixes) are filtered out during POM generation. In the Uber Android monorepo, these rules are wrapped by the uber_fat_aar macro in android/defs.bzl, which pairs the fat AAR with an aar_import for internal consumption and a publish target for Artifactory delivery.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…utable SDK
Introduces a new fat_aar rule that consolidates multiple android_library targets and their transitive dependencies into a single self-contained AAR file, complete with a companion fat_aar_pom rule for Maven POM generation.
Motivation
At Uber, shipping SDK artifacts to external partners (e.g., logistics,
delivery, mapping capabilities distributed to third-party apps) requires
packaging internal Android modules as a single distributable unit. Building
those SDKs directly from the Bazel monorepo avoids the maintenance cost of
maintaining a separate SDK project: the SDK AAR is produced as a build
output of the same android_library graph that ships inside Uber's own apps,
keeping the SDK and the app in lock-step with no extra integration layer.
Dependency graph traversal via aspect
A fat_aar_aspect walks the full transitive dependency graph and collects
Android providers — resources (AndroidResourcesInfo / StarlarkAndroidResourcesInfo),
assets (AndroidAssetsInfo), native libraries (AndroidNativeLibsInfo),
manifests, and ProGuard specs (ProguardSpecInfo) — as (label, provider)
tuples. Tracking labels alongside providers is what enables the filtering
step that separates Uber's internal modules from external Maven dependencies.
Selective bundling via exclude patterns
The exclude attribute accepts label prefix patterns (e.g., "@maven//",
"@@com_github_jetbrains_kotlin"). Any dependency whose label or file path
matches a pattern is omitted from the bundled AAR. External dependencies
excluded this way are tracked in a FatAarDependenciesInfo provider and
written to an excluded_deps output group, which fat_aar_pom consumes to
generate correct entries in the POM. Partners are expected to
provide those external dependencies themselves via the generated POM.
Classes.jar
All transitive runtime JARs from included android_library targets are
merged into a single classes.jar using singlejar with --normalize for
deterministic output. External Maven JARs are excluded from the merge
via the same label-pattern filtering applied to resources.
Resources and manifests
Transitive resource files, R.txt files, and assets are collected from
all included android_library providers, filtered by the exclude patterns,
and passed to the AAPT2 resource bundler. Multiple AndroidManifest.xml
files are merged using the Android manifest merger tool (APPLICATION merge
type, dependency order) with a synthetic primary manifest pinning the
minimum SDK version.
Native libraries
Native .so files from AndroidNativeLibsInfo are extracted from ZIP archives
and converted from lib/ARCH/.so layout (Bazel convention) to jni/ARCH/.so
layout (AAR spec) via add_native_libs.sh before being inserted into the
final AAR.
ProGuard rules
Transitive ProGuard specs are merged and embedded in the AAR's
proguard.txt, ensuring consumers applying R8 or ProGuard at the app level
receive the correct keep rules for the bundled SDK.
Optional R8 optimization
An optional r8_config attribute accepts a .pro file. When provided, R8
runs in --classfile mode (outputting .class files rather than .dex,
as required for AAR distribution) with --release optimization, using the
user-provided config combined with all transitive ProGuard specs. This
enables shrinking and obfuscation of the SDK surface before distribution.
POM generation
fat_aar_pom maps the excluded Bazel labels back to their Maven coordinates
(group:artifact:version, with proper type handling for both 3-part and
4-part coordinate formats) and generates a well-formed POM file suitable
for publishing the AAR to Maven/Artifactory. Special internal Bazel targets
(jarinfer_, proguard_ prefixes) are filtered out during POM generation.
In the Uber Android monorepo, these rules are wrapped by the uber_fat_aar macro in android/defs.bzl, which pairs the fat AAR with an aar_import for internal consumption and a publish target for Artifactory delivery.