Skip to content

Instantly share code, notes, and snippets.

@ZakTaccardi
Created August 29, 2022 17:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZakTaccardi/add6e4e390221670a8826bd0ef859612 to your computer and use it in GitHub Desktop.
Save ZakTaccardi/add6e4e390221670a8826bd0ef859612 to your computer and use it in GitHub Desktop.
Migrate to version catalogs now!
plugins {
id("myapp.dependencyCatalogs.plugin")
}
dependencies {
// this will target the Gradle generated `libs` from `dependencies.toml` or the buildSrc `Project.libs`
// extension function depending on the existence of `Project.libs` function (delete that file to switch between
// behaviors
api(libs.kotlin.standardLib)
}
## See https://docs.gradle.org/current/userguide/platforms.html
################################################
[versions]
kotlin = "1.7.10"
kotlinCoroutines = "1.6.4"
[libraries]
### Kotlin
kotlin-standardLib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "kotlin" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-kotlinScriptRuntime = { module = "org.jetbrains.kotlin:kotlin-script-runtime", version.ref = "kotlin" }
### Coroutines
kotlin-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinCoroutines" }
kotlin-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinCoroutines" }
kotlin-coroutines-reactiveStreams = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-reactive", version.ref = "kotlinCoroutines" }
kotlin-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinCoroutines" }
import myapp.dependencyCatalogs.LibsCatalogExtension
import org.gradle.api.Project
import org.gradle.kotlin.dsl.the
// this file is in `buildSrc` in the root package, so `libs` will point to this function or the generated `libs` from the `.toml` file
/**
* Wrapper with no package name to have projects automatically pick up [LibsCatalogExtension] when this function exists.
*
* The generated version accessors is [org.gradle.accessors.dm.LibrariesForLibs].
*
* The generated version accessors and [LibsCatalogExtension] will have the same API surface, so we can safely delete
* this later once VersionCatalogs have full IDE support and no other code will need updating.
*
* see https://issuetracker.google.com/issues/187326581
*/
val Project.libs get(): LibsCatalogExtension = the<LibsCatalogExtension>()
package myapp.dependencyCatalogs
import org.gradle.api.Project
import org.gradle.api.artifacts.MinimalExternalModuleDependency
import org.gradle.api.artifacts.VersionCatalog
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.api.artifacts.VersionConstraint
import org.gradle.api.provider.Provider
import org.gradle.api.provider.ProviderFactory
import org.gradle.kotlin.dsl.the
import javax.inject.Inject
// this file is in `buildSrc`
/**
* Look at the root project `dependencies.toml` file to see where are dependencies are defined.
*
* Note: this is not accessible in `buildSrc/build.gradle.kts`. See `LibsCatalog` in that file for the file used there.
*/
abstract class LibsCatalogExtension @Inject constructor(
private val providers: ProviderFactory,
versionCatalogsExtension: VersionCatalogsExtension
) {
private val libs = versionCatalogsExtension.named("libs")
val versions = Versions()
inner class Versions {
val kotlin = libs.getVersion("kotlin", providers)
val kotlinCoroutines = libs.getVersion("kotlinCoroutines", providers)
}
val kotlin = Kotlin()
inner class Kotlin {
val standardLib = libs.getLibrary("kotlin.standardLib")
val reflect = libs.getLibrary("kotlin.reflect")
val test = libs.getLibrary("kotlin.test")
val gradlePlugin = libs.getLibrary("kotlin.gradlePlugin")
val coroutines = Coroutines()
inner class Coroutines {
val core = libs.getLibrary("kotlin.coroutines.core")
val android = libs.getLibrary("kotlin.coroutines.android")
val reactiveStreams = libs.getLibrary("kotlin.coroutines.reactiveStreams")
val test = libs.getLibrary("kotlin.coroutines.test")
}
}
package myapp.dependencyCatalogs
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.getByType
// this file is in `buildSrc`
plugins {
// none ..
}
// creates the extension once for re-use
extensions.create<LibsCatalogExtension>("myLibsCatalogExtension", providers, extensions.getByType<VersionCatalogsExtension>())
dependencyResolutionManagement {
versionCatalogs {
// creats a `libs` accessor, which matches our `Project.libs` extension function defined in `buildSrc`
// simply delete the `Project.libs` extension function to switch between using this generated version
// catalog
create("libs") {
from(files("dependencies.toml"))
}
}
}
@ZakTaccardi
Copy link
Author

This workaround leverages the type-unsafe VersionCatalogsExtension API to create an identical API surface for your version catalogs.

Have CI delete the Project.libs extension function and your project will switch to using the Gradle generated libs rather than your custom plugin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment