Gradle implementation vs. compile dependencies

Gradle implementation vs. compile

Last Updated on November 29, 2021

Gradle version 6 supports both the implementation and compile dependency configurations. Why are they both there and which one should you use? Let’s find out with the two simple rules described in this article.

Quick answer: use the implementation configuration and never compile, BUT read on for some important caveats

Ways to declare dependencies

When declaring Java dependencies in Gradle you provide a dependency configuration to which to assign your dependency. e.g.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web:2.2.5.RELEASE'

This uses the implementation dependency configuration. We can just as easily use the compile dependency configuration, at least in Gradle 6.

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web:2.2.5.RELEASE'

However, the docs for the Java plugin say:

Compile time dependencies. Superseded by implementation.

The compile dependency configuration has been removed in the recently released Gradle 7.0, and is deprecated in earlier versions. Fortunately, the implementation dependency configuration provides the same functionality as compile.

Rule One
You should always use implementation rather than compile for dependencies, as compile is now deprecated or removed in the case of Gradle 7+.

Breaking the rules gives warnings

If you try to use compile in your Gradle 6 project you’ll get a warning like this:

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use ‘–warning-mode all’ to show the individual deprecation warnings.

If you run with --warning-mode all enabled you’ll get a more detailed explanation:

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

So if you want to continue using the latest version of Gradle, I suggest swapping out compile for implementation as soon as possible. 🏃

What is an implementation dependency?

Forget Gradle for a moment. When you’re building and running a Java project there are two classpaths involved:

  1. Compile classpath – this is a list of dependencies that are required for the JDK to be able to compile Java code into .class files
  2. Runtime classpath – this list of dependencies is required to actually run the compiled Java code

When we’re configuring Gradle dependencies all we’re really doing is configuring which dependencies should appear on which classpath. Given there are only two classpaths, it makes sense that we have three options to declare our dependencies.

  1. compileOnly – put the dependency on the compile classpath only
  2. runtimeOnly – put the dependency on the runtime classpath only
  3. implementation – put the dependency on both classpaths

Rule Two
Use the implementation dependency configuration if you need the dependency to be on both the compile and runtime classpaths. If not, consider compileOnly or runtimeOnly.

Why would you care so much about a dependency being only on a specific classpath? Well, a few benefits include:

  • faster compilation if the compile classpath contains fewer dependencies
  • when writing code you won’t accidentally use a class that’s from a dependency that should only appear on the runtime classpath
  • cleaner classpaths reduce complexity

In Gradle you can inspect your classpaths using this task ./gradlew dependencies --configuration <compileClasspath | runtimeClasspath>, substituting in the configuration you want to see.

Dependency configurations for tests

It’s worth noting that it’s a very similar story for test dependencies, with the Gradle Java plugin providing the testRuntimeOnly, testImplementation, and testCompileOnly dependency configurations. What dependencies you add to these configurations determines how your test compile and runtime classpaths will be created.

Of course, these test configurations also inherit from the non-test configurations, at least for implementation and runtime. After all, your test code does need to call your non-test code.

For a full understanding of dependency configurations I highly recommend the Gradle Hero course, which also explains how they relate to tasks in your project.

Writing Java libraries has an extra twist

If you’re writing a library that another Gradle project is going to consume, then you’ll probably want to use the Java Library Plugin. This plugin adds an additional api configuration, on top of the already mentioned implementation configuration.

For any Gradle projects consuming a project built using the Java Library Plugin, the following applies:

  1. any api dependencies declared in the consumed library will appear on the compile and runtime classpaths of the consumer library
  2. any implementation dependencies in the consumed library will appear on only the runtime classpath of the consumer library

If this sounds a bit cryptic, you can check out all the details in the article How to use Gradle api vs. implementation dependencies with the Java Library plugin.

Quick summary on implementation and compile dependencies

There’s just one main point to remember when it comes to figuring out whether to use implementation vs. compile dependencies.

Rule 1: you should always use implementation rather than compile for dependencies, as compile is now deprecated or removed in Gradle 7+.

Also bear in mind:

Rule two: use the implementation dependency configuration if you need the dependency to be on both the compile and runtime classpaths. If not, consider compileOnly or runtimeOnly.

Hopefully this makes sense now. Be sure to check out the Gradle Java Plugin documentation on this subject.

Get going with Gradle course
Gradle icon

Want to learn more about Gradle?
Check out the full selection of Gradle tutorials.

Gradle implementation vs. compile dependencies

16 thoughts on “Gradle implementation vs. compile dependencies

  1. You saved my day, I noticed that the dependencies of the gradle project that uses a java library were not imported during the compile stage.
    So I changed `implementation` to `api`, which did the trick. Thank you! 🙂

  2. Gradle: 7.1.1
    Hi have an interesting one.
    In a multi-project setup

    main application as a bunch of tasks that use the core project
    Should work.
    But I get a warning “Executation Optimization have been disabled for task….
    as it uses output of task “core.jar” without declaring implicit dependancy.. ”
    The task being” prepareTestingfSandbox” which is for an intellij plug in

    Well I though i had defined it, if I do
    The warning vanishes, any ideas?

  3. I have classpath reference in build gradle like below
    classpath: configuartions.compile.asPath
    How can I conconvert it in Gradle 7?


    1. Hi Souvik. I think you have a typo, and you should reference the compileClasspath dependency configuration.

      This works for me in Gradle 7.2:

      println configurations.compileClasspath.asPath

  4. I have the same problem upgrading Gradle in 7.1.1. I did that as suggested here but I get an exception:
    * What went wrong:
    Execution failed for task ‘: processIntegrationTestResources’.
    > Entry jacocoagent.jar is a duplicate but no duplicate handling strategy has been set.

  5. After upgrading to Gradle 7 and replacing `testRuntime` with `testRuntimeOnly` in the following lines in my `build.gradle` file:
    sourceSets {
    e2eTest {
    compileClasspath += main.output + test.output + configurations.testRuntimeOnly
    I am getting the following error:
    Resolving dependency configuration ‘testRuntimeOnly’ is not allowed as it is defined as ‘canBeResolved=false’.
    Instead, a resolvable (‘canBeResolved=true’) dependency configuration that extends ‘testRuntimeOnly’ should be resolved.
    Any idea how to fix this?

    1. Hi Pietro. Just replace the word compile with implementation in the dependencies configuration in your build.gradle.

  6. This is a problem with earlier versions of gradle, as POM-only dependencies aren’t resolved correctly by ‘implementation’, but do work for ‘compile’. That just bit me today in a build using gradle 6.2.2. So you need to be careful not to switch too early.

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top


Getting started with Gradle just got A LOT easier!

Get Going with Gradle is the fastest way to a working knowledge of Gradle.

✅ Work effectively in basic Gradle projects
✅ Know how to setup Java projects in Gradle
✅ Understand the Gradle fundamentals

And it's yours today for FREE!

Where shall I send your access details?

Please wait...

Thank you, check your e-mail inbox for all the details!