gradle: tar task not creating a tar.gz - java

Hi I have a tar task that I made after looking at numerous methods and some SO posts.
task buildDist(type: Tar, dependsOn: jar) {
print 'here'
archiveName = 'xyz-' + version
destinationDir = file('build/dist')
extension = 'tar.gz'
compression = Compression.GZIP
from 'build/libs'
include 'xyz.jar'
}
buildDist.mustRunAfter jar
I have the java plugin applied and the jar task makes the xyz.jar file available under build/libs. The build/dist directory does not exist yet, but I tried new File("build/dist") as well. That did not work either - I even pointed it to the build directory that exists - doesn't work. I run the entire script with /gradlew clean build. The print in the above code does print.

I am making a few assumptions here as you didn't post the output from running Gradle.
The build task is just a normal Gradle task that doesn't do anything by itself. Instead, it depends on other tasks. If you create your own custom task and you like to have it included when executing build, you have to add a dependency to it. If this is not the problem and you have actually done this, please give some more details as to what makes it "not work" when you run build.
If you want to test your task in isolation (e.g. to make sure it works correctly without running unit tests or whatever else that is unrelated), just run gradlew cleanBuildDist buildDist.
A note about the 'print' statement - it executes doing the configuration phase, but this doesn't mean you can use it to test if the task actually executes. In fact, it will most likely print no matter what task you execute. If you wanted to print something on execution time, you would have to put it in a doLast block.
There is a few other things you should change as well:
It is not a good practice to use relative references. Instead, use the buildDir property to get an absolute reference to the build directory.
Don't use deprecated methods like archiveName and destinationDir. Use archiveFileName and destinationDirectory instead.
The extension property is also deprecated, but it is ignored if you set the full name of the archive yourself. So just remove it. This also means you are missing the extension on the full name.
The from and include is a little fragile. Just use from jar.archivePath if you only want to gzip your application jar.
Example:
task buildDist(type: Tar, dependsOn: jar) {
archiveFileName = "${jar.baseName}-${version}.tar.gz"
destinationDirectory = file("$buildDir/dist")
compression = Compression.GZIP
from jar.archivePath
}
build.dependsOn buildDist
Lastly, if your intention is to create a distribution of your application that is runnable on its own (with all required dependencies), you should consider using the distribution plugin and perhaps also the application plugin.

Related

Izpack custom actions JAR cannot be found

I need to create an installer using gradle and izpack through gradle-izpack-plugin, but every time I run gradle build, it points out that the custom action .jar that are defined in izpack-install.xml are not being found , even though I put them in the correct folder. I have the same project written in Ant, and it works normally, but even trying to run the Ant project through gradle, it shows the same error, the same way it happens when I use the gradle-izpack-plugin. Am I doing something wrong or is there any additional configuration to be done in gradle?
build.gradle
(I can only post the tasks because its from my work)
izPackCreateInstaller.dependsOn('customActions')
izpack{
baseDir = file("target")
installFile = file('IzPack-install.xml')
outputFile = file(project.jarName)
compression = 'deflate'
compressionLevel = 9
}
task customActions(type: Copy, dependsOn: ['jar']){
duplicatesStrategy=DuplicatesStrategy.EXCLUDE
into 'bin'
into('/customActions'){
from 'build/libs'
rename('installer.jar', 'MyTestInstallerListener.jar')
}
into('/customActions'){
from 'build/libs'
rename('installer.jar', 'MyTestUninstallerListener.jar')
}
}
The error :
[org.gradle.api.internal.project.ant.AntLoggingAdapter] Couldn't load Resource bin/customActions/MyTestInstallerListener.jar
[org.gradle.api.internal.project.ant.AntLoggingAdapter] Couldn't load Resource bin/customActions/MyTestUninstallerListener.jar
directory structure
I already check and the customActions task is running before izPackCreateInstaller task

Use Scala (or java) method in Gradle build script

I have a Gradle build script which has to call a Scala (or Java) method in a Task.
currently, i have src/.../utils/lib.java
this file has a simple class with a static method that I would like to call in the build.gradle script.
but I have no idea how to import this file and use this method.
This really depends on how your gradle script is set up and what you are trying to accomplish. Without seeing it, it is hard to give a concrete all encompassing response. Here are the two most common methods I know of that would allow you to execute code in a gradle script.
1) To directly answer your response, to execute a static java method, it needs to be compiled first. If the rest of your build requires this to be executed, then you would need to structure this as a multi-project build.
https://docs.gradle.org/current/userguide/multi_project_builds.html
Assuming you have
apply plugin: 'java'
You would then be able to create a jar with the class containing your static method, and create a task that you can execute of type Exec or JavaExec that would execute this jar.
2) The easier and less complex approach:
Since gradle allows you to directly execute groovy code, if possible, I would try to move the logic from the static method into the gradle file. You can reference Objects and methods on the org.gradle.api to customize a lot of build actions.
https://docs.gradle.org/current/javadoc/
Here is an example from my build.gradle use to copy resources files after a compile step into the build directory before it is packaged into a jar.
compileJava {
doLast {
def f = file("src/main/java/resources/db/migration")
println "Copying SQL from {$f} to {$buildDir/db/migration}"
copy {
from file(f)
into file("$buildDir/db/migration")
include('*.sql')
}
}
}
This may not be the easy solution that you were looking for but I hope it gives you some good guidance.

Gradle: Multi-project dependency: Tasks of the same name executing together

