Use Gradle's version catalog

This moves our depedencies into a plain file that can be read and
updated by tooling. While the current tooling is not particularly better
than just using gradle-versions-plugin, it should put us on better
footing. gradle-versions-plugin is actually pretty nice, but will be
incompatible with Gradle 8, so we need to wait a bit to see what the
future holds.

Left libraries as an alias for libs to reduce the commit size and make
it easier to revert if we don't end up liking this approach.

We're using Gradle 7.3.3 where it was an incubating fetaure. But in
Gradle 7.4 is became stable.
diff --git a/alts/build.gradle b/alts/build.gradle
index 1d50bf5..9bcff8b 100644
--- a/alts/build.gradle
+++ b/alts/build.gradle
@@ -17,12 +17,12 @@
             project(':grpc-grpclb'),
             project(':grpc-protobuf'),
             project(':grpc-stub'),
-            libraries.protobuf,
+            libraries.protobuf.java,
             libraries.conscrypt,
             libraries.guava,
-            libraries.google_auth_oauth2_http
+            libraries.google.auth.oauth2Http
     def nettyDependency = implementation project(':grpc-netty')
-    compileOnly libraries.javax_annotation
+    compileOnly libraries.javax.annotation
 
     shadow configurations.implementation.getDependencies().minus(nettyDependency)
     shadow project(path: ':grpc-netty-shaded', configuration: 'shadow')
@@ -32,14 +32,14 @@
             project(':grpc-testing-proto'),
             libraries.guava,
             libraries.junit,
-            libraries.mockito,
+            libraries.mockito.core,
             libraries.truth
 
