Reputation: 4555
I have this multi-module project structure
proj
├── subprojA
└── subprojB [depends on subprojA]
Both subprojects are producing a java jar each. I want to do an extra publishing step where the 2 subproject jars would be given version "1.0.0-dev" and they would be pushed to MavenLocal.
It was relatively easy to publish using a new "publication" entity as these are designed to be able to override the project version (not shown, an additional trick to make each publication go to only their respective repo):
devlocal(MavenPublication) {
from components.java
version "1.0.0-dev"
alias true // prevents error "Publishing is not able to resolve a dependency on a project with multiple publications that have different coordinates"
}
However - you guessed it - there is a problem with this. The new publication is "dumb" in the sense that subprojB would depend on the wrong version of subprojA - i.e. the actual project version not 1.0.0-dev
. I want the extra publication jars to depend on one-another.
I discover this is not trivial, there are 2 approaches:
configuration
which declares dependencies with the right version 1.0.0-dev and is published as-is, however while this might be conceptually more natural, is likely even harder because it takes a Gradle artist to avoid the duplication of dependency declarations and putting together the publication, which is not as simple as "from components.java"
.Which option is better and can anyone point to an example for either?
Edit: I did find an example for approach #1 here but after implementing it I realise it's not enough, as it only changes POM metadata whereas Gradle uses "Gradle module metadata". Not so lucky to find the same tweaks for Module metadata.
Upvotes: 5
Views: 2846
Reputation: 656
Faced the same problem, I have a common project named Commun used by project A.
and this solved my problem :
tasks.withType(GenerateModuleMetadata) {
enabled = false
}
When you declare this dependency in your build.gradle like this :
implementation (group: 'com.example', name: 'common', version: "${commonVersion}")
You always download the jar in you repository (Maven in your case).
If you want to have the flexibility between Local environement and Production, so that when you update the common library you can use it directly in project A without publishing it you can do this :
in the build.gradle :
dependencies {
// Common
if (project.hasProperty("production")) {
implementation (group: 'com.example', name: 'common', version: "${commonVersion}")
} else {
implementation group: 'com.example', name: 'common'
}
}
in your settings.gradle :
rootProject.name = 'projectA'
if (startParameter.projectProperties.get("production") == null) {
includeBuild "../common"
}
don't forget to update the buil task in production environement :
./gradlew clean build -Pproduction=true
Upvotes: 1
Reputation: 4555
After much fighting with Gradle it turns out approach #1 requires to switch off "gradle module metadata" and have publication only publish POM files, which can be hacked to contain the right version for the deps. Starting Gradle 6, by default Gradle's own metadata is used instead of POM, which is retained for Maven interoperability. But this metadata seemingly cannot be edited during publication (it can only be edited during resolution in client projects - see this). So the (suboptimal) solution for now is to hack the POM like here and disable Gradle module metadata like this:
tasks.withType(GenerateModuleMetadata) {
enabled = false
}
Upvotes: 2