Files
amethyst/.claude/skills/gradle-expert/references/version-catalog-guide.md
T
2025-12-30 15:45:02 +02:00

9.8 KiB

Version Catalog Guide

Overview

AmethystMultiplatform uses Gradle's version catalog (gradle/libs.versions.toml) to centralize dependency management. This ensures version consistency across all modules and simplifies updates.

Structure

sections

[versions]     # Version numbers (referenced by libraries and plugins)
[libraries]    # Library dependencies
[plugins]      # Gradle plugins

Version References

Defining Versions

[versions]
kotlin = "2.3.0"
composeMultiplatform = "1.9.3"
okhttp = "5.3.2"

Special Patterns

Android SDK Versions

android-compileSdk = "36"
android-minSdk = "26"
android-targetSdk = "36"

Access in build.gradle.kts:

compileSdk = libs.versions.android.compileSdk.get().toInt()
minSdk = libs.versions.android.minSdk.get().toInt()

Version Suffixes (Git Commits)

androidKotlinGeohash = "b481c6a64e"  # Jitpack commit hash
markdown = "f92ef49c9d"

Why: For GitHub dependencies via Jitpack that don't have semantic versions

Library Declarations

Basic Pattern

[libraries]
library-name = { group = "...", name = "...", version.ref = "..." }

Examples

Version Reference

okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }

Module Reference (for multi-artifact libs)

androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "androidxCamera" }

Without Group (shorthand)

androidx-ui = { group = "androidx.compose.ui", name = "ui" }

Note: Inherits version from BOM (compose-bom)

BOMs (Bill of Materials)

AndroidX Compose BOM

[versions]
composeBom = "2025.12.01"

[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }

Usage in build.gradle.kts:

val composeBom = platform(libs.androidx.compose.bom)
implementation(composeBom)
implementation(libs.androidx.ui)        // Version from BOM
implementation(libs.androidx.material3) // Version from BOM

Benefits:

  • All AndroidX Compose artifacts use compatible versions
  • Update single BOM version, not individual libraries
  • Prevents version conflicts

Platform-Specific Variants

secp256k1 (KMP crypto library)

secp256k1KmpJniAndroid = "0.22.0"

[libraries]
secp256k1-kmp-common = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp", version.ref = "secp256k1KmpJniAndroid" }
secp256k1-kmp-jni-android = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp-jni-android", version.ref = "secp256k1KmpJniAndroid" }
secp256k1-kmp-jni-jvm = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp-jni-jvm", version.ref = "secp256k1KmpJniAndroid" }

Critical: All three variants MUST share the same version

JNA (for LibSodium)

jna = "5.18.1"

[libraries]
jna = { group = "net.java.dev.jna", name = "jna", version.ref = "jna" }

Usage in build.gradle.kts:

// androidMain - AAR packaging
implementation("net.java.dev.jna:jna:5.18.1@aar")

// jvmMain - JAR packaging
implementation(libs.jna)

Why: Android needs AAR, JVM needs JAR (different artifact types)

Plugin Declarations

Basic Pattern

[plugins]
plugin-id = { id = "...", version.ref = "..." }

Examples

Kotlin Plugins

[versions]
kotlin = "2.3.0"

[plugins]
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
jetbrainsKotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
jetbrainsComposeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
serialization = { id = 'org.jetbrains.kotlin.plugin.serialization', version.ref = 'kotlinxSerializationPlugin' }

Critical: All Kotlin plugins MUST use the same Kotlin version

Android Gradle Plugin

[versions]
agp = "8.13.2"

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
androidLibrary = { id = "com.android.library", version.ref = "agp" }
androidKotlinMultiplatformLibrary = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }

Compose Multiplatform

[versions]
composeMultiplatform = "1.9.3"

[plugins]
composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "composeMultiplatform" }

Plugin Application

// In build.gradle.kts
plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidLibrary)
    alias(libs.plugins.composeMultiplatform)
    alias(libs.plugins.jetbrainsComposeCompiler)
}

Usage in Build Files

Accessing Versions

// Direct version access
val kotlinVersion = libs.versions.kotlin.get()
val minSdk = libs.versions.android.minSdk.get().toInt()

Accessing Libraries

dependencies {
    implementation(libs.kotlinx.coroutines.core)
    api(libs.secp256k1.kmp.common)
    implementation(libs.okhttp)
}

