From c1dfa885ae741aa01c7ba5b145a2a9a159b2a0d1 Mon Sep 17 00:00:00 2001 From: Yuri Schimke Date: Wed, 4 Feb 2026 21:00:33 +0000 Subject: [PATCH 1/5] Fix configuration cache issues --- build-logic/src/main/kotlin/Osgi.kt | 97 ++++++++++++------- .../kotlin/okhttp.base-conventions.gradle.kts | 7 +- gradle.properties | 6 ++ okhttp/build.gradle.kts | 5 +- 4 files changed, 72 insertions(+), 43 deletions(-) diff --git a/build-logic/src/main/kotlin/Osgi.kt b/build-logic/src/main/kotlin/Osgi.kt index 18869a86c120..3ffcddff60ee 100644 --- a/build-logic/src/main/kotlin/Osgi.kt +++ b/build-logic/src/main/kotlin/Osgi.kt @@ -30,9 +30,7 @@ import org.gradle.kotlin.dsl.getByName import org.gradle.kotlin.dsl.named fun Project.applyOsgi(vararg bndProperties: String) { - plugins.withId("org.jetbrains.kotlin.jvm") { - applyOsgi("jar", "osgiApi", bndProperties) - } + plugins.withId("org.jetbrains.kotlin.jvm") { applyOsgi("jar", "osgiApi", bndProperties) } } private fun Project.applyOsgi( @@ -43,24 +41,33 @@ private fun Project.applyOsgi( val osgi = project.sourceSets.create("osgi") val osgiApi = project.configurations.getByName(osgiApiConfigurationName) - project.dependencies { - osgiApi(kotlinOsgi) - } + project.dependencies { osgiApi(kotlinOsgi) } val jarTask = tasks.getByName(jarTaskName) val bundleExtension = - jarTask.extensions.findByType() ?: jarTask.extensions.create( - BundleTaskExtension.NAME, - BundleTaskExtension::class.java, - jarTask, - ) + jarTask.extensions.findByType() + ?: jarTask.extensions.create( + BundleTaskExtension.NAME, + BundleTaskExtension::class.java, + jarTask, + ) bundleExtension.run { setClasspath(osgi.compileClasspath + sourceSets["main"].compileClasspath) bnd(*bndProperties) } // Call the convention when the task has finished, to modify the jar to contain OSGi metadata. - jarTask.doLast { - bundleExtension.buildAction().execute(this) + val okhttpForceConfigurationCache = + project.providers + .gradleProperty("okhttpForceConfigurationCache") + .map { it.toBoolean() } + .getOrElse(false) + if (!okhttpForceConfigurationCache) { + val buildAction = bundleExtension.buildAction() + jarTask.doLast { buildAction.execute(this) } + } else { + logger.warn( + "Skipping OSGi metadata generation for ${jarTask.name} because configuration caching is enabled and BND is not compatible." + ) } } @@ -77,55 +84,71 @@ fun Project.applyOsgiMultiplatform(vararg bndProperties: String) { object : SourceSet by jvmMainSourceSet { override fun getName() = "main" - override fun getProcessResourcesTaskName() = "${jvmMainSourceSet.processResourcesTaskName}ForFakeMain" + override fun getProcessResourcesTaskName() = + "${jvmMainSourceSet.processResourcesTaskName}ForFakeMain" - override fun getCompileJavaTaskName() = "${jvmMainSourceSet.compileJavaTaskName}ForFakeMain" + override fun getCompileJavaTaskName() = + "${jvmMainSourceSet.compileJavaTaskName}ForFakeMain" override fun getClassesTaskName() = "${jvmMainSourceSet.classesTaskName}ForFakeMain" - override fun getCompileOnlyConfigurationName(): String = jvmMainSourceSet.compileOnlyConfigurationName + "ForFakeMain" + override fun getCompileOnlyConfigurationName(): String = + jvmMainSourceSet.compileOnlyConfigurationName + "ForFakeMain" - override fun getCompileClasspathConfigurationName(): String = jvmMainSourceSet.compileClasspathConfigurationName + "ForFakeMain" + override fun getCompileClasspathConfigurationName(): String = + jvmMainSourceSet.compileClasspathConfigurationName + "ForFakeMain" - override fun getImplementationConfigurationName(): String = jvmMainSourceSet.implementationConfigurationName + "ForFakeMain" + override fun getImplementationConfigurationName(): String = + jvmMainSourceSet.implementationConfigurationName + "ForFakeMain" - override fun getAnnotationProcessorConfigurationName(): String = jvmMainSourceSet.annotationProcessorConfigurationName + "ForFakeMain" + override fun getAnnotationProcessorConfigurationName(): String = + jvmMainSourceSet.annotationProcessorConfigurationName + "ForFakeMain" - override fun getRuntimeClasspathConfigurationName(): String = jvmMainSourceSet.runtimeClasspathConfigurationName + "ForFakeMain" + override fun getRuntimeClasspathConfigurationName(): String = + jvmMainSourceSet.runtimeClasspathConfigurationName + "ForFakeMain" - override fun getRuntimeOnlyConfigurationName(): String = jvmMainSourceSet.runtimeOnlyConfigurationName + "ForFakeMain" + override fun getRuntimeOnlyConfigurationName(): String = + jvmMainSourceSet.runtimeOnlyConfigurationName + "ForFakeMain" override fun getTaskName( verb: String?, target: String?, ) = "${jvmMainSourceSet.getTaskName(verb, target)}ForFakeMain" } - extensions - .getByType(JavaPluginExtension::class.java) - .sourceSets - .add(mainSourceSet) + extensions.getByType(JavaPluginExtension::class.java).sourceSets.add(mainSourceSet) tasks.named { it.endsWith("ForFakeMain") }.configureEach { onlyIf { false } } val osgiApi = configurations.create("osgiApi") - dependencies { - osgiApi(kotlinOsgi) - } + dependencies { osgiApi(kotlinOsgi) } // Call the convention when the task has finished, to modify the jar to contain OSGi metadata. tasks.named("jvmJar").configure { val bundleExtension = - extensions - .create( - BundleTaskExtension.NAME, - BundleTaskExtension::class.java, - this, - ).apply { - classpath(osgiApi.artifacts) + extensions.create( + BundleTaskExtension.NAME, + BundleTaskExtension::class.java, + this, + ) + .apply { + val osgiApiArtifacts = osgiApi.artifacts + classpath(osgiApiArtifacts) classpath(tasks.named("jvmMainClasses").map { it.outputs }) bnd(*bndProperties) } - doLast { - bundleExtension.buildAction().execute(this) + val okhttpForceConfigurationCache = + project.providers + .gradleProperty("okhttpForceConfigurationCache") + .map { it.toBoolean() } + .getOrElse(false) + if (!okhttpForceConfigurationCache) { + val buildAction = bundleExtension.buildAction() + doLast { buildAction.execute(this) } + } else { + // Configuration caching is enabled, and BND's buildAction is not compatible. + // We skip OSGi metadata generation for now when configuration caching is enabled. + logger.warn( + "Skipping OSGi metadata generation for :okhttp:jvmJar because configuration caching is enabled and BND is not compatible." + ) } } } diff --git a/build-logic/src/main/kotlin/okhttp.base-conventions.gradle.kts b/build-logic/src/main/kotlin/okhttp.base-conventions.gradle.kts index 2c7c3a7bf517..5bdff2c6f2da 100644 --- a/build-logic/src/main/kotlin/okhttp.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/okhttp.base-conventions.gradle.kts @@ -48,13 +48,12 @@ tasks.withType().configureEach { friendPaths.from(friendsTestImplementation.incoming.artifactView { }.files) } +val resolvableConfigurations = configurations.filter { it.isCanBeResolved } tasks.register("downloadDependencies") { description = "Download all dependencies to the Gradle cache" doLast { - for (configuration in configurations) { - if (configuration.isCanBeResolved) { - configuration.files - } + for (configuration in resolvableConfigurations) { + configuration.files } } } diff --git a/gradle.properties b/gradle.properties index 5ee973826ad9..9f7d385a24e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,9 @@ org.gradle.caching=true org.gradle.parallel=true +# Blocked on BND +org.gradle.configuration-cache=false + android.useAndroidX=true kotlin.mpp.applyDefaultHierarchyTemplate=false @@ -11,6 +14,9 @@ containerTests=false okhttpModuleTests=false okhttpDokka=false +# When true BND is disabled to allow testing configuration-cache +okhttpForceConfigurationCache=false + org.gradle.jvmargs='-Dfile.encoding=UTF-8' # AGP 9.0 Settings diff --git a/okhttp/build.gradle.kts b/okhttp/build.gradle.kts index 97f8cd55938f..152bc0a7fbd9 100644 --- a/okhttp/build.gradle.kts +++ b/okhttp/build.gradle.kts @@ -29,9 +29,10 @@ val copyKotlinTemplates = filteringCharset = Charsets.UTF_8.toString() + val projectVersionProvider = project.provider { project.version } expand( // Build & use okhttp3/internal/-InternalVersion.kt - "projectVersion" to project.version, + "projectVersion" to projectVersionProvider, ) } @@ -284,7 +285,7 @@ tasks.named("jvmJar").configure { ) } - from(compileJavaModuleInfo.get().destinationDirectory) { + from(compileJavaModuleInfo.map { it.destinationDirectory }) { into("META-INF/versions/9/") } } From 5c9236ec7824ee8e65d59d9a663f77db5b7facbc Mon Sep 17 00:00:00 2001 From: Yuri Schimke Date: Wed, 4 Feb 2026 21:01:57 +0000 Subject: [PATCH 2/5] cleanup --- build-logic/src/main/kotlin/Osgi.kt | 40 ++++++++----------- .../okhttp3/buildsupport/OkHttpBuildUtils.kt | 8 ++-- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/build-logic/src/main/kotlin/Osgi.kt b/build-logic/src/main/kotlin/Osgi.kt index 3ffcddff60ee..bffcb50cc193 100644 --- a/build-logic/src/main/kotlin/Osgi.kt +++ b/build-logic/src/main/kotlin/Osgi.kt @@ -66,7 +66,7 @@ private fun Project.applyOsgi( jarTask.doLast { buildAction.execute(this) } } else { logger.warn( - "Skipping OSGi metadata generation for ${jarTask.name} because configuration caching is enabled and BND is not compatible." + "Skipping OSGi metadata generation for ${jarTask.name} because configuration caching is enabled and BND is not compatible.", ) } } @@ -84,31 +84,23 @@ fun Project.applyOsgiMultiplatform(vararg bndProperties: String) { object : SourceSet by jvmMainSourceSet { override fun getName() = "main" - override fun getProcessResourcesTaskName() = - "${jvmMainSourceSet.processResourcesTaskName}ForFakeMain" + override fun getProcessResourcesTaskName() = "${jvmMainSourceSet.processResourcesTaskName}ForFakeMain" - override fun getCompileJavaTaskName() = - "${jvmMainSourceSet.compileJavaTaskName}ForFakeMain" + override fun getCompileJavaTaskName() = "${jvmMainSourceSet.compileJavaTaskName}ForFakeMain" override fun getClassesTaskName() = "${jvmMainSourceSet.classesTaskName}ForFakeMain" - override fun getCompileOnlyConfigurationName(): String = - jvmMainSourceSet.compileOnlyConfigurationName + "ForFakeMain" + override fun getCompileOnlyConfigurationName(): String = jvmMainSourceSet.compileOnlyConfigurationName + "ForFakeMain" - override fun getCompileClasspathConfigurationName(): String = - jvmMainSourceSet.compileClasspathConfigurationName + "ForFakeMain" + override fun getCompileClasspathConfigurationName(): String = jvmMainSourceSet.compileClasspathConfigurationName + "ForFakeMain" - override fun getImplementationConfigurationName(): String = - jvmMainSourceSet.implementationConfigurationName + "ForFakeMain" + override fun getImplementationConfigurationName(): String = jvmMainSourceSet.implementationConfigurationName + "ForFakeMain" - override fun getAnnotationProcessorConfigurationName(): String = - jvmMainSourceSet.annotationProcessorConfigurationName + "ForFakeMain" + override fun getAnnotationProcessorConfigurationName(): String = jvmMainSourceSet.annotationProcessorConfigurationName + "ForFakeMain" - override fun getRuntimeClasspathConfigurationName(): String = - jvmMainSourceSet.runtimeClasspathConfigurationName + "ForFakeMain" + override fun getRuntimeClasspathConfigurationName(): String = jvmMainSourceSet.runtimeClasspathConfigurationName + "ForFakeMain" - override fun getRuntimeOnlyConfigurationName(): String = - jvmMainSourceSet.runtimeOnlyConfigurationName + "ForFakeMain" + override fun getRuntimeOnlyConfigurationName(): String = jvmMainSourceSet.runtimeOnlyConfigurationName + "ForFakeMain" override fun getTaskName( verb: String?, @@ -124,12 +116,12 @@ fun Project.applyOsgiMultiplatform(vararg bndProperties: String) { // Call the convention when the task has finished, to modify the jar to contain OSGi metadata. tasks.named("jvmJar").configure { val bundleExtension = - extensions.create( - BundleTaskExtension.NAME, - BundleTaskExtension::class.java, - this, - ) - .apply { + extensions + .create( + BundleTaskExtension.NAME, + BundleTaskExtension::class.java, + this, + ).apply { val osgiApiArtifacts = osgiApi.artifacts classpath(osgiApiArtifacts) classpath(tasks.named("jvmMainClasses").map { it.outputs }) @@ -147,7 +139,7 @@ fun Project.applyOsgiMultiplatform(vararg bndProperties: String) { // Configuration caching is enabled, and BND's buildAction is not compatible. // We skip OSGi metadata generation for now when configuration caching is enabled. logger.warn( - "Skipping OSGi metadata generation for :okhttp:jvmJar because configuration caching is enabled and BND is not compatible." + "Skipping OSGi metadata generation for :okhttp:jvmJar because configuration caching is enabled and BND is not compatible.", ) } } diff --git a/build-logic/src/main/kotlin/okhttp3/buildsupport/OkHttpBuildUtils.kt b/build-logic/src/main/kotlin/okhttp3/buildsupport/OkHttpBuildUtils.kt index d78cd0551e9b..3ae040629f8e 100644 --- a/build-logic/src/main/kotlin/okhttp3/buildsupport/OkHttpBuildUtils.kt +++ b/build-logic/src/main/kotlin/okhttp3/buildsupport/OkHttpBuildUtils.kt @@ -3,13 +3,13 @@ package okhttp3.buildsupport import org.gradle.api.Project val Project.platform: String - get() = findProperty("okhttp.platform")?.toString() ?: "jdk9" + get() = findProperty("okhttp.platform")?.toString() ?: "jdk9" val Project.testJavaVersion: Int - get() = findProperty("test.java.version")?.toString()?.toInt() ?: 21 + get() = findProperty("test.java.version")?.toString()?.toInt() ?: 21 val Project.androidBuild: Boolean - get() = findProperty("androidBuild")?.toString()?.toBoolean() ?: false + get() = findProperty("androidBuild")?.toString()?.toBoolean() ?: false val Project.alpnBootVersion: String? - get() = findProperty("alpn.boot.version")?.toString() + get() = findProperty("alpn.boot.version")?.toString() From 07484f75bc01db85b9c0bb4a3f749c1a02ab48dc Mon Sep 17 00:00:00 2001 From: Yuri Schimke Date: Wed, 4 Feb 2026 21:15:03 +0000 Subject: [PATCH 3/5] fix --- okhttp/build.gradle.kts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/okhttp/build.gradle.kts b/okhttp/build.gradle.kts index 152bc0a7fbd9..afa384d9304b 100644 --- a/okhttp/build.gradle.kts +++ b/okhttp/build.gradle.kts @@ -29,10 +29,8 @@ val copyKotlinTemplates = filteringCharset = Charsets.UTF_8.toString() - val projectVersionProvider = project.provider { project.version } expand( - // Build & use okhttp3/internal/-InternalVersion.kt - "projectVersion" to projectVersionProvider, + "projectVersion" to project.version.toString(), ) } From f85991255f42f0f3507e768104b2001f78dca138 Mon Sep 17 00:00:00 2001 From: Yuri Schimke Date: Wed, 4 Feb 2026 21:17:55 +0000 Subject: [PATCH 4/5] fix --- okhttp-osgi-tests/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/okhttp-osgi-tests/build.gradle.kts b/okhttp-osgi-tests/build.gradle.kts index 0e58640655e5..94a7af0822e9 100644 --- a/okhttp-osgi-tests/build.gradle.kts +++ b/okhttp-osgi-tests/build.gradle.kts @@ -67,9 +67,13 @@ dependencies { } val testJavaVersion = project.testJavaVersion +val okhttpForceConfigurationCache: String by project tasks.withType { dependsOn(copyOsgiTestDeployment) onlyIf("Tests require JDK 17") { testJavaVersion >= 17 } + onlyIf("OSGi tests are incompatible with configuration cache due to BND limitations") { + !okhttpForceConfigurationCache.toBoolean() + } } From 125309991ee0c4631b5360786bae89d3da272f96 Mon Sep 17 00:00:00 2001 From: Yuri Schimke Date: Wed, 4 Feb 2026 21:23:29 +0000 Subject: [PATCH 5/5] another attempt --- build-logic/src/main/kotlin/Osgi.kt | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/build-logic/src/main/kotlin/Osgi.kt b/build-logic/src/main/kotlin/Osgi.kt index bffcb50cc193..1066b33507fd 100644 --- a/build-logic/src/main/kotlin/Osgi.kt +++ b/build-logic/src/main/kotlin/Osgi.kt @@ -28,6 +28,7 @@ import org.gradle.kotlin.dsl.findByType import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.getByName import org.gradle.kotlin.dsl.named +import org.gradle.kotlin.dsl.provideDelegate fun Project.applyOsgi(vararg bndProperties: String) { plugins.withId("org.jetbrains.kotlin.jvm") { applyOsgi("jar", "osgiApi", bndProperties) } @@ -56,12 +57,8 @@ private fun Project.applyOsgi( bnd(*bndProperties) } // Call the convention when the task has finished, to modify the jar to contain OSGi metadata. - val okhttpForceConfigurationCache = - project.providers - .gradleProperty("okhttpForceConfigurationCache") - .map { it.toBoolean() } - .getOrElse(false) - if (!okhttpForceConfigurationCache) { + val okhttpForceConfigurationCache: String by project + if (!okhttpForceConfigurationCache.toBoolean()) { val buildAction = bundleExtension.buildAction() jarTask.doLast { buildAction.execute(this) } } else { @@ -127,12 +124,8 @@ fun Project.applyOsgiMultiplatform(vararg bndProperties: String) { classpath(tasks.named("jvmMainClasses").map { it.outputs }) bnd(*bndProperties) } - val okhttpForceConfigurationCache = - project.providers - .gradleProperty("okhttpForceConfigurationCache") - .map { it.toBoolean() } - .getOrElse(false) - if (!okhttpForceConfigurationCache) { + val okhttpForceConfigurationCache: String by project + if (!okhttpForceConfigurationCache.toBoolean()) { val buildAction = bundleExtension.buildAction() doLast { buildAction.execute(this) } } else {