I have a pretty simple Gradle Kotlin project.
plugins {
id 'application'
id 'maven-publish'
}
repositories { mavenCentral() }
dependencies {
compile 'com.google.guava:guava:31.1-jre' // 'compile' is deprecated
}
publishing {
publications {
maven(MavenPublication) {
groupId = 'de.mabe'; artifactId = 'project1'; version = '1.0'
from components.java
}
}
}
When I start gradle publishToMavenLocal
it generates a correct pom
file with a correct dependency:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
<scope>compile</scope> <!-- this scope is important -->
</dependency>
Now I replaced the compile
with implementation
in the gradle script.
implementation 'com.google.guava:guava:31.1-jre'
Unexpectedly this changes the scope in the pom
file from compile
to runtime
.
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
<scope>runtime</scope> <!-- compile EXPECTED ?!?! -->
</dependency>
What do I have to do to get the previous pom
back?
That is by design. The semantics of the implementation
configuration is to declare dependencies that are internal to a module. By mapping it to the runtime
scope of a Maven pom, it ensures that it doesn't leak onto the compilation classpath of consumers. This has a few advantages like being more free to swap out transitive depencies with less risk of affecting consuming modules, to make compilation faster and more.
If you need to make a transitive dependency part of the compile
scope, i.e. expose it on the compilation classpath of consuming projects, you need to use the api
configuration instead. This is available by applying the java-library
plugin.
For example (Groovy DSL):
plugins {
id 'java-library'
id 'maven-publish'
}
dependencies {
implementation 'org.apache.commons:commons-math3:3.6.1' // <- Maps to the Maven runtime scope
api 'com.google.guava:guava:30.1.1-jre' // <- Maps to the Maven compile scope
}
publishing {
publications {
maven(MavenPublication) {
groupId = 'de.mabe'; artifactId = 'project1'; version = '1.0'
from components.java
}
}
}
You can read more about the separation between API and implementation in the Gradle user guide here.