Why is task resolution different in command-line vs dependsOn? - gradle

I am using the shadowJar plugin in my gradle build. Certain subprojects have a shadowJar task.
If I run gradlew shadowJar from the command line, the shadowJar tasks of all the sub-projects are executed. If on the other hand I have another task that dependsOn shadowJar and I run that, it only runs the shadowJar task on the root project.
What is the reason for this and how can I make my dependency use the same task resolution mechanism as the command line tool?

That is perfectly fine. From command line it's gradle that handles this and resolves the tasks for all projects that are taking part in the current build - were included in included during initialization phase.
Whereas when you use dependsOn it depends on in which: build.gradle you expressed the dependency and also in which block e.g. subprojects or allprojects.

Related

Gradle - copy jar to another folder as part of the 'jar' task

I have a multi project gradle setup. I want to simply copy the generated jar file of any project anytime the jar is rebuild and thought this would work in my root project's subprojects closure:
task copyJarToGenerated(type: Copy) {
from jar
into "../my-generated-jars/"
}
copyJarToGenerated.mustRunAfter jar
But if I run the 'clean' task then 'jar' task of any sub project, my jar is generated under build/libs as usual but not copied.
Looking at the gradle output, it only runs compileJava, processResources, classes then jar. It isn't running copyJarToGenerated.
The method mustRunAfter does not define a task dependency, it just enforces a specific order. It basically says 'if both tasks are executed in a build (for whatever reason), then they are executed in the specified order'.
So you need to define the task dependency on your own:
jar.finalizedBy copyJarToGenerated
You could also just add copyJarToGenerated as a dependency of the lifecycle task build:
build.dependsOn copyJarToGenerated
Since you specify the task jar in the method from of your task, it is registered as a task input and therefor registered as a task dependency implicitly. So you won't need to define order with mustRunAfter anymore.
You may also consider using the property destinationDirectory of the task jar instead of creating a new task at all.

Task that executes a specific task in all included builds

I have a root project that includes quite a number of other projects via includeBuild in settings.gradle. All the subprojects have a task named publishToMavenLocal.
How can I define a task publishToMavenLocal in the root project that calls each publishToMavenLocal of each subproject without the need to manually define dependsOn for every subproject specifically?
This use-case is actually covered in the documentation on composite builds. The following code adapts the example from the documentation to your use-case:
task publishToMavenLocal {
dependsOn gradle.includedBuilds*.task(':publishToMavenLocal')
}

Calling Gradle task for only one subproject

How do I configure subprojects for Gradle and run a Gradle task from the build.gradle only for the current directory I'm executing the task from?
For example, suppose I have two projects in a parent folder:
root-project
project-1
project-2
build.gradle
settings.gradle
I have project 1 and 2 included in the settings.gradle file:
include(
'project-1',
'project-2'
)
I have a task configured in the build.gradle file that I would like to call. I've nested the tasks within a subprojects{} block:
subprojects {
...
task check(type: JavaExec) {
main = MAIN_CLASS
classpath = sourceSets.main.runtimeClasspath
}
...
}
However, the build.gradle is run for all subprojects that way.
How can I define all possible subprojects but only call a Gradle task for the current project I'm executing from (i.e., avoid calling the task for all subprojects)? I would like to do this with the current task name only (e.g., gradle check).
Invoking the task in a single project with gradle check is not possible.
You have two options:
Leverage the model Gradle proposes, where tasks can be prefixed by the project name in a multi project build which removes the need to navigate to subprojects.
Which means invoking gradle :project-1:check or gradle :project-2:check depending on which task you want to run.
Define the tasks to have different name in each subprojects. See task rules on how to define tasks with dynamic names.
Which means invoking gradle check1 or gradle check2

how to execute 'gradle build' command from gradle.build script

I want to execute a gradle build command from build.gradle file.
build.gradle file
apply plugin: 'java'
apply plugin: 'application'
task me{
//Can we perform gradle build command here.
}
Question:
Can we perform gradle build command inside task me, similarly like we do from command prompt(screenshot attached)..?
Note : I am using windows env, please assume I am providing all other statements in build.gradle file.
I am able to build from command prompt by executing
.
I want to execute this task me from command prompt and it should be responsible to call gradle build command.(attached screenshot)
Yes, if you make the task me to a task of type GradleBuild
https://docs.gradle.org/current/dsl/org.gradle.api.tasks.GradleBuild.html
E.g.
task me(type: GradleBuild){
buildFile 'mybuild.gradle' //defaults to build.gradle so not needed
dir 'someDir'
tasks 'clean', 'build'
}
You cannot "call" a Gradle task in a Gradle build.
You might stumble upon the method execute() that each Gradle task has, but this is a purely internal method that must not be used by any build script. Using it will not work properly. It will not ensure the task is run only once, it will not ensure dependency tasks are run before and so on and so on, just don't use it.
Your code snippet is too big for me wanting to interpret it right now to understand what you want to do exactly, but if you want to "call" a Gradle task from another Gradle task, your logic is bogus and should be changed. If you want to run a Gradle task before or after another Gradle task is run, the only supported way is to use dependsOn (before) or finalizedBy (after) and you can not set these properties during execution phase of a task but only during configuration phase.
Well, there is one other way to call a Gradle task from a build script, but this is by using a task of type GradleBuild which would start a complete new and separate build of the project you specify which is most often not the action you really want to do.

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