I have a multi-project dependency in my gradle build, but there's a feature that's somewhat in my way. Whenever I call a task name that exists in both projects, it calls them both. I don't like that.
My directory structure is as follows:
[Root]
---->[projA]
----------->build.gradle
---->[projB]
----------->build.gradle
So I have projB dependent on projA in my code.
Say I have a task run in projB:
task run << {
println 'projB running'
}
And I also have a task run in projA:
task run << {
println 'projA running'
}
By calling gradle run, I would get
:run
projB running
:projA:run
projA running
Is there any way to prevent some of the tasks from having this dependency? Some of them, say clean is fine, but I'd prefer to have specific tasks separate (without having to change the naming scheme).
The equivalent of what I want can be achieved by doing either:
gradle run -x :projA:run
or
gradle :run
I want a solution that is within the build file, though.
Thanks!
That fact that projB declares a project dependency on projA is irrelevant for the behavior you are seeing. If you execute a task from the root project of a multi-project build Gradle will try to find the task in any of its subprojects with the requested name and execute it. This feature is called task execution matching. Given this default behavior there's no way Gradle could know which run task you mean when executing gradle run from the root project. I'd suggest you define what you want to execute on the command line as mentioned in my previous comment.
If you really wanted to add logic to your build script, then you could achieve it with the following code:
def taskRequests = gradle.startParameter.taskRequests
def runTaskRequest = taskRequests.find { it.args.contains('run') }
if (runTaskRequest) {
gradle.startParameter.excludedTaskNames = [':projA:run']
}
The code provided would prevent the execution of the run task for the subproject projA if you execute the command gradle run. Keep in mind that it would also exclude :projA:run if you navigate to the projA subdirectory and run the same command. If you still want to be able to execute the run task from the subdirectory, then you'll have to build in additional logic.

Perform an action on each file during installApp phase of Gradle build

Here is a minimal build.gradle file I'm using.
apply plugin: 'application'
installApp {
eachFile {
println "$it.name"
loadProperties(it)
}
}
I'm trying to load properties into some placeholders in a properties file located in src/dist/bin. This technique works fine if the properties file is in src/main/resources and I replace installApp with processResources which I am doing in another project within the build.
The println isn't printing anything so it makes sense the placeholders aren't replaced but I don't understand why it's not iterating through all the files the installApp task is copying.
Running this as ./gradlew clean installApp using gradle 1.10.
It appears that the installApp task doesn't run closure passed to the eachFile function. Here is a complete build.gradle file that demonstrates this behavior
apply plugin: "application"
mainClassName = "test.Test"
installApp {
eachFile {
println "$it.name"
}
}
I run gradle clean installApp -i
and around the installApp section get
:installApp (Thread[main,5,main]) started.
:installApp
Executing task ':installApp' (up-to-date check took 0.011 secs) due to:
Output file /Users/joshbrackett/Documents/workspace/gtest/build/install/gtest has changed.
Output file /Users/joshbrackett/Documents/workspace/gtest/build/install/gtest/bin/gtest has been removed.
Output file /Users/joshbrackett/Documents/workspace/gtest/build/install/gtest/lib/gtest.jar has been removed.
:installApp (Thread[main,5,main]) completed. Took 0.748 secs.
I have replicated your issue. I suspect this is a bug. While we investigate further, here is a workaround that worked for me.
make your eachFile call on the applicationDistribution copySpec rather than the installApp task.
applicationDistribution.eachFile {
println "$it.name"
}
I suspect that this is what you want to do anyway, since then it will also be used by the dist tasks.
BTW you may also find that the expand method is of interest http://www.gradle.org/docs/current/javadoc/org/gradle/api/file/CopySpec.html#expand(java.util.Map)
This has changed again in Gradle 2.3 apparently. Now using applicationDistribution doesn't work and you need to use installDist instead.

Copy file from a jar in a custom gradle plugin

I write a custom gradle plugin where I would like to copy a specific file from a jar inside the classpath into the buildDir. I played around in a sandbox project and got this solution working:
task copyFile(type: Copy) {
from zipTree(project.configurations.compile.filter{it.name.startsWith('spring-webmvc')}.singleFile)
include "overview.html"
into project.buildDir
}
but if copy it into my plugin:
project.task(type: Copy, "copyFile") {
from zipTree(project.configurations.compile.filter{it.name.startsWith('spring-webmvc')}.singleFile)
include "overview.html"
into project.buildDir
}
I got the error:
* What went wrong:
A problem occurred evaluating root project 'gradle-springdoc-plugin-test'.
> Could not find method zipTree() for arguments [/Users/blackhacker/.gradle/caches/artifacts-26/filestore/org.springframework/spring-webmvc/4.0.0.RELEASE/jar/a82202c4d09d684a8d52ade479c0e508d904700b/spring-webmvc-4.0.0.RELEASE.jar] on task ':copyFile'.
The result of
println project.configurations.compile.filter{it.name.startsWith('spring-webmvc')}.singleFile.class
is
class java.io.File
What I am doing wrong?
Unlike a build script, a plugin does not have an implicit project context (unless you give it one). Hence you'll have to use project.task rather than task, project.zipTree rather than zipTree, project.file rather than file, etc.
PS: In your case, it's important to use project.zipTree { ... } (note the curly braces) to defer searching for the file until the Zip contents are actually requested. Otherwise you risk slowing down each build invocation (even ones that never execute copyFile) and, if the file is being produced by the same build, even build failures (because the configuration is resolved before the file has been added).

Categories