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

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.

Related

gradle: tar task not creating a tar.gz

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.

run checkstyles in subprojects before all tests in all subprojects

I have gradle project with 4 subprojects. I have current root gradle.build with checkstyle:
allprojects {
apply plugin: "checkstyle"
checkstyle {
...
}
}
so when I run ./gradlew build in the main folder, I get next:
checkstyle for 1st subproject, then tests. Then it runs checkstyle for 2nd subproject and then tests for 2nd, etc.
The problem is: if I have long tests in 1st subproject, I can wait a lot of time, and then discover that I have 2 spaces in the 4th project, so checkstyle fails, but I was waiting so much time for it.
What I really want:
run all checks (checkstyle, and I have pmd too) for all subprojects, and then run all tests in all subprojects. It will save a lot of time for everybody in the team.
Can I do it except, make 2 different pipelines, and run them separately? like: ./gradlew allMyCheckstyles && ./gradlew build.
I would love to use just ./gradlew build
Thanks!
I tried many dependsOn, runAfter, but it didn't work out.
Apologies, a previous version of this answer misinterpreted the requirements of this question.
Here's a solution that should do what you want:
// Create a lifecycle task in the root project.
// We'll make this depend on all checkstyle tasks from subprojects (see below)
def checkstyleAllTask = task("checkstyleAll")
// Make 'check' task depend on our new lifecycle task
check.dependsOn(checkstyleAllTask)
allProjects {
// Ensure all checkstyle tasks are a dependency of the "checkstyleAll" task
checkstyleAllTask.dependsOn(tasks.withType(Checkstyle))
tasks.withType(Test) {
// Indicate that testing tasks should run after the "checkstyleAll" task
shouldRunAfter(checkstyleAllTask)
// Indicate that testing tasks should run after any checksytle tasks.
// This is useful for when you only want to run an individual
// subproject's checks (e.g. ./gradlew ::subprojA::check)
shouldRunAfter(tasks.withType(Checkstyle))
}
}
Documentation here and here

Gradle: How to run build in user defined task?

i would like to run the build-task from the gradle war plugin inside one of my own defined tasks. I tried various things, but nothing worked.
This is how my task looks at the moment:
task deploy << {
build.execute()
copy {
from '/build/libs/app.war'
into tomcat_webapps
}
}
When i run
gradle deploy
the build task will not be executed. Does anyone of you know how i can do this?
Thank you!
Calling tasks manually should be your very last resort. The gradle way would be to define a dependency between your task and the build task. This way gradle can determine a proper order for the tasks that need to be executed.
Setting up the dependency can be done in several ways. One way would be this:
task deploy(type: Copy) {
dependsOn build
from '/build/libs/app.war'
into tomcat_webapps
}

With Gradle 2.12 (for Java), how can download source files if and only if 'build'?

I want to make a gradle script which downloads source code via internet when and only when you build (e.g. not when you 'gradle claen').
I can basically make it possible and the downloading is done only there is no directory 'src'. If I make a task that downloads the source codes, then maybe the downloading is not done when you 'gradle clean'.
but I want to make the script download the codes when you 'gradle build'
thats why I write scripts which downloads the codes in ccompileJava...
but If I do so, if you do 'gradle clean' when you have no a directory 'src',
gradle downloads the codes and then deletes it...
How can I make a script satisfying my wish...?
below is the script part related to the question.
compileJava {
if (!new File('src').exists()){
tasks.downloadZipFile.execute()
tasks.downloadAndUnzipFile.execute()
file('downloaded/src').renameTo('src')
delete 'downloaded'
}
}
clean { delete 'src' }
Your code executes during the configuration phase. So it's executed whatever task you execute.
It should instead execute in the execution phase, once gradle has decided which tasks to run, in which order. Create a task, and make compileJava depend on that task, since it must execute before compileJava:
task downloadSources << {
...
}
compileJava {
dependsOn downloadSources
}
Note the << in downloadSources. That means that the closure following is executed as part of the task execution, and not as part of its configuration.

How do I add a task to main 'build' task in gradle

When I try to add a task to the main build task with the following code:
rootProject.tasks.getByName('build').dependsOn mytask
It complains when I run gradle(w) build with the output:
* Where:
Build file '...' line
: ...
* What went wrong:
A problem occurred evaluating project ':myapp'.
> Task with name 'build' not found in root project 'main'.
how do i add the task to the build task?
The problem is that your build has no build task, at least at the time when above line gets evaluated. Usually, the build task gets added by the java-base plugin, which in turns gets applied by plugins such as java, groovy, or scala. So make sure to apply one of these plugins first. Or, if you don't use any of them, declare your own build task.

Categories