Deprecation and removal of runtimeClasspath and related configurations should NOT occur

With Gradle 6.1.1 we get the following if we use runtimeClasspath configuration:

The runtimeClasspath configuration has been deprecated for dependency declaration. This will fail with an error in Gradle 7.0. Please use the implementation or compileOnly or runtimeOnly configuration instead.

This actually removes a valid and needed configuration and functionality of Gradle. It should not be removed. It could be replaced with something equivalent but it needs to exist. Current documentation does not state what the replacement should be. In fact, it does not even state that it is deprecated for 6.2. See:

https://docs.gradle.org/current/userguide/java_plugin.html
https://docs.gradle.org/6.2/userguide/java_plugin.html

Here are the saved versions in case the above changes:
https://web.archive.org/save/https://docs.gradle.org/current/userguide/java_plugin.html
https://web.archive.org/save/https://docs.gradle.org/6.2/userguide/java_plugin.html
https://web.archive.org/web/20200222171844/https://docs.gradle.org/6.2/userguide/java_plugin.html

Here are the reasons:

  1. It provides a common way to obtain everything that is needed at runtime. It isn’t just Gradle itself or tools built by Gradle needing this. Our scripts and surrounding ecosystem also rely on this to obtain “everything” rather than (a) having to know what actually goes in (implementation, runtimeOnly) and (b) actually reference all. Note that tools may not, in fact, know about other configurations that runtimeClasspath has been set to “extendsFrom” and would need separate setup for that.
  2. Gradle isn’t strict with transitive dependencies but it allows us to configure it to be strict. Safe and strict compile time dependencies should be NOT transitive (by default they are but can be configured not to be). In other words, if we use an unstated dependency the compilation should fail precisely because we didn’t state it as needed. Runtime dependencies ARE and should be transitive. But, at the same time the (unstated) transitive dependencies of compilation dependencies should nevertheless appear as (transitive) runtime dependencies. Gradle does not do this on its own by default but is easy to accomplish by adding the same compilation (implementation) dependency again as a runtime dependency and have the implementation configuration declared as NOT transitive. Duplication can be avoided with a little bit of utility scripting (we do that). Right now we do this dual declaration with implementation and runtimeClasspath configurations. runtimeOnly would not be the correct configuration to use as it implies that these aren’t used during compilation. Even if Gradle itself may not care if this is polluted with other stuff, other tools in the ecosystem do. Even if we wanted to declare our own “runtimeFromTransitiveImplementation” configuration, we would not have a proper way to “plug” it into any common configuration that the rest of Gradle ecosystem would know about (e.g. runtimeClasspath.extendsFrom runtimeFromTransitiveImplementation) - that brings us full circle back to the issue #1.

Much of the above applies to RuntimeClasspath and also compileClasspath and CompileClasspath.

The most positive way I can understand this, and the way I am proceeding about this is that the configurations noted above will not be removed and that the only thing disappearing will be the ability to directly declare dependencies for them. Instead we will continue to be able to declare that they extend from a custom configuration we define.

I hope that this is it. Please confirm.

Hey @Learner

Don’t worry. We won’t remove such fundamental functionality.

The most positive way I can understand this, and the way I am proceeding about this is that the configurations noted above will not be removed and that the only thing disappearing will be the ability to directly declare dependencies for them. Instead we will continue to be able to declare that they extend from a custom configuration we define.

That is absolutely correct. If you want to declare something for “runtime only”, you should use runtimeOnly. If you want to resolve the complete runtime classpath, you should continue to rely on runtimeClasspath which will not go away.

Sorry if the wording is confusing. The concept of Configuration has evolved over time in Gradle and now there are basically three different usages of the Configuration concept:
https://docs.gradle.org/current/userguide/declaring_dependencies.html#sec:resolvable-consumable-configs

In the future we want to make these distinctions clearer and also optimize the code behind it. That’s why the unwanted ways of using a certain configuration are deprecated now.

1 Like

Thanks! That’s a relief!

1 Like