-    testImplementation (libraries.guava_testlib) {
+    testImplementation (libraries.guava.testlib) {
         exclude group: 'junit', module: 'junit'
     }
-    testRuntimeOnly libraries.netty_tcnative
-    testRuntimeOnly (libraries.netty_epoll) {
+    testRuntimeOnly libraries.netty.tcnative
+    testRuntimeOnly (libraries.netty.transport.epoll) {
         artifact {
             classifier = "linux-x86_64"
         }
diff --git a/android-interop-testing/build.gradle b/android-interop-testing/build.gradle
index f399210..03dc6c3 100644
--- a/android-interop-testing/build.gradle
+++ b/android-interop-testing/build.gradle
@@ -56,7 +56,7 @@
 dependencies {
     implementation 'androidx.appcompat:appcompat:1.3.0'
     implementation 'androidx.multidex:multidex:2.0.0'
-    implementation libraries.androidx_annotation
+    implementation libraries.androidx.annotation
     implementation 'com.google.android.gms:play-services-base:18.0.1'
 
     implementation project(':grpc-auth'),
@@ -68,9 +68,9 @@
             libraries.hdrhistogram,
             libraries.junit,
             libraries.truth,
-            libraries.opencensus_contrib_grpc_metrics
+            libraries.opencensus.contrib.grpc.metrics
 
-    implementation (libraries.google_auth_oauth2_http) {
+    implementation (libraries.google.auth.oauth2Http) {
         exclude group: 'org.apache.httpcomponents'
     }
 
@@ -78,7 +78,7 @@
         exclude group: 'com.google.protobuf'
     }
 
-    compileOnly libraries.javax_annotation
+    compileOnly libraries.javax.annotation
 
     androidTestImplementation 'androidx.test.ext:junit:1.1.3',
             'androidx.test:runner:1.4.0'
diff --git a/android/build.gradle b/android/build.gradle
index 7e32ac5..a542d3f 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -33,7 +33,7 @@
     api project(':grpc-core')
     implementation libraries.guava
     testImplementation project('::grpc-okhttp')
-    testImplementation libraries.androidx_test
+    testImplementation libraries.androidx.test.core
     testImplementation libraries.junit
     testImplementation (libraries.robolectric) {
         // Unreleased change: https://github.com/robolectric/robolectric/pull/5432
diff --git a/api/build.gradle b/api/build.gradle
index 9f5e616..03a996f 100644
--- a/api/build.gradle
+++ b/api/build.gradle
@@ -13,13 +13,13 @@
 dependencies {
     api project(':grpc-context'),
             libraries.jsr305,
-            libraries.errorprone
+            libraries.errorprone.annotations
     implementation libraries.guava
 
     testImplementation project(':grpc-context').sourceSets.test.output,
             project(':grpc-testing'),
             project(':grpc-grpclb')
-    testImplementation (libraries.guava_testlib) {
+    testImplementation (libraries.guava.testlib) {
         exclude group: 'junit', module: 'junit'
     }
     jmh project(':grpc-core')
diff --git a/auth/build.gradle b/auth/build.gradle
index 233de35..e9c9d0b 100644
--- a/auth/build.gradle
+++ b/auth/build.gradle
@@ -9,10 +9,10 @@
 description = "gRPC: Auth"
 dependencies {
     api project(':grpc-api'),
-            libraries.google_auth_credentials
+            libraries.google.auth.credentials
     implementation libraries.guava
     testImplementation project(':grpc-testing'),
-            libraries.google_auth_oauth2_http
+            libraries.google.auth.oauth2Http
     signature "org.codehaus.mojo.signature:java17:1.0@signature"
     signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature"
 }
diff --git a/authz/build.gradle b/authz/build.gradle
index 0014dee..2d1432a 100644
--- a/authz/build.gradle
+++ b/authz/build.gradle
@@ -13,12 +13,12 @@
     implementation project(':grpc-protobuf'),
             project(':grpc-core')
 
-    annotationProcessor libraries.autovalue
-    compileOnly libraries.javax_annotation
+    annotationProcessor libraries.auto.value
+    compileOnly libraries.javax.annotation
 
     testImplementation project(':grpc-testing'),
             project(':grpc-testing-proto')
-    testImplementation (libraries.guava_testlib) {
+    testImplementation (libraries.guava.testlib) {
         exclude group: 'junit', module: 'junit'
     }
 
diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle
index a276be8..acc8ae9 100644
--- a/benchmarks/build.gradle
+++ b/benchmarks/build.gradle
@@ -29,18 +29,18 @@
             project(':grpc-testing'),
             project(path: ':grpc-xds', configuration: 'shadow'),
             libraries.hdrhistogram,
-            libraries.netty_tcnative,
-            libraries.math
-    implementation (libraries.netty_epoll) {
+            libraries.netty.tcnative,
+            libraries.commons.math3
+    implementation (libraries.netty.transport.epoll) {
         artifact {
             classifier = "linux-x86_64"
         }
     }
-    compileOnly libraries.javax_annotation
-    alpnagent libraries.jetty_alpn_agent
+    compileOnly libraries.javax.annotation
+    alpnagent libraries.jetty.alpn.agent
 
     testImplementation libraries.junit,
-            libraries.mockito
+            libraries.mockito.core
 }
 
 import net.ltgt.gradle.errorprone.CheckSeverity
diff --git a/binder/build.gradle b/binder/build.gradle
index dc3da4c..e4eaa66 100644
--- a/binder/build.gradle
+++ b/binder/build.gradle
@@ -47,38 +47,38 @@
 dependencies {
     api project(':grpc-core')
 
-    implementation libraries.androidx_annotation
-    implementation libraries.androidx_core
-    implementation libraries.androidx_lifecycle_common
+    implementation libraries.androidx.annotation
+    implementation libraries.androidx.core
+    implementation libraries.androidx.lifecycle.common
     implementation libraries.guava
-    testImplementation libraries.androidx_core
-    testImplementation libraries.androidx_test
-    testImplementation libraries.androidx_lifecycle_common
-    testImplementation libraries.androidx_lifecycle_service
+    testImplementation libraries.androidx.core
+    testImplementation libraries.androidx.test.core
+    testImplementation libraries.androidx.lifecycle.common
+    testImplementation libraries.androidx.lifecycle.service
     testImplementation libraries.junit
-    testImplementation libraries.mockito
+    testImplementation libraries.mockito.core
     testImplementation (libraries.robolectric) {
         // Unreleased change: https://github.com/robolectric/robolectric/pull/5432
         exclude group: 'com.google.auto.service', module: 'auto-service'
     }
-    testImplementation (libraries.guava_testlib) {
+    testImplementation (libraries.guava.testlib) {
         exclude group: 'junit', module: 'junit'
     }
     testImplementation libraries.truth
 
-    androidTestAnnotationProcessor libraries.autovalue
+    androidTestAnnotationProcessor libraries.auto.value
     androidTestImplementation project(':grpc-testing')
     androidTestImplementation project(':grpc-protobuf-lite')
-    androidTestImplementation libraries.autovalue_annotation
+    androidTestImplementation libraries.auto.value.annotations
     androidTestImplementation libraries.junit
-    androidTestImplementation libraries.androidx_core
-    androidTestImplementation libraries.androidx_test
-    androidTestImplementation libraries.androidx_test_rules
-    androidTestImplementation libraries.androidx_test_ext_junit
+    androidTestImplementation libraries.androidx.core
+    androidTestImplementation libraries.androidx.test.core
+    androidTestImplementation libraries.androidx.test.rules
+    androidTestImplementation libraries.androidx.test.ext.junit
     androidTestImplementation libraries.truth
-    androidTestImplementation libraries.mockito_android
-    androidTestImplementation libraries.androidx_lifecycle_service
-    androidTestImplementation (libraries.guava_testlib) {
+    androidTestImplementation libraries.mockito.android
+    androidTestImplementation libraries.androidx.lifecycle.service
+    androidTestImplementation (libraries.guava.testlib) {
         exclude group: 'junit', module: 'junit'
     }
 }
diff --git a/build.gradle b/build.gradle
index 2b99576..b06f006 100644
--- a/build.gradle
+++ b/build.gradle
@@ -55,14 +55,6 @@
         protocPluginBaseName = 'protoc-gen-grpc-java'
         javaPluginPath = "$rootDir/compiler/build/exe/java_plugin/$protocPluginBaseName$exeSuffix"
 
-        nettyVersion = '4.1.72.Final'
-        guavaVersion = '31.1-android'
-        googleauthVersion = '1.4.0'
-        protobufVersion = '3.19.2'
-        protocVersion = protobufVersion
-        opencensusVersion = '0.31.0'
-        autovalueVersion = '1.9'
-
         configureProtoCompilation = {
             String generatedSourcePath = "${projectDir}/src/generated"
             project.protobuf {
@@ -70,7 +62,7 @@
                     if (project.hasProperty('protoc')) {
                         path = project.protoc
                     } else {
-                        artifact = "com.google.protobuf:protoc:${protocVersion}"
+                        artifact = libs.protobuf.protoc.get()
                     }
                 }
                 generateProtoTasks {
@@ -146,70 +138,7 @@
             }
         }
 
-        libraries = [
-            android_annotations: "com.google.android:annotations:4.1.1.4",
-            animalsniffer_annotations: "org.codehaus.mojo:animal-sniffer-annotations:1.19",
-            autovalue: "com.google.auto.value:auto-value:${autovalueVersion}",
-            autovalue_annotation: "com.google.auto.value:auto-value-annotations:${autovalueVersion}",
-            errorprone: "com.google.errorprone:error_prone_annotations:2.11.0",
-            cronet_api: 'org.chromium.net:cronet-api:92.4515.131',
-            cronet_embedded: 'org.chromium.net:cronet-embedded:92.4515.131',
-            gson: "com.google.code.gson:gson:2.9.0",
-            guava: "com.google.guava:guava:${guavaVersion}",
-            javax_annotation: 'org.apache.tomcat:annotations-api:6.0.53',
-            jsr305: 'com.google.code.findbugs:jsr305:3.0.2',
-            google_api_protos: 'com.google.api.grpc:proto-google-common-protos:2.0.1',
-            google_auth_credentials: "com.google.auth:google-auth-library-credentials:${googleauthVersion}",
-            google_auth_oauth2_http: "com.google.auth:google-auth-library-oauth2-http:${googleauthVersion}",
-            okhttp: 'com.squareup.okhttp:okhttp:2.7.4',
-            okio: 'com.squareup.okio:okio:1.17.5',
-            opencensus_api: "io.opencensus:opencensus-api:${opencensusVersion}",
-            opencensus_contrib_grpc_metrics: "io.opencensus:opencensus-contrib-grpc-metrics:${opencensusVersion}",
-            opencensus_impl: "io.opencensus:opencensus-impl:${opencensusVersion}",
-            opencensus_impl_lite: "io.opencensus:opencensus-impl-lite:${opencensusVersion}",
-            opencensus_proto: "io.opencensus:opencensus-proto:0.2.0",
-            instrumentation_api: 'com.google.instrumentation:instrumentation-api:0.4.3',
-            perfmark: 'io.perfmark:perfmark-api:0.25.0',
-            protobuf: "com.google.protobuf:protobuf-java:${protobufVersion}",
-            protobuf_lite: "com.google.protobuf:protobuf-javalite:${protobufVersion}",
-            protobuf_util: "com.google.protobuf:protobuf-java-util:${protobufVersion}",
-
-            netty: "io.netty:netty-codec-http2:[${nettyVersion}]",
-            netty_epoll: "io.netty:netty-transport-native-epoll:${nettyVersion}",
-            netty_unix_common: "io.netty:netty-transport-native-unix-common:${nettyVersion}",
-            netty_proxy_handler: "io.netty:netty-handler-proxy:${nettyVersion}",
-
-            // Keep the following references of tcnative version in sync whenever it's updated
-            // SECURITY.md (multiple occurrences)
-            // examples/example-tls/build.gradle
-            // examples/example-tls/pom.xml
-            netty_tcnative: 'io.netty:netty-tcnative-boringssl-static:2.0.46.Final',
-
-            conscrypt: 'org.conscrypt:conscrypt-openjdk-uber:2.5.1',
-            re2j: 'com.google.re2j:re2j:1.5',
-
-            // Test dependencies.
-            junit: 'junit:junit:4.12',
-            mockito: 'org.mockito:mockito-core:3.3.3',
-            mockito_android: 'org.mockito:mockito-android:3.8.0',
-            truth: 'com.google.truth:truth:1.0.1',
-            guava_testlib: "com.google.guava:guava-testlib:${guavaVersion}",
-            androidx_annotation: "androidx.annotation:annotation:1.1.0",
-            androidx_core: "androidx.core:core:1.3.0",
-            androidx_lifecycle_common: "androidx.lifecycle:lifecycle-common:2.3.0",
-            androidx_lifecycle_service: "androidx.lifecycle:lifecycle-service:2.3.0",
-            androidx_test: "androidx.test:core:1.3.0",
-            androidx_test_rules: "androidx.test:rules:1.3.0",
-            androidx_test_ext_junit: "androidx.test.ext:junit:1.1.2",
-            robolectric: "org.robolectric:robolectric:4.4",
-
-            // Benchmark dependencies
-            hdrhistogram: 'org.hdrhistogram:HdrHistogram:2.1.12',
-            math: 'org.apache.commons:commons-math3:3.6.1',
-
-            // Jetty ALPN dependencies
-            jetty_alpn_agent: 'org.mortbay.jetty.alpn:jetty-alpn-agent:2.0.10'
-        ]
+        libraries = libs
 
         appendToProperty = { Property<String> property, String value, String separator ->
             if (property.present) {
@@ -231,7 +160,7 @@
 
     checkstyle {
         configDirectory = file("$rootDir/buildscripts")
-        toolVersion = "6.17"
+        toolVersion = libs.versions.checkstyle.get()
         ignoreFailures = false
         if (rootProject.hasProperty("checkstyle.ignoreFailures")) {
             ignoreFailures = rootProject.properties["checkstyle.ignoreFailures"].toBoolean()
@@ -240,8 +169,8 @@
 
     if (!project.hasProperty('errorProne') || errorProne.toBoolean()) {
         dependencies {
-            errorprone 'com.google.errorprone:error_prone_core:2.10.0'
-            errorproneJavac 'com.google.errorprone:javac:9+181-r4173-1'
+            errorprone libs.errorprone.core
+            errorproneJavac libs.errorprone.javac
         }
     } else {
         // Disable Error Prone
@@ -256,7 +185,7 @@
 
         dependencies {
             testImplementation libraries.junit,
-                    libraries.mockito,
+                    libraries.mockito.core,
                     libraries.truth
         }
 
@@ -301,7 +230,7 @@
 
         if (!project.hasProperty('errorProne') || errorProne.toBoolean()) {
             dependencies {
-                annotationProcessor 'com.google.guava:guava-beta-checker:1.0'
+                annotationProcessor libs.guava.betaChecker
             }
         }
 
@@ -325,8 +254,7 @@
         plugins.withId("ru.vyarus.animalsniffer") {
 	    // Only available after java plugin has loaded
             animalsniffer {
-                // Breaks on upgrade: https://github.com/mojohaus/animal-sniffer/issues/131
-                toolVersion = '1.18'
+                toolVersion = libs.versions.animalsniffer.get()
             }
         }
     }
diff --git a/census/build.gradle b/census/build.gradle
index 35973a5..45c14a7 100644
--- a/census/build.gradle
+++ b/census/build.gradle
@@ -10,14 +10,14 @@
 dependencies {
     api project(':grpc-api')
     implementation libraries.guava,
-            libraries.opencensus_api,
-            libraries.opencensus_contrib_grpc_metrics
+            libraries.opencensus.api,
+            libraries.opencensus.contrib.grpc.metrics
 
     testImplementation project(':grpc-api').sourceSets.test.output,
             project(':grpc-context').sourceSets.test.output,
             project(':grpc-core').sourceSets.test.output,
             project(':grpc-testing'),
-            libraries.opencensus_impl
+            libraries.opencensus.impl
 }
 
 javadoc {
diff --git a/compiler/build.gradle b/compiler/build.gradle
index 0b57665..1ff8aed 100644
--- a/compiler/build.gradle
+++ b/compiler/build.gradle
@@ -134,10 +134,10 @@
 dependencies {
     testImplementation project(':grpc-protobuf'),
             project(':grpc-stub'),
-            libraries.javax_annotation
+            libraries.javax.annotation
     testLiteImplementation project(':grpc-protobuf-lite'),
             project(':grpc-stub'),
-            libraries.javax_annotation
+            libraries.javax.annotation
 }
 
 sourceSets {
@@ -163,7 +163,7 @@
         if (project.hasProperty('protoc')) {
             path = project.protoc
         } else {
-            artifact = "com.google.protobuf:protoc:${protocVersion}"
+            artifact = libs.protobuf.protoc.get()
         }
     }
     plugins {
@@ -186,7 +186,7 @@
     }
 }
 
-println "*** Building codegen requires Protobuf version ${protocVersion}"
+println "*** Building codegen requires Protobuf version ${libs.versions.protobuf.get()}"
 println "*** Please refer to https://github.com/grpc/grpc-java/blob/master/COMPILING.md#how-to-build-code-generation-plugin"
 
 task buildArtifacts(type: Copy) {
diff --git a/core/build.gradle b/core/build.gradle
index bc8231f..53bbad9 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -25,16 +25,16 @@
 dependencies {
     api project(':grpc-api')
     implementation libraries.gson,
-            libraries.android_annotations,
-            libraries.animalsniffer_annotations,
-            libraries.errorprone,
+            libraries.android.annotations,
+            libraries.animalsniffer.annotations,
+            libraries.errorprone.annotations,
             libraries.guava,
-            libraries.perfmark
+            libraries.perfmark.api
     testImplementation project(':grpc-context').sourceSets.test.output,
             project(':grpc-api').sourceSets.test.output,
             project(':grpc-testing'),
             project(':grpc-grpclb')
-    testImplementation (libraries.guava_testlib) {
+    testImplementation (libraries.guava.testlib) {
         exclude group: 'junit', module: 'junit'
     }
 
diff --git a/cronet/build.gradle b/cronet/build.gradle
index d66eaf3..61551cb 100644
--- a/cronet/build.gradle
+++ b/cronet/build.gradle
@@ -38,14 +38,14 @@
 
 dependencies {
     api project(':grpc-core'),
-            libraries.cronet_api
+            libraries.cronet.api
     implementation libraries.guava
     testImplementation project(':grpc-testing')
 
-    testImplementation libraries.cronet_embedded
+    testImplementation libraries.cronet.embedded
 
     testImplementation libraries.junit
-    testImplementation libraries.mockito
+    testImplementation libraries.mockito.core
     testImplementation (libraries.robolectric) {
         // Unreleased change: https://github.com/robolectric/robolectric/pull/5432
         exclude group: 'com.google.auto.service', module: 'auto-service'
diff --git a/gae-interop-testing/gae-jdk8/build.gradle b/gae-interop-testing/gae-jdk8/build.gradle
index 325e465..0512452 100644
--- a/gae-interop-testing/gae-jdk8/build.gradle
+++ b/gae-interop-testing/gae-jdk8/build.gradle
@@ -51,8 +51,8 @@
         exclude group: 'io.grpc', module: 'grpc-xds'
     }
     implementation libraries.junit
-    implementation libraries.protobuf
-    runtimeOnly libraries.netty_tcnative
+    implementation libraries.protobuf.java
+    runtimeOnly libraries.netty.tcnative
 }
 
 compileJava {
diff --git a/gcp-observability/build.gradle b/gcp-observability/build.gradle
index a3dc550..264a4a6 100644
--- a/gcp-observability/build.gradle
+++ b/gcp-observability/build.gradle
@@ -23,17 +23,17 @@
     def cloudLoggingVersion = '3.6.1'
     def opencensusExporterVersion = '0.31.0'
 
-    annotationProcessor libraries.autovalue
+    annotationProcessor libraries.auto.value
     api project(':grpc-api')
     
     implementation project(':grpc-protobuf'),
             project(':grpc-stub'),
             project(':grpc-alts'),
             project(':grpc-census'),
-            libraries.google_auth_oauth2_http,
-            libraries.autovalue_annotation,
-            libraries.perfmark,
-            libraries.opencensus_contrib_grpc_metrics,
+            libraries.google.auth.oauth2Http,
+            libraries.auto.value.annotations,
+            libraries.perfmark.api,
+            libraries.opencensus.contrib.grpc.metrics,
             libraries.gson,
             ('com.google.guava:guava:31.1-jre'),
             ('com.google.auth:google-auth-library-credentials:1.4.0'),
@@ -46,12 +46,12 @@
             ("io.opencensus:opencensus-exporter-stats-stackdriver:${opencensusExporterVersion}"),
             ("io.opencensus:opencensus-exporter-trace-stackdriver:${opencensusExporterVersion}")
 
-    runtimeOnly libraries.opencensus_impl
+    runtimeOnly libraries.opencensus.impl
 
     testImplementation project(':grpc-testing'),
             project(':grpc-testing-proto'),
             project(':grpc-netty-shaded')
-    testImplementation (libraries.guava_testlib) {
+    testImplementation (libraries.guava.testlib) {
         exclude group: 'junit', module: 'junit'
     }
 
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 0000000..5879764
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,69 @@
+[versions]
+# Breaks on upgrade: https://github.com/mojohaus/animal-sniffer/issues/131
+animalsniffer = "1.18"
+autovalue = "1.9"
+checkstyle = "6.17"
+googleauth = "1.4.0"
+guava = "31.1-android"
+netty = "4.1.72.Final"
+opencensus = "0.31.0"
+protobuf = "3.19.2"
+
+[libraries]
+android-annotations = "com.google.android:annotations:4.1.1.4"
+androidx-annotation = "androidx.annotation:annotation:1.1.0"
+androidx-core = "androidx.core:core:1.3.0"
+androidx-lifecycle-common = "androidx.lifecycle:lifecycle-common:2.3.0"
+androidx-lifecycle-service = "androidx.lifecycle:lifecycle-service:2.3.0"
+androidx-test-core = "androidx.test:core:1.3.0"
+androidx-test-ext-junit = "androidx.test.ext:junit:1.1.2"
+androidx-test-rules = "androidx.test:rules:1.3.0"
+animalsniffer-annotations = "org.codehaus.mojo:animal-sniffer-annotations:1.19"
+auto-value = { module = "com.google.auto.value:auto-value", version.ref = "autovalue" }
+auto-value-annotations = { module = "com.google.auto.value:auto-value-annotations", version.ref = "autovalue" }
+commons-math3 = "org.apache.commons:commons-math3:3.6.1"
+conscrypt = "org.conscrypt:conscrypt-openjdk-uber:2.5.1"
+cronet-api = "org.chromium.net:cronet-api:92.4515.131"
+cronet-embedded = "org.chromium.net:cronet-embedded:92.4515.131"
+errorprone-annotations = "com.google.errorprone:error_prone_annotations:2.11.0"
+errorprone-core = "com.google.errorprone:error_prone_core:2.10.0"
+errorprone-javac = "com.google.errorprone:javac:9+181-r4173-1"
+google-api-protos = "com.google.api.grpc:proto-google-common-protos:2.0.1"
+google-auth-credentials = { module = "com.google.auth:google-auth-library-credentials", version.ref = "googleauth" }
+google-auth-oauth2Http = { module = "com.google.auth:google-auth-library-oauth2-http", version.ref = "googleauth" }
+gson = "com.google.code.gson:gson:2.9.0"
+guava = { module = "com.google.guava:guava", version.ref = "guava" }
+guava-betaChecker = "com.google.guava:guava-beta-checker:1.0"
+guava-testlib = { module = "com.google.guava:guava-testlib", version.ref = "guava" }
+hdrhistogram = "org.hdrhistogram:HdrHistogram:2.1.12"
+instrumentation-api = "com.google.instrumentation:instrumentation-api:0.4.3"
+javax-annotation = "org.apache.tomcat:annotations-api:6.0.53"
+jetty-alpn-agent = "org.mortbay.jetty.alpn:jetty-alpn-agent:2.0.10"
+jsr305 = "com.google.code.findbugs:jsr305:3.0.2"
+junit = "junit:junit:4.12"
+mockito-android = "org.mockito:mockito-android:3.8.0"
+mockito-core = "org.mockito:mockito-core:3.3.3"
+netty-codec-http2 = { module = "io.netty:netty-codec-http2", version.ref = "netty" }
+netty-handler-proxy = { module = "io.netty:netty-handler-proxy", version.ref = "netty" }
+netty-transport-epoll = { module = "io.netty:netty-transport-native-epoll", version.ref = "netty" }
+# Keep the following references of tcnative version in sync whenever it's updated:
+#   SECURITY.md (multiple occurrences)
+#   examples/example-tls/build.gradle
+#   examples/example-tls/pom.xml
+netty-tcnative = "io.netty:netty-tcnative-boringssl-static:2.0.46.Final"
+netty-unix-common = { module = "io.netty:netty-transport-native-unix-common", version.ref = "netty" }
+okhttp = "com.squareup.okhttp:okhttp:2.7.4"
+okio = "com.squareup.okio:okio:1.17.5"
+opencensus-api = { module = "io.opencensus:opencensus-api", version.ref = "opencensus" }
+opencensus-contrib-grpc-metrics = { module = "io.opencensus:opencensus-contrib-grpc-metrics", version.ref = "opencensus" }
+opencensus-impl = { module = "io.opencensus:opencensus-impl", version.ref = "opencensus" }
+opencensus-impl-lite = { module = "io.opencensus:opencensus-impl-lite", version.ref = "opencensus" }
+opencensus-proto = "io.opencensus:opencensus-proto:0.2.0"
+perfmark-api = "io.perfmark:perfmark-api:0.25.0"
+protobuf-java = { module = "com.google.protobuf:protobuf-java", version.ref = "protobuf" }
+protobuf-java-util = { module = "com.google.protobuf:protobuf-java-util", version.ref = "protobuf" }
+protobuf-javalite = { module = "com.google.protobuf:protobuf-javalite", version.ref = "protobuf" }
+protobuf-protoc = { module = "com.google.protobuf:protoc", version.ref = "protobuf" }
+re2j = "com.google.re2j:re2j:1.5"
+robolectric = "org.robolectric:robolectric:4.4"
+truth = "com.google.truth:truth:1.0.1"
diff --git a/grpclb/build.gradle b/grpclb/build.gradle
index 58ff2f4..14e3d19 100644
--- a/grpclb/build.gradle
+++ b/grpclb/build.gradle
@@ -14,11 +14,11 @@
     implementation project(':grpc-core'),
             project(':grpc-protobuf'),
             project(':grpc-stub'),
-            libraries.protobuf,
-            libraries.protobuf_util,
+            libraries.protobuf.java,
+            libraries.protobuf.java.util,
             libraries.guava
-    runtimeOnly libraries.errorprone
-    compileOnly libraries.javax_annotation
+    runtimeOnly libraries.errorprone.annotations
+    compileOnly libraries.javax.annotation
     testImplementation libraries.truth,
             project(':grpc-core').sourceSets.test.output
 }
diff --git a/interop-testing/build.gradle b/interop-testing/build.gradle
index 385374d..533adee 100644
--- a/interop-testing/build.gradle
+++ b/interop-testing/build.gradle
@@ -32,11 +32,11 @@
             libraries.hdrhistogram,
             libraries.junit,
             libraries.truth,
-            libraries.opencensus_contrib_grpc_metrics,
-            libraries.google_auth_oauth2_http
+            libraries.opencensus.contrib.grpc.metrics,
+            libraries.google.auth.oauth2Http
     def xdsDependency = implementation project(':grpc-xds')
 
-    compileOnly libraries.javax_annotation
+    compileOnly libraries.javax.annotation
     shadow configurations.implementation.getDependencies().minus(xdsDependency)
     shadow project(path: ':grpc-xds', configuration: 'shadow')
     // TODO(sergiitk): replace with com.google.cloud:google-cloud-logging
@@ -46,16 +46,16 @@
     // Error example: "java.util.logging.ErrorManager: 1"
     // Latest failing version com.google.cloud:google-cloud-logging:2.1.2
     runtimeOnly group: 'io.github.devatherock', name: 'jul-jsonformatter', version: '1.1.0'
-    runtimeOnly libraries.opencensus_impl,
-            libraries.netty_tcnative,
+    runtimeOnly libraries.opencensus.impl,
+            libraries.netty.tcnative,
             project(':grpc-grpclb'),
             project(':grpc-rls')
     testImplementation project(':grpc-context').sourceSets.test.output,
             project(':grpc-api').sourceSets.test.output,
             project(':grpc-core').sourceSets.test.output,
-            libraries.mockito,
+            libraries.mockito.core,
             libraries.okhttp
-    alpnagent libraries.jetty_alpn_agent
+    alpnagent libraries.jetty.alpn.agent
 }
 
 configureProtoCompilation()
diff --git a/netty/build.gradle b/netty/build.gradle
index 09fb39e..74db632 100644
--- a/netty/build.gradle
+++ b/netty/build.gradle
@@ -17,28 +17,28 @@
 
 dependencies {
     api project(':grpc-core'),
-            libraries.netty
-    implementation libraries.netty_proxy_handler,
+            libraries.netty.codec.http2
+    implementation libs.netty.handler.proxy,
             libraries.guava,
-            libraries.errorprone,
-            libraries.perfmark,
-            libraries.netty_unix_common
+            libraries.errorprone.annotations,
+            libraries.perfmark.api,
+            libraries.netty.unix.common
 
     // Tests depend on base class defined by core module.
     testImplementation project(':grpc-core').sourceSets.test.output,
             project(':grpc-api').sourceSets.test.output,
             project(':grpc-testing'),
             project(':grpc-testing-proto'),
-            libraries.netty_epoll
-    testRuntimeOnly libraries.netty_tcnative,
+            libraries.netty.transport.epoll
+    testRuntimeOnly libraries.netty.tcnative,
             libraries.conscrypt
-    testRuntimeOnly (libraries.netty_epoll) {
+    testRuntimeOnly (libraries.netty.transport.epoll) {
         artifact {
             classifier = "linux-x86_64"
         }
     }
     signature "org.codehaus.mojo.signature:java17:1.0@signature"
-    alpnagent libraries.jetty_alpn_agent
+    alpnagent libraries.jetty.alpn.agent
 }
 
 import net.ltgt.gradle.errorprone.CheckSeverity
diff --git a/netty/shaded/build.gradle b/netty/shaded/build.gradle
index 739320b..a790b55 100644
--- a/netty/shaded/build.gradle
+++ b/netty/shaded/build.gradle
@@ -17,13 +17,13 @@
 
 dependencies {
     implementation project(':grpc-netty')
-    runtimeOnly libraries.netty_tcnative
-    runtimeOnly (libraries.netty_epoll) {
+    runtimeOnly libraries.netty.tcnative
+    runtimeOnly (libraries.netty.transport.epoll) {
         artifact {
             classifier = "linux-x86_64"
         }
     }
-    runtimeOnly (libraries.netty_epoll) {
+    runtimeOnly (libraries.netty.transport.epoll) {
         artifact {
             classifier = "linux-aarch_64"
         }
diff --git a/okhttp/build.gradle b/okhttp/build.gradle
index 490e527..fffdf8d 100644
--- a/okhttp/build.gradle
+++ b/okhttp/build.gradle
@@ -14,7 +14,7 @@
     api project(':grpc-core')
     implementation libraries.okio,
             libraries.guava,
-            libraries.perfmark
+            libraries.perfmark.api
     // Make okhttp dependencies compile only
     compileOnly libraries.okhttp
     // Tests depend on base class defined by core module.
diff --git a/protobuf-lite/build.gradle b/protobuf-lite/build.gradle
index 7b58309..77e3578 100644
--- a/protobuf-lite/build.gradle
+++ b/protobuf-lite/build.gradle
@@ -11,7 +11,7 @@
 
 dependencies {
     api project(':grpc-api'),
-            libraries.protobuf_lite
+            libraries.protobuf.javalite
     implementation libraries.jsr305,
             libraries.guava
 
@@ -33,7 +33,7 @@
         if (project.hasProperty('protoc')) {
             path = project.protoc
         } else {
-            artifact = "com.google.protobuf:protoc:${protocVersion}"
+            artifact = libs.protobuf.protoc.get()
         }
     }
     generateProtoTasks {
diff --git a/protobuf/build.gradle b/protobuf/build.gradle
index bb8546d..8853d38 100644
--- a/protobuf/build.gradle
+++ b/protobuf/build.gradle
@@ -12,10 +12,10 @@
 dependencies {
     api project(':grpc-api'),
             libraries.jsr305,
-            libraries.protobuf
+            libraries.protobuf.java
     implementation libraries.guava
 
-    api (libraries.google_api_protos) {
+    api (libraries.google.api.protos) {
         // 'com.google.api:api-common' transitively depends on auto-value, which breaks our
         // annotations.
         exclude group: 'com.google.api', module: 'api-common'
diff --git a/rls/build.gradle b/rls/build.gradle
index 45f17fb..60b971a 100644
--- a/rls/build.gradle
+++ b/rls/build.gradle
@@ -14,10 +14,10 @@
     implementation project(':grpc-core'),
             project(':grpc-protobuf'),
             project(':grpc-stub'),
-            libraries.autovalue_annotation,
+            libraries.auto.value.annotations,
             libraries.guava
-    annotationProcessor libraries.autovalue
-    compileOnly libraries.javax_annotation
+    annotationProcessor libraries.auto.value
+    compileOnly libraries.javax.annotation
     testImplementation libraries.truth,
             project(':grpc-grpclb'),
             project(':grpc-testing'),
diff --git a/services/build.gradle b/services/build.gradle
index 5a3dd23..d53f05a 100644
--- a/services/build.gradle
+++ b/services/build.gradle
@@ -22,16 +22,16 @@
     api project(':grpc-protobuf'),
             project(':grpc-stub'),
             project(':grpc-core')
-    implementation libraries.protobuf_util,
+    implementation libraries.protobuf.java.util,
             libraries.guava
 
-    runtimeOnly libraries.errorprone
+    runtimeOnly libraries.errorprone.annotations
 
-    compileOnly libraries.javax_annotation
+    compileOnly libraries.javax.annotation
     testImplementation project(':grpc-testing'),
-            libraries.netty_epoll, // for DomainSocketAddress
+            libraries.netty.transport.epoll, // for DomainSocketAddress
             project(':grpc-core').sourceSets.test.output  // for FakeClock
-    testCompileOnly libraries.javax_annotation
+    testCompileOnly libraries.javax.annotation
     signature "org.codehaus.mojo.signature:java17:1.0@signature"
 }
 
diff --git a/settings.gradle b/settings.gradle
index 254fea4..64a1291 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -25,6 +25,8 @@
     }
 }
 
+enableFeaturePreview('VERSION_CATALOGS')
+
 rootProject.name = "grpc"
 include ":grpc-api"
 include ":grpc-core"
diff --git a/stub/build.gradle b/stub/build.gradle
index 2b5a6a4..d5378ca 100644
--- a/stub/build.gradle
+++ b/stub/build.gradle
@@ -10,7 +10,7 @@
 dependencies {
     api project(':grpc-api'),
         libraries.guava
-    implementation libraries.errorprone
+    implementation libraries.errorprone.annotations
     testImplementation libraries.truth,
             project(':grpc-testing')
     signature "org.codehaus.mojo.signature:java17:1.0@signature"
diff --git a/testing-proto/build.gradle b/testing-proto/build.gradle
index f12fe92..5ee06fe 100644
--- a/testing-proto/build.gradle
+++ b/testing-proto/build.gradle
@@ -10,9 +10,9 @@
 dependencies {
     api project(':grpc-protobuf'),
             project(':grpc-stub')
-    compileOnly libraries.javax_annotation
+    compileOnly libraries.javax.annotation
     testImplementation libraries.truth
-    testRuntimeOnly libraries.javax_annotation
+    testRuntimeOnly libraries.javax.annotation
 }
 
 configureProtoCompilation()
diff --git a/testing/build.gradle b/testing/build.gradle
index 0879eca..4b5fa32 100644
--- a/testing/build.gradle
+++ b/testing/build.gradle
@@ -14,10 +14,10 @@
             project(':grpc-stub'),
             libraries.junit
     // Only io.grpc.internal.testing.StatsTestUtils depends on opencensus_api, for internal use.
-    compileOnly libraries.opencensus_api
+    compileOnly libraries.opencensus.api
     runtimeOnly project(":grpc-context") // Pull in newer version than census-api
 
-    testImplementation (libraries.mockito) {
+    testImplementation (libraries.mockito.core) {
         // prefer our own versions instead of mockito's dependency
         exclude group: 'org.hamcrest', module: 'hamcrest-core'
     }
diff --git a/xds/build.gradle b/xds/build.gradle
index 48d3d80..935324b 100644
--- a/xds/build.gradle
+++ b/xds/build.gradle
@@ -35,27 +35,27 @@
             project(path: ':grpc-alts', configuration: 'shadow'),
             libraries.gson,
             libraries.re2j,
-            libraries.autovalue_annotation,
-            libraries.opencensus_proto,
-            libraries.protobuf_util
+            libraries.auto.value.annotations,
+            libraries.opencensus.proto,
+            libraries.protobuf.java.util
     def nettyDependency = implementation project(':grpc-netty')
 
     testImplementation project(':grpc-rls')
     testImplementation project(':grpc-core').sourceSets.test.output
 
-    annotationProcessor libraries.autovalue
-    compileOnly libraries.javax_annotation,
+    annotationProcessor libraries.auto.value
+    compileOnly libraries.javax.annotation,
             // At runtime use the epoll included in grpc-netty-shaded
-            libraries.netty_epoll
+            libraries.netty.transport.epoll
 
     testImplementation project(':grpc-testing'),
             project(':grpc-testing-proto')
-    testImplementation (libraries.netty_epoll) {
+    testImplementation (libraries.netty.transport.epoll) {
         artifact {
             classifier = "linux-x86_64"
         }
     }
-    testImplementation (libraries.guava_testlib) {
+    testImplementation (libraries.guava.testlib) {
         exclude group: 'junit', module: 'junit'
     }
 
@@ -63,7 +63,7 @@
     shadow project(path: ':grpc-netty-shaded', configuration: 'shadow')
 
     signature "org.codehaus.mojo.signature:java17:1.0@signature"
-    testRuntimeOnly libraries.netty_tcnative
+    testRuntimeOnly libraries.netty.tcnative
 }
 
 sourceSets {