gradle access another project - gradle

I have 2 gradle projects. Lets say projectA and projectB. I need to create a task in projectA, which can execute a task in projectB. I tried with many ways, but i couldn't find a way to do that. Consider following code,
//ProjectA build.gradle
task taskA(dependsOn: ProjectB.taskB) << { println "executed taskB" }
//ProjectB build.gradle
task taskB() << { println "executing taskB"}
when I run taskA output should be,
>> gradle taskA
executing taskB
executed taskB
Can I anyhow achieve this?
thanks.

task taskA(dependsOn: project(":ProjectB").taskB)
We don't say that taskA executes taskB but that it depends on taskB.

Related

Gradle task dependsOn already executed task

If taskB depends on taskA, when I execute task A and then taskB...
Question 1: Is taskA executed just once?
Question 2: Is it executed when I run taskA or when I run taskB?
Each Gradle task will only be executed once in a build (Gradle invocation).
Also, the task order you pass to Gradle will only be maintained, if there are no dependencies between them:
If you call gradle taskA taskB, but taskA.dependsOn taskB, taskB will be executed before taskA.

What's the difference between mustRunAfter and dependsOn in Gradle?

Whether taskB mustRunAfter taskA, or taskB dependsOn taskA, it seems that taskA runs first, then taskB runs. What's the difference?
For example:
tasks.create('a')
tasks.create('b').dependsOn('a')
tasks.create('c')
tasks.create('d').mustRunAfter('c')
dependsOn - sets task dependencies. Executing b here would require that a be executed first.
mustRunAfter - sets task ordering. Executing d does not require c. But, when both c and d are included, c will execute before d.
Where possible, declare task inputs instead of task dependencies. That said, expanding on mkobit's answer:
Ordering and dependencies involving two tasks
mustRunAfter
mustRunAfter controls the execution order of tasks explicitly specified on the command line, but doesn't create implicit dependencies on other tasks. Given taskA and taskB:
build.gradle.kts
val taskA by tasks.registering {
doLast {
println("taskA")
}
}
val taskB by tasks.registering {
doLast {
println("taskB")
}
}
taskB {
mustRunAfter(taskA)
}
then
gradle taskB taskA executes taskA followed by taskB;
gradle taskA executes taskA only;
gradle taskB executes taskB only.
dependsOn
dependsOn creates implicit dependencies on other tasks. Given the same two tasks:
taskB {
dependsOn(taskA)
}
then
gradle taskB executes taskA followed by taskB;
gradle taskB taskA executes taskA followed by taskB;
gradle taskA executes taskA only.
Ordering and dependencies involving three tasks
mustRunAfter and dependsOn accept an unordered collection of tasks. Given:
val taskC by tasks.registering {
doLast {
println("taskC")
}
}
taskC {
dependsOn(taskA, taskB)
}
then gradle taskC executes taskA and taskB in no guaranteed order, followed by taskC (assuming no other dependsOn or mustRunAfter declarations).
mustRunAfter also controls the execution order between interdependent tasks that would otherwise have no guaranteed order. Given:
taskB {
mustRunAfter(taskA)
}
then gradle taskC executes taskA followed by taskB followed by taskC, but gradle taskB only runs taskA because taskB does not dependOn(taskA).
Other types of task dependency
taskA { finalizedBy(taskB) } ensures gradle taskA executes taskA followed by taskB;
shouldRunAfter provides weaker ordering guarantees than mustRunAfter, useful for breaking cyclic dependencies and parallel task execution.
Further reading
Consult the Gradle documentation for more information on:
adding dependencies to tasks
ordering tasks
skipping tasks
Sometimes they have the same effect. For example, if taskC dependsOn taskA and taskB, then it doesn't matter whether taskB dependsOn taskA or mustRunAfter it - when you run taskC, the order will be taskA, taskB, taskC.
But if taskC dependsOn taskB only, then there's a difference. If taskB dependsOn taskA, then it's the same as above - taskA, taskB, taskC. If taskB merely mustRunAfter taskA, then taskA doesn't run, and running taskC will run taskB, then taskC.
mustRunAfter really means if taskA runs at all, then taskB must run after it.
Generally, if order is important, it appears that you need both dependsOn and mustRunAfter. Here is an example of running two tasks, one (custom registered "importUnicodeFiles" task) that is in "this" project and one (predefined "run" task) that is in a sibling project named ":unicode":
tasks.register("rebuildUnicodeFiles") {
description = "Force the rebuild of the `./src/main/resources/text` data"
val make = project(":unicode").tasks["run"]
val copy = tasks["importUnicodeFiles"]
dependsOn(make)
dependsOn(copy)
copy.mustRunAfter(make)
}

Gradle - run testReport task after test phase of all submodules

