Introducing Compile-Only Dependencies

One of the most highly-anticipated Gradle features has just arrived in Gradle 2.12: support for declaring compile-only dependencies. For Java developers familiar with Maven, compile-only dependencies function similarly to Maven’s provided scope, allowing you to declare non-transitive dependencies used only at compilation time. While a similar capability has been available for users of the Gradle War Plugin, compile-only dependencies can now be declared for all Java projects using the Java Plugin.

Compile-only dependencies address a number of use cases, including:

  • Dependencies required at compile time but never required at runtime, such as source-only annotations or annotation processors;
  • Dependencies required at compile time but required at runtime only when using certain features, a.k.a. optional dependencies;
  • Dependencies whose API is required at compile time but whose implementation is to be provided by a consuming library, application or runtime environment.

Compile-only dependencies are distinctly different than regular compile dependencies. They are not included on the runtime classpath and they are non-transitive, meaning they are not included in dependent projects. This is true when using Gradle project dependencies and also when publishing to Maven or Ivy repositories. In the latter case, compile-only dependencies are simply omitted from published metadata.

As part of our commitment to quality IDE support, compile-only dependencies continue to work with Gradle’s IDEA and Eclipse plugins. When used within IntelliJ IDEA, compile-only dependencies are mapped to IDEA’s own provided scope. Within Eclipse, compile-only dependencies are not exported via project dependencies.

In the Gradle model we consider tests to be a “consumer” of the production code. With this in mind, compile-only dependencies are not inherited by the test classpath. The intention is that tests, like any other runtime environment, should provide their own implementation, either in the form of mocks or some other dependency.

Declaring compile-only dependencies is simple—just assign dependencies to the new compileOnly configuration for the appropriate source set:

dependencies {
    compileOnly 'javax.servlet:servlet-api:2.5'
}

As a result of the addition of the compileOnly configuration, the compile configuration no longer represents a complete picture of all compile time dependencies. When it’s necessary to reference a compile classpath in build scripts or custom plugins, the appropriate source set’s compileClasspath property should be used instead.

For more information, see the Java Plugin chapter of the Gradle user guide. And as always, we welcome your feedback and questions in the comments below or via the Gradle Forum at discuss.gradle.org.