Execute one gradle task - gradle

I've this two tasks:
war {
webInf { from 'src/main/resources/WEB-INF' }
manifest {
attributes 'Implementation-Version': versioning.info.display
}
}
task createDemoWar(type: War, dependsOn: classes) {
archiveName "webapi-demo-${versioning.info.display}.war"
destinationDir = file("$buildDir/dist")
copy {
from 'scopes'
include 'configuration.demo.properties'
into 'src/main/resources/'
}
}
task createDevelopmentWar(type: War, dependsOn: classes) {
archiveName "webapi-dev-${versioning.info.display}.war"
destinationDir = file("$buildDir/dist")
copy {
from 'scopes/'
include 'configuration.development.properties'
into 'src/main/resources/'
}
}
Both tasks are trying to copy a property file fromscopes folder to src/main/resources/ folder.
I only run one task, however two files are copied in src/main/resources/ (configuration.demo.properties and configuration.development,properties.
Any ideas?

You use two copy specifications at the configuration phase (note, copy specification in that case doesn't configure your task, but add some extra action to it's configuration). That means, your files are getting copied during configuration. That's all because of this:
copy {
...
}
You have to run it during execution, to do that, try to move it into the doLast or doFirst closure, like so (for both tasks):
task createDemoWar(type: War, dependsOn: classes) {
archiveName "webapi-demo-${versioning.info.display}.war"
destinationDir = file("$buildDir/dist")
doFirst {
copy {
from 'scopes'
include 'configuration.demo.properties'
into 'src/main/resources/'
}
}
}
In that case, files will be copied only if task will be executed, right before the execution.

Related

Gradle JAR Creation Timing

i have a gradle build that retrieves properties file and such that are remote (to keep passwords out of github) but the remote retrieval doesn't complete by the time the JAR is built.
i figured i either had to get the JAR created in the execution phase instead of configuration phase or add the remote files in the execution phase but i couldn't get either working.
any suggestions?
task fatJar(type: Jar) {
doFirst {
exec {
executable './scripts/getRemoteResources.sh'
}
}
...
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)
}
//some resources are retrieved remotely & b/c of timing they don't get included here
from ('src/main/java/resources') {
include '*'
}
with jar
//tried this but doesn't work
//doLast {
// jar {
// from ('src/main/java/resources') {
// include '*'
// }
// }
//}
}
You shouldn't use the task graph for this. Also you shouldn't download the file to src/main/
Instead, you should
Create a task to download the remote resources to a directory under $buildDir (so it's cleaned via the "clean" task)
Configure the TaskOutputs so that the result can be cached and re-used.
Wire the task into Gradle's DAG
Add the directory to the "processResources" task so it ends up on the runtime classpath (ie in the jar)
Eg:
tasks.register('remoteResources', Exec) {
inputs.property('environment', project.property('env')) // this assumes there's a project property named 'env'
outputs.dir "$buildDir/remoteResources" // point 2 (above)
commandLine = [
'./scripts/getRemoteResources.sh',
'--environment', project.property('env'),
'--outputdir', "$buildDir/remoteResources"
]
doFirst {
delete "$buildDir/remoteResources"
mkdir "$buildDir/remoteResources"
}
}
processResources {
from tasks.remoteResources // points 3 & 4 (above)
}
See The Java Plugin - Tasks
processResources — Copy
Copies production resources into the production resources directory.
this seems to work so i'm going with it unless someone has a better solution...
gradle.taskGraph.beforeTask { Task task ->
println "just before $task.name"
// i just chose to kick this off with the first task sent through here
if (task.name=="compileJava") {
exec {
executable './scripts/getRemoteResources.sh'
}
}
}
task fatJar(type: Jar) {
...
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)
}
from ('src/main/java/resources') {
include '*'
}
with jar
}

Using a gradle task generate a properties file to be included in a jar before the jar task is executed