I have a simple project with subprojects and I want to generate aggregate report for all tests when I execute gradle test command.
I have followed the gradle documentation and added following:
task testReport(type: TestReport) {
// make sure this task is run after all subproject test tasks
mustRunAfter subprojects*.test
destinationDir = file("$buildDir/reports/allTests")
// Include the results from the `test` task in all subprojects
reportOn subprojects*.test
}
This works when I execute gradle test testReport, but when I execute gradle test or gradle build in the root project - the task testReport is not run.
How do make gradle to run the task without specifying it every time?
Add: test.finalizedBy 'testReport' to your build.gradle; just at the root level, doesn't have to be inside any closure.
taskX.finalizedBy taskY
Will run taskY everytime taskX completes execution successfully.

Gradle task at the end of build with a multiproject build

I am attempting to create my own task, that will create a package of all the artifacts generated during my multi-project build.
Currently what I do right is now just:
gradle build createPackage
Which gives output like the following:
:test-utility:compileJava UP-TO-DATE
:test-utility:processResources UP-TO-DATE
...
:test-utility:check UP-TO-DATE
:test-utility:build UP-TO-DATE
Creating Package...
Created.
BUILD SUCCESSFUL
Total time: 4.654 secs
With the createPackage task being:
task createPackage {
println "Creating Package..."
println "Created."
}
However, I would like to simply it by running just one command, so what would the best way to do this and ensure the order stays maintained?
Ideally I would like to call build within the createPackage task or append to the build task with my task.
Ok reading between the lines there are a few things to clear up
1) Your printlns are being run in the configuration phase, not the execution phase. See http://www.gradle.org/docs/current/userguide/build_lifecycle.html for more info.
2) You do not have a single 'build' task. gradle build on the command line will run the 'build' task of each of your subprojects. Your package task would need to depend on all of them. Something like..
apply plugin: 'java'
evaluationDependsOnChildren()
task createPackage(type:Zip) {
dependsOn subprojects*.build
}
3) You can be more declarative with gradle - just tell it what you want to package up and it will figure out what it needs to run. For example, you can say that you want to zip up all the jars from your subprojects.
apply plugin: 'java'
evaluationDependsOnChildren()
task createPackage(type:Zip) {
from subprojects*.jar
}
There are plenty of ways. One suggestion is to modify build to depend on createPackage to make sure you can call just gradle build. Then you want to enhance your task and tell what are its inputs (probably those are outputs of some other tasks like jar). Gradle will add these tasks to execution when you run the build and can re-run them based on up-to-date status of each task. This is documented in userguide - http://www.gradle.org/docs/current/userguide/more_about_tasks.html#sec:up_to_date_checks and later in a chapter on custom tasks.

Gradle batch task that invokes subproject and other tasks in order

I am writing gradle 1.4 build file for multimodule project. So there is root build.gradle that defines something like:
subprojects {
apply plugin: 'java'
...
which defines build task for all submodules. Submodules are included in settings.gradle and each module has its build file with defined dependencies.
Everything by-the-book, so far:) Now, in the main build file I've added some additional project-scope tasks, like: aggregateJavadoc (collects all javadocs into one) or bundleJar (creates bundle jar from all classes), etc. Each on works when invoked manually.
Now I need a task release that will
build all submodules (as invoked from command line - meaning, i dont want to manually write execute() for each submodule)
invoke additional tasks (using execute() I presume).
I tried dependsOn but the order of listed tasks is not followed. Also, dependent modules seems to be executed after release task execution. I tried several other ideas and failed.
Question: what would be the best way to create such batch task, that has to invoke something on all submodules and additionally to perform some more tasks? What would be the best gradle-friendly solution? Thanx!
It happened that this can be solved with simple dependency management.
So, we have many modules. Now, lets create additional tasks that depends on modules being build:
task aggregateJavadoc(type: Javadoc) {
dependsOn subprojects.build
task bundleJar(type: Jar) {
dependsOn subprojects.build
Finally, our release task would simply look like this:
task release() {
dependsOn subprojects.build
dependsOn aggregateJavadoc
dependsOn bundleJar
...
}
This will build subprojects first; not because it is listed first, but because additional tasks depends on building. Order of additional task is not important. This make sense the most to me.
EDIT
if one of your subprojects (i.e. modules) is non-java module, then you will have a problem building this project. What I do is to group submodules, like this:
def javaModules() {
subprojects.findAll {it.name.contains('jodd-')}
}
and then instead to refer to subprojects, use javaModules everywhere! For example:
configure(javaModules()) {
apply plugin: 'java'
...
and
task prj {
dependsOn javaModules().build
}
btw, I am using this 'dummy' task prj for dependsOn on all those additional projects that depends on building, to prevent repeating.

Resources