Accessing Plugins

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidLibrary)
}

Version Catalog Benefits

1. Centralized Version Management

Update once, applies everywhere:

# Change one line
kotlin = "2.3.0"   "2.4.0"

# Affects all usages
- kotlinMultiplatform plugin
- jetbrainsKotlinAndroid plugin
- kotlin-stdlib
- All Kotlin-related dependencies

2. Type-Safe Accessors

// Compile-time checked
implementation(libs.okhttp)  // ✅ IDE autocomplete

// vs string-based (error-prone)
implementation("com.squareup.okhttp3:okhttp:5.3.2")  // ❌ No autocomplete

3. Dependency Consistency

// All modules reference same catalog
:quartz   libs.okhttp
:commons  libs.okhttp
:desktopApp  libs.okhttp

// Same version everywhere

4. Gradle Sync Improvements

  • Faster IDE sync (pre-parsed catalog)
  • Better dependency resolution
  • Clearer error messages

Common Patterns

GitHub Dependencies (Jitpack)

[versions]
markdown = "f92ef49c9d"  # Git commit hash

[libraries]
markdown-ui = { group = "com.github.vitorpamplona.compose-richtext", name = "richtext-ui", version.ref = "markdown" }

Repository config (in settings.gradle):

repositories {
    maven { url = "https://jitpack.io" }
}

Multi-Artifact Libraries

[versions]
media3 = "1.9.0"

[libraries]
androidx-media3-exoplayer = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3" }
androidx-media3-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "media3" }
androidx-media3-session = { group = "androidx.media3", name = "media3-session", version.ref = "media3" }

Why: All media3 artifacts share same version for compatibility

Test Dependencies

[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxJunit" }
mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" }
kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinx-coroutines-test"}

Version Update Strategy

Check for Updates

# Using Gradle Versions Plugin (if installed)
./gradlew dependencyUpdates

# Manual check
# Browse to Maven Central for specific library

Update Process

  1. Update version in catalog

    okhttp = "5.3.2"   "5.4.0"
    
  2. Test locally

    ./gradlew clean build
    
  3. Check for breaking changes

    • Review library changelog
    • Run full test suite
  4. Commit with clear message

    chore: update okhttp 5.3.2 → 5.4.0
    

Critical Version Alignments

Kotlin Ecosystem

kotlin = "2.3.0"
kotlinxCoroutinesCore = "1.10.2"
kotlinxSerialization = "1.9.0"

Rule: Kotlin version must be compatible with kotlinx libraries

Compose Ecosystem

composeMultiplatform = "1.9.3"
composeBom = "2025.12.01"
kotlin = "2.3.0"

Rule: Compose Multiplatform → Kotlin version (see compatibility matrix)

AGP & Gradle

agp = "8.13.2"
# Requires Gradle 8.9+

Rule: AGP version dictates minimum Gradle version

Troubleshooting

Issue 1: Unresolved Reference

Error: Unresolved reference: libs

Cause: Gradle version < 7.0 (version catalogs not supported)

Fix: Upgrade Gradle in gradle/wrapper/gradle-wrapper.properties

Issue 2: Library Not Found

Error: Could not find com.example:library:1.0.0

Cause: Repository not configured or typo in catalog

Fix:

  1. Check repository in settings.gradle
  2. Verify group/name/version in libs.versions.toml

Issue 3: Version Conflict

Error: Conflict with dependency ... and ...

Cause: Different versions of same library via transitive dependencies

Fix:

configurations.all {
    resolutionStrategy {
        force(libs.okhttp.get().toString())
    }
}

Best Practices

1. Naming Conventions

# Hyphen-separated, hierarchical
androidx-compose-ui
androidx-compose-material3
kotlinx-coroutines-core

# Platform suffixes
secp256k1-kmp-jni-android
secp256k1-kmp-jni-jvm
# Camera APIs together
androidx-camera-core
androidx-camera-camera2
androidx-camera-view

3. Document Special Cases

# JNA requires @aar for Android (see build.gradle.kts)
jna = { group = "net.java.dev.jna", name = "jna", version.ref = "jna" }

4. Keep BOMs Updated

# Update BOM, individual libs follow
composeBom = "2025.12.01"  # Latest stable

5. Test Version Updates

# Before committing
./gradlew :quartz:test
./gradlew :commons:test
./gradlew :desktopApp:run