Before is a snippet of my build.gradle, it lists a series of tasks which should ideally be run in the following order:
createPropertiesFile
jar
obfuscate
deleteNonObfuscatedJar
deletePropertiesFile
I need createPropertiesFile to run before jar, as users are building the .jar using ./gradlew jar.
The problem I'm seeing at the moment is this error:
> Could not find method doFirst() for arguments [task ':createAuthenticationPropertiesFile']
on task ':jar' of type org.gradle.api.tasks.bundling.Jar.
I've also tried jar.dependsOn(project.tasks.createAuthenticationPropertiesFile) but I've seen that custom.properties is not included in the generated .jar when using jar.dependsOn
build.gradle:
nonObfuscatedJar = 'appNotObfuscated.jar'
task createPropertiesFile << {
def props = project.file('src/main/resources/custom.properties')
props << 'prop1=value1'
}
jar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
archiveName = "$nonObfuscatedJar"
from sourceSets.main.output.classesDir
from configurations.compileOnly.asFileTree.files.collect { zipTree(it) }
include '**/*.class'
include '**/custom.properties'
manifest {
attributes 'Main-Class': 'com.bobbyrne01.App'
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}
task obfuscate(type: proguard.gradle.ProGuardTask) {
configuration 'proguard.txt'
injars "$libsDir/$nonObfuscatedJar"
outjars "$libsDir/app.jar"
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
}
task deleteNonObfuscatedJar (type: Delete) {
delete "$libsDir/$nonObfuscatedJar"
}
task deletePropertiesFile (type: Delete) {
delete project.file('src/main/resources/custom.properties')
}
jar.doFirst(project.tasks.createPropertiesFile)
jar.finalizedBy(project.tasks.obfuscate)
jar.finalizedBy(project.tasks.deleteNonObfuscatedJar)
jar.finalizedBy(project.tasks.deletePropertiesFile)
As a workaround, move the properties file creation to the start of the jar task:
jar {
// Create properties file
def props = project.file('src/main/resources/custom.properties')
props << 'prop1=value1'
// Build jar
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
archiveName = "$nonObfuscatedJar"
from sourceSets.main.output.classesDir
from configurations.compileOnly.asFileTree.files.collect { zipTree(it) }
include '**/*.class'
include '**/custom.properties'
manifest {
attributes 'Main-Class': 'com.bobbyrne01.App'
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}

Use gradle to build a jarfile from other jarfiles

I have what should be a simple problem: I have a directory full of jarfiles, and I want to use gradle (v4.4.1) to combine the contents of these jarfiles into a single jarfile (i.e., when I do jar tf big-jar.jar, I want to see a bunch of classes, not a bunch of jars). I tried the following:
task bigJar(type: Jar) {
inputs.dir "$distLibsJar"
outputs.file "$distDir/big-jar.jar"
destinationDir = file("$distDir")
baseName = "big-jar"
from("$distLibsDir")
}
but this produces a jarfile with other jars as its contents rather than the contents of those other jars as the contents of the combined jar.
Any ideas? Thanks...
In this case best way to proceed is with a shadow jar. for this you can have this kind of configuration in build.gradle .posting some sample
apply plugin: 'com.github.johnrengelman.shadow'
shadowJar {
zip64 true
//classifier "shadow" can be mentioned according to need
mergeServiceFiles()
artifacts {
shadow(tasks.shadowJar.archivePath) {
builtBy shadowJar
}
}
}
artifacts {
archives shadowJar
}
distZip {
dependsOn shadowJar
//appendix='software'
eachFile { file ->
String path = file.relativePath
file.setPath(path.substring(path.indexOf("/")+1,path.length()))
}
doLast{
//operation to perform
}
}
distributions {
main {
contents {
//from and to can be mentioned here
}
}
}
hope it helps

How to collect javadoc jars into a zip file

For a multi-project Gradle project, foo, bar and baz. I'm trying to create a task which creates a zip file with both libraries and javadoc, i.e. foo.jar, AND foo-javadoc.jar..
./build.gradle
./settings.gradle
./foo/build.gradle
./bar/build.gradle
./baz/build.gradle
settings.gradle
include ":foo"
include ":bar"
include ":baz"
Top level build
allprojects {
apply plugin: 'java'
task generateJavadoc (type : Javadoc) {
source = sourceSets.main.allJava
classpath = sourceSets.main.compileClasspath
failOnError = false
}
task javadocJar(type: Jar, dependsOn: generateJavadoc) {
classifier = 'javadoc'
from generateJavadoc.destinationDir
}
artifacts {
archives javadocJar
}
}
task buildZip(type: Zip, dependsOn: build) {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from (project(':foo').configurations.runtime) {
into 'jars'
}
from (project (':foo').configurations.archives.all) {
into 'jars'
}
}
When I invoke this with gradle clean buildZip a zip file is created, but without the any -javadoc JARs I was expecting... The JavaDoc jars are generated into the project build directories, e.g. foo/build/lib/foo-javadoc.jar I've tried multiple combinations of from project (':foo').artifacts etc.
This is possible using the following. Note javadocJar is the name of the task defined in the allprojects block
from (rootProject.allprojects.javadocJar.outputs) {
into 'javadoc'
}

Is there a way to "merge" gradle tasks to avoid many dependsOn declarations

Suppose this gradle script:
task copyGroovyScript(dependsOn: prepare, type: Copy) {
from "${scriptSrcLocation}/${scriptSrcName}"
into buildFolderZipSource
}
task copyDependenciesForGroovyScript(dependsOn: copyGroovyScript, type: Copy) {
from configurations.groovyScript.resolve()
into "${buildFolderZipSource}/groovy-plugin-lib"
}
task copyTestScripts(dependsOn: copyDependenciesForGroovyScript, type: Copy ) {
from "${scriptSrcLocation}/ReadClient.groovy"
into "${buildFolderZipSource}/test"
}
task copyTestScriptsBin(dependsOn: copyTestScripts, type: Copy ) {
from "${scriptSrcLocation}/bin"
into "${buildFolderZipSource}/test/bin"
}
task copyDependenciesForTestScripts(dependsOn: copyTestScriptsBin, type: Copy) {
from configurations.testScripts.resolve()
into "${buildFolderZipSource}/test/lib"
}
task packageAll(dependsOn: copyDependenciesForTestScripts, type:Zip) {
archiveName "output-${buildTime()}.zip"
excludes ['*.zip']
destinationDir buildFolder
from buildFolder
}
I need different Copy tasks before they have different output folders.
Is there a way to avoid having to have all those dependsOn statements and just have gradle execute things in order of declaration in the file somehow?
There's no way to execute in the way it's declared. But why don't you go this way:
task packageAll(dependsOn: copyDependenciesForTestScripts, type:Zip) {
doFirst {
copy {
from "${scriptSrcLocation}/${scriptSrcName}"
into buildFolderZipSource
}
}
//following doFirst and so on..
archiveName "output-${buildTime()}.zip"
excludes ['*.zip']
destinationDir buildFolder
from buildFolder
}
EDIT
After discussion in comments it turned out that the following piece of code should do the job
task prepare {
doFirst {
copy {
from "${scriptSrcLocation}/${scriptSrcName}"
into buildFolderZipSource
}
}
//following doFirst and so on..
}
task packageAll(dependsOn: prepare, type:Zip) {
archiveName "output-${buildTime()}.zip"
excludes ['*.zip']
destinationDir buildFolder
from buildFolder
}

Resources