Let's say there are 3 sub projects: sub1, sub2, and sub3. They all have task uploadArchives. If we run gradle uploadArchives, how it is cascaded to sub projects?
Assume your project layout as bellow
gradle-tasks
|- sub1
|- sub2
|- sub3
settings.gradle as below:
include 'sub1', 'sub2', 'sub3'
rootProject.name = 'gradle-tasks'
And your build.gradle is like this:
allprojects {
task uploadArchives {
doLast { task ->
println "I'm $task.project.name"
}
}
}
Then when you execute ./gradlew uploadArchives in root, you will have
$ ./gradlew uploadArchives
> Task :uploadArchives
I'm gradle-tasks
> Task :sub1:uploadArchives
I'm sub1
> Task :sub2:uploadArchives
I'm sub2
> Task :sub3:uploadArchives
I'm sub3
Ref: https://docs.gradle.org/current/userguide/multi_project_builds.html
Related
I have a multi-module project that ends up outputting a directory called logs at the root of each module - including the root project.
I have extended the clean task like this but it only deletes the logs dir in the root project and not in the sub-modules.
allprojects {
clean {
delete 'logs'
}
}
I thought that this meant "add the clean task to all the projects and delete the logs dir in each project".
It seems like even though the delete is being called in each sub-module, it is using the root directory as the relative path to find the logs dir.
However, if I change it to the following it deletes the directory in each module.
allprojects {
clean {
delete file('./logs')
}
}
This looks functionally identical to me since if the path of each clean task is relative to the root then file('./logs') should also be relative to the root.
However, the file object seems to be relative to the module dir and not the root.
Why does the file object resolve correctly but the string passed to the clean task does not?
How are paths resolved for each module when running a multi-module project?
Is there a better way to do this than using a file object?
Could not replicate - gradle 6.7 / jdk 11
Dir structure
.
|____a
| |____b
| |____c
common delete task
allprojects {
apply plugin: 'java'
task deleteLogs(type: Delete) {
delete 'logs'
}
clean {
delete 'logs'
}
task printcd {
println 'project : ' + project.name
println 'rootDir : ' + project.rootDir
println 'prjDir : ' + project.projectDir
println '-------------'
println 'file : ' + file('logs').absolutePath
println 'file ./ : ' + file('./logs').absolutePath
println '-------------'
print 'deletePath : '
project.tasks.getByName('deleteLogs').targetFiles.each {file -> println file.absolutePath }
println '-------------'
print 'clean : '
project.tasks.getByName('clean').targetFiles.each {file -> print file.absolutePath + " , " }
println ''
println '============='
}
repositories {
mavenCentral()
}
}
output
-bash$ gradle printcd
> Configure project :
project : a
rootDir : /Users/xyz/a
prjDir : /Users/xyz/a
-------------
file : /Users/xyz/a/logs
file ./ : /Users/xyz/a/logs
-------------
deletePath : /Users/xyz/a/logs
-------------
clean : /Users/xyz/a/build , /Users/xyz/a/logs ,
=============
project : b
rootDir : /Users/xyz/a
prjDir : /Users/xyz/a/b
-------------
file : /Users/xyz/a/b/logs
file ./ : /Users/xyz/a/b/logs
-------------
deletePath : /Users/xyz/a/b/logs
-------------
clean : /Users/xyz/a/b/build , /Users/xyz/a/b/logs ,
=============
project : c
rootDir : /Users/xyz/a
prjDir : /Users/xyz/a/c
-------------
file : /Users/xyz/a/c/logs
file ./ : /Users/xyz/a/c/logs
-------------
deletePath : /Users/xyz/a/c/logs
-------------
clean : /Users/xyz/a/c/build , /Users/xyz/a/c/logs ,
=============
BUILD SUCCESSFUL in 578ms
-bash$ gradle --version
------------------------------------------------------------
Gradle 6.7
------------------------------------------------------------
JVM: 11.0.8 (Oracle Corporation 11.0.8+10-LTS)
I have a task from a plugin which I call on command line like this:
$ gradle myTask -PsomeArg=<value>
I want to define another task that would do exactly the same with a default parameter value. I expect to be able to call it like this:
$ gradle otherTask
I assume my task should look something like this:
task otherTask (dependsOn: 'myTask', someArg: 'value') {...}
You could define a task that would set default value for project property someArg when this value is not provided as command line parameter :
task otherTask (){
finalizedBy myTask
doFirst{
if (!project.hasProperty("someArg")) {
project.ext.set("someArg", "defaultValue")
}
}
}
Note that you need to use finalizedBy dependency type here: if you use otherTask.dependsOn myTask the task myTask will be executed first (so default value for property someArg will not be set yet)
Execution result:
./gradlew myTask -PsomeArg=myValue
> Task :myTask
executing task pluginTask with arg: myValue
./gradlew otherTask -PsomeArg=myValue
> Task :myTask
executing task pluginTask with arg: myValue
./gradlew otherTask
> Task :myTask
executing task pluginTask with arg: defaultValue
I have project ("backend") configuration:
dependencies {
compile project(':model') //I would like to pass some params into this being build.
...
And other project ("frontend") configuration is very similar:
dependencies {
compile project(':model') //but from this project I will not pass params.
...
And when I build the dependant project model- I need to pass a parameter to it's build parameter and do something on condition. So for all projects who needs the sub-projects it will be built according to their needs.
To be more specific: When I build "backtend" - "model"'s project should run some task, but when I build "frontend" I don't.
Is it possible to force clean the sub-project as well?
You can easily pass parameters from command line, or by properties defined in gradle.properties or in ext. Here's a little project:
/build.gradle
ext {
var = "alpha"
}
task hello {
println "Name: $project.name"
println "Var: $var"
println "Param: $param"
println "Prop: $prop"
}
/gradle.properties
prop=gama
/settings.gradle
project.name = 'foo'
include 'bar'
/bar/build.gradle
task hello {
println "Name: $project.name"
println "Var: $var"
println "Param: $param"
println "Prop: $prop"
}
If you run gradle hello -Pparam=beta it will print:
Name: foo
Var: alpha
Param: beta
Prop: gama
Name: bar
Var: alpha
Param: beta
Prop: gama
:hello UP-TO-DATE
:bar:hello UP-TO-DATE
I starting playing around gradle and trying to understand the purpose of <<.
On executing gradle -q task0 when build.gradle contains gave me task 0
4.times { counter ->
task "task$counter" <<{
println "task $counter"
}
}
where as executing gradle -q test{0123} when build.gradle contains
4.times { counter ->
task "task$counter" {
println "task $counter"
}
}
returning
task 0
task 1
task 2
task 3
Can someone help in understanding purpose of <<?
If you have << it will execute the print lines when the task is executed and not having it executes the print lines when the task is configured.
This can effect your output since the Gradle Lifecycle is Initialization > Configuration > Execution.
For example if your build.gradle contains:
task "task0" << {
println "task 0"
}
task "task1" {
println "task 1"
}
Then if you execute task0 you will get:
> gradlew -q task0
task 1
task 0
Even though you would only expect task 0 to print. While if you execute task1 you get:
> gradlew -q task1
task 1
This is because task1 is printing out during configuration which even though you are not running it, the whole build.gradle file gets read in during the configuration phase to determine what gets executed. You could even go:
> gradlew clean
task 1
And you get your output from task1.
I think the problem here is what << means. It is predefined shift left operator and with it we say to a Gradle task. "Gradle task, I want closure which is after << to be put as your last action".So with
task "taskHello" <<{
println "Hello Gradle action"
}
you say in my build I have a task, which name is taskHello and I want when excecute it with
gradle taskHello
To do action
{
println "Hello Gradle action"
}
<< is a syntax sugar short for doLast{}, so you can rewrite your task like this:
4.times { counter ->
task "task$counter" {
doLast{
println "task $counter"
}
}
}
I'm trying to port over a somewhat convoluted Makefile to Gradle. I need to be able to have some tasks that execute in isolation of each other, but I cannot figure out how to do this in Gradle; for example, if I have a build.gradle that looks like the following:
apply plugin: 'eclipse'
apply plugin: 'idea'
task foo {
println 'foo'
}
task bar {
println 'bar'
}
task baz {
println 'baz'
}
If I run:
gradle -q foo
Then I expect to see
foo
But instead I see:
foobarbaz
printed to my terminal.
How can I configure Gradle to only perform the single task?
You haven't given the tasks any functionality; what you're seeing is the output of the tasks being instantiated.
Change your build.gradle to this...
task foo {
doLast {
println 'foo'
}
}
task bar << {
println 'bar'
}
task baz {
println 'baz'
}
and then run the foo task:
gradle foo
Your output should be...
baz
:foo
foo
...showing that baz was output when the baz task was created, then the foo task was executed (":foo") followed by the output of the foo task. Note that the "<<" operator is an alias for doLast.
See Build Script Basics in the Gradle User Guide.