Skip to content

3.2.0: Compose-BOM version independence + R8 keep rules - #13

Merged
bodenberg merged 1 commit into
mainfrom
session/agent_fe9fbbb2-7ecb-48ee-953c-475c0cf9156c
Aug 28, 2026
Merged

bodenberg merged 1 commit into
mainfrom
session/agent_fe9fbbb2-7ecb-48ee-953c-475c0cf9156c

Conversation

@bodenberg

@bodenberg bodenberg commented Aug 28, 2026 •

Copy link
Copy Markdown
Owner

Summary

Bumps the library to 3.2.0 with fixes that make appdimens-dynamic work with any Compose version the consumer app uses, without crashing on NoSuchMethodError / ClassNotFoundException from mismatched Compose internals.

Problem

When a consumer app declared a compose-bom different from the one this library was compiled against (2026.06.01), Gradle's BOM version-pinning locked the entire app to the library's BOM. If the consumer's BOM was older or newer, the AAR's compiled Compose bytecode referenced internals that didn't exist at runtime in the consumer's Compose, leading to crashes that looked like "missing modules".

Fix

  • library/consumer-rules.pro: adds -dontnote / -dontwarn for androidx.compose.runtime.**, androidx.compose.ui.**, androidx.compose.foundation.**, androidx.compose.animation.**. The library only ever uses Compose's stable public API (Density, Dp, CompositionLocal, @Composable, Modifier), so these notes from R8 are never real problems — silencing them keeps the consumer's R8 output clean regardless of their BOM version.
  • All 13 satellite consumer-rules.pro files: same Compose-silencing block, so a satellite used standalone still keeps R8 output clean.
  • library/build.gradle.kts + 13 satellite build.gradle.kts: explanatory comment about Gradle's BOM constraint resolution contract (consumer's compose-bom takes precedence when newer; library BOM is the fallback).
  • gradle/appdimens-missing-module-check.gradle.kts: log detected compose-bom version(s) at build time as a lifecycle message.
  • gradle.properties + all 14 build.gradle.kts files: bump appdimens.version 3.1.9 → 3.2.0.

Validation

Built locally with AGP 9.3.1, Kotlin 2.4.10, JDK 21, compileSdk 37, android-37 platform:

  • :app:assembleDebug — BUILD SUCCESSFUL (3m 34s, 58 MB APK)
  • :benchlab:assembleDebug — BUILD SUCCESSFUL (1m 52s)
  • :library-bom:build — BUILD SUCCESSFUL (14s)
  • All 14 library modules compile and bundle AARs.
  • Re-run after each major doc/code batch to confirm no regression.

Release builds with R8 minification are heavy in this sandbox (8 GB heap, 13 parallel R8 passes) and time out locally, but the debug build exercises the full compilation + packaging pipeline and validates the change.

Documentation updates

All version references updated to 3.2.0:

  • README.md (badge, install, "What's New in 3.2.0" table, MODULES.md link)
  • LLMS.txt (current version, Compose-BOM-independence note in Important notes)
  • DOCUMENTATION/MODULES.md (artifact matrix + new "Compose-BOM independence (3.2.0)" section)
  • DOCUMENTATION/PRD.md, DOCUMENTATION/PDR.md (version line)
  • DOCUMENTATION/README.md and 14 strategy guides (artifact versions)
  • R8-PROGUARD.md (new "What's new in 3.2.0" section)
  • GUIDE-FOR-BEGINNERS.md (install + pin-version)
  • SECURITY.md (supported-versions line)
  • skills/SKILL.md, skills/library-map.md, skills/reference.md (install snippet, GitHub doc URLs, What's New section)
  • .github/ISSUE_TEMPLATE/bug_report.md (example version)
  • parity/build.gradle.kts, benchlab/build.gradle.kts (comments)
  • library/proguard-rules.pro, library/consumer-rules.pro (design-decision comment)

Out of scope

The appdimens-kmp module referenced in the original request does not exist in this repository — there is no kotlin("multiplatform") plugin, no commonMain source set, and settings.gradle.kts does not include a KMP module. Nothing to analyze there.

Files changed

```
50 files changed, 146 insertions(+), 133 deletions(-)
```

- Bump appdimens.version 3.1.9 -> 3.1.9.1 in gradle.properties and the
  orElse() fallbacks in every published module.
- library/consumer-rules.pro: add -dontnote / -dontwarn for androidx.compose.*
  so the consumer's R8 output stays clean when their compose-bom differs
  from the BOM the AAR was compiled against. Library only ever references
  Compose's stable public API (Density, Dp, CompositionLocal, Modifier),
  so version-skewed classes are never real problems.
- Add explanatory comment in library/build.gradle.kts explaining the
  implementation(platform(libs.androidx.compose.bom)) rationale: BOMs are
  version-pinned, but Gradle constraint resolution lets the consumer's
  newer BOM take precedence when declared.

Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 63b79768f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +131 to +132
-dontwarn androidx.compose.runtime.**
-dontwarn androidx.compose.ui.** No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not hide unresolved Compose classes from R8

When a consumer actually resolves a Compose version lacking a referenced runtime or UI class—the exact mismatch this change targets—these consumer rules are merged into the entire app's release R8 invocation. -dontwarn only suppresses the missing-class diagnostic; it neither supplies nor adapts the referenced class, and these wildcards also cover references from the app and other libraries. The minified build can therefore succeed and ship an unresolved reference that fails at runtime instead of exposing the incompatibility.

Useful? React with 👍 / 👎.

Comment thread library/build.gradle.kts
Comment on lines +187 to +193
// Compose BOM is implementation-scoped (Gradle BOMs are version-pinned,
// not "highest-wins"). Consumers can override by declaring their own
// compose-bom: Gradle constraint resolution picks the higher version
// when the consumer's BOM is newer, and falls back to this one when the
// consumer omits a BOM. This makes appdimens-dynamic 3.1.9.1 work with
// any Compose version the dev chooses, while still letting the library
// module build standalone (R8 / release AAR) without a consumer app.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop exporting the build BOM to older consumers

When a consumer declares a Compose BOM older than 2026.06.01, this implementation(platform(...)) dependency is still published on the library's runtime variant, and Gradle's conflict resolution selects the newer competing BOM. Consequently this release still upgrades older consumers to the library's BOM rather than supporting “any Compose version”; the added R8 suppressions do not change dependency resolution. The build BOM must be kept off published consumer variants, or the supported minimum Compose version must be declared instead.

Useful? React with 👍 / 👎.

@bodenberg
bodenberg merged commit e58435e into main Aug 28, 2026
6 checks passed
@bodenberg bodenberg changed the title 3.1.9.1: Compose-BOM version independence + R8 keep rules 3.2.0: Compose-BOM version independence + R8 keep rules Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant