Reputation: 764
I'm new to Gradle and Groovy, and I'd hope there would be something to solve my problem.
I have several packages, each of which needs to be compiled into one jar.
One solution I've found is to create multiple tasks that are of Jar
type, but I'd like to avoid copy/paste and end up with a giant gradle file whenever I add a new package to my project.
My current implementation is to have multiple jar tasks, like this one :
task jarFoo(type: Jar) {
baseName = "foo"
version = "1.0.0"
String className = baseName.capitalize()
from(sourceSets.main.output) {
include "$baseName/**"
}
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes "Implementation-Title": "$className",
"Implementation-Version": "$version",
"Main-Class": "$baseName.$className"
}
}
It works like a charm, however I add packages very often and I will end up with a lot of packages, therefore a lot of tasks and a lot of copied/pasted code.
After fiddling with build.gradle
file, I've found that I needed to extend from Jar
in order to get a jar created.
So here's the code for the class so far :
class JarTask extends Jar {
String jarName = "default"
String jarVersion = "1.0.0"
@TaskAction
def jar() {
baseName = jarName
version = jarVersion
String className = baseName.capitalize()
// Thanks Opal for reminding that sourceSets
// is defined in project.
from(project.sourceSets.main.output) {
include "$baseName/**"
}
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes "Implementation-Title": "$className",
"Implementation-Version": "$version",
"Main-Class": "$baseName.$className"
}
}
}
task jarFoo(type: JarTask) {
jarName = "foo"
}
task jarBar(type: JarTask) {
jarName = "bar"
jarVersion = "1.2.42"
}
The problem is that the jar that is created ignores basically everything in the method: it contains only a MANIFEST.MF
containing one line with the manifest version and is given the name of the project, not the name given in task. Nothing else.
If needed, you can find the code online in my GitHub repo (mainly in French).
Any idea would be truly appreciated!
Upvotes: 2
Views: 5963
Reputation: 764
Here is another easier option that allows to pass parameters. I found the inspiration on this topic : https://discuss.gradle.org/t/passing-arguments-to-a-task/8427/20, which sounds exactly like what I was trying to do.
Here we basically define a method that returns a task, given some parameters. The rest is just testing if a version is given, or the code already given in question and adapted with @Opal great help.
It is sufficient to include the new builds in the artifacts
block to make tasks available. Then, just run gradle jarqcm
to build a single package or gradle assemble
to compile everything.
apply plugin: "idea"
apply plugin: "java"
repositories {
mavenCentral()
}
dependencies {
compile "com.intellij:forms_rt:7.0.3"
runtime "com.intellij:forms_rt:7.0.3"
}
def jarPackage(artifactName, artifactVersion) {
if (artifactVersion == "" || artifactVersion == null) {
artifactVersion = "1.0.0"
}
return tasks.create("jar${artifactName}", Jar) {
baseName = artifactName
version = artifactVersion
String className = baseName.capitalize()
from(sourceSets.main.output) {
include "$baseName/**"
}
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes "Implementation-Title": "$className",
"Implementation-Version": "$version",
"Main-Class": "$baseName.$className"
}
}
}
artifacts {
archives jarPackage("aleatoire", ""), jarPackage("calculatrice", "1.2.3"), jarPackage("copier", ""),
jarPackage("qcm", "1.0.0")
}
Upvotes: 2
Reputation: 84776
After you edited the question is easy. There's no property sourceSets
for the given task (Jar
in this case). sourceSets
are defined on Project
and every task that extends DefaultTask
inherits project
field from it's parent. So you just need:
from(project.sourceSets.main.output) {
include "$baseName/**"
}
ANSWER
I hope you understand the difference between task configuration and execution phase. This is the problem that occurs here. Basically you extended Jar
task which as all tasks of type Copy
is not designed to be extended - see here. In task action you configure the artifacts to be copied but.. there's too late for configuration - it's execution phase. To solve the problem task rules may be used. I've modified the script and it's:
apply plugin: "idea"
apply plugin: "java"
repositories {
mavenCentral()
}
dependencies {
compile "com.intellij:forms_rt:7.0.3"
runtime "com.intellij:forms_rt:7.0.3"
}
tasks.addRule('Pattern: build<ID>') { String taskName ->
if (taskName.startsWith('build')) {
task(taskName, type: Jar) {
baseName = taskName - 'build'
version = '1.0.0'
String className = baseName.capitalize()
from(sourceSets.main.output) {
include "$baseName/**"
}
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes "Implementation-Title": "$className",
"Implementation-Version": "$version",
"Main-Class": "$baseName.$className"
}
}
}
}
artifacts {
archives project.tasks['buildqcm'], project.tasks['buildlistage'] //etc
}
and should invoked simply with gradle buildlistage buildqcm
. You can make additional validation to check if <ID>
passed is on the list of packages e.g. Hope that helps and sorry for having to wait so long :/
Upvotes: 1