Hi All
I have a weird requirement. I have looking into generating secondary JARs from a single Gradle project. I have written a Gradle task that perform this task.
Unfortunately this secondary JAR requires a slightly different Manifest and the only idea I have to unpack the primary JAR and rebuild it again in a second module. This is because the second JAR must also have a different GAV coordinate.
Suppose, I have
acme-core/build.gradle
acme-core/src/main/java/uk/gov/acme /*Java source code*/
acme-core/acme-core.jar /* is the primary JAR */
acme-core/acme-core-client.jar /* is the secondary JAR (alternative manifest and same source file) */
Now I believe the best way is to split this build.gradle
into two separate modules and therefore Gradle will understand the different GAVs.
Build the primary Jar
acme-core/build.gradle /* acme-core:1.0 */
acme-core/src/main/java/uk/gov/acme
Build the second Jar
acme-core-client/build.gradle /* acme-core-client:1.0 */
acme-core-client/build/unzip-dependency
The secondary build file will have a runtime dependency, because there is no source code to compile.
runtime "acme:acme-core:1.0"
In order to write the single task in the secondary gradle file, I want to know how to find the primary dependency artifact and then unzip it to a folder build/unzip-dependency
, then I can re-JAR it as the secondary artifact.
Thoughts?
PS: I also tried to answer this stack overflow question: http://stackoverflow.com/questions/20008324/gradle-multiple-jars-from-single-source-folder/30477258#30477258
If you want to create another jar with just a different manifest you can do that in a single project.
task clientJar(type: Jar) {
appendix = 'client'
from sourceSets.main.output
manifest {
// configure the manifest
}
}
If you want to publish that other Jar with a unique GAV you’ll want to create a separate publication for it.
Yes Mark you are correct there.
If your second JAR is also dependency somewhere else in the multi-module Gradle then YMMV.
My solution was to create a parallel or separate module acme-core-client
.
In this build.gradle
, create a task to find the dependency from the classpath and unzip it. Remove the offending MANIFEST.MF with the `Class-Path’ property. Add new entries to the distributon using some other private client specific tasks.
task repack {
ext.unzipDir = "build/unzip-dependency"
outputs.file unzipDir
doLast {
def dependencyFiles = configurations.runtime.findAll { File file ->
if (file.getName().startsWith("acme-core-${version}")) {
logger.info( "**** Found the dependency file: [" + file.getName() + "]" )
file
}
}
def dependencyFile = dependencyFiles[0]
ant.mkdir( dir: unzipDir )
ant.unzip( src: dependencyFile, dest: unzipDir )
ant.delete( file: "$unzipDir/META-INF/MANIFEST.MF")
/* Bring in other stuff */
}
}
(PS: Raise a GradleException if you don’t find the dependency)
With the exploded directory, we then simply JAR this up with a new manifest
jar {
manifest {
attributes(
"Main-Class": platformMainClass,
"Implementation-Title": platformDisplayName,
"Implementation-Description": platformDescription,
"Implementation-Version": version,
"Implementation-Type": "CLIENT",
)
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from 'build/unzip-dependency'
include '**/*'
exclude( [ 'log4j*.properties', 'acme/private/**' ])
}
Make sure the JAR task depends on the repack task.
jar.dependsOn(repack)
At least now, we have a real dependency u.gov.acme:acme-core-client:1.0
and this works for the other project modules.