1

I have a project with sub projects. The layout:

rootproj
--subproj1
----mybuild.number
--subproj2
--build.gradle
--gradle.properties
--settings.gradle

mybuild.number

#Build Number for ANT. Do not edit!
#Wed Nov 210 2121:210:2121 PST 2102121
build.number=1

settings.gradle

include ('subproj1', 'subproj2')

build.gradle

allprojects {

    repositories {
        mavenLocal()
        maven {url "http://repo1.maven.org/maven2"}
    }


}

subprojects {

    project (':subproj1')   { 

        def oldN = new File("D:/rootproj/subproj1/mybuild.number").text.split("=")[1]
        def newN = (oldN.toInteger() + 1).toString()
        ant.replace(
            file: "mybuild.number",
            token: "${oldN}",
            value: "${newN}"
        )
        println "From subproj1 : ${newN}"
        task hello(overwrite: true){
            doLast{
                println "hello from subproject 1"
            }
        }

    }
    project (':subproj2'){

        println "the build Dir: $buildDir"
        task hello(overwrite: true){
            doLast{
                println "hello from subproject 2"
            }
        }

    }
}

when I run

gradle -q subproj1:hello

or

gradle -q subproj2:hello

or

gradle

from the rootproj, I always get e.g.

....
From subproj1 : 24
the build Dir: D:\rootproj\subproj2\build
From subproj1 : 25
the build Dir: D:\rootproj\subproj2\build

1. Why the two sub projects always get executed twice, therefore the build number is incremented twice, instead of once?
2. why all sub projects get executed even though I explicitly specified the project:task in the command line?
I have searched the Internet, could not find useful information.
Thanks for your help in advance.

EDIT: Change build.gradle as @JB Nizet suggested:

  1. move the ant.replace to task incr
  2. comment out subprojects

It works exactly as I expected.

    allprojects {
    repositories {
        mavenLocal()
        maven {url "http://repo1.maven.org/maven2"}
    }
}

//subprojects {
    def oldN = new File("E:/hqin/build/gradle/rootproj/subproj1/mybuild.number").text.split("=")[1]
    def newN = (oldN.toInteger() + 1).toString()
    project (':subproj1')   { 

        task incr {
            doLast{

                ant.replace(
                    file: "mybuild.number",
                    token: "${oldN}",
                    value: "${newN}"
                )
            }
            println "From subproj1 : ${newN}"
        }
        task hello(overwrite: true, dependsOn: 'incr'){
            doLast{
                println "hello from subproject 1"
            }
        }

    }
    project (':subproj2'){


        task hello(overwrite: true){
            doLast{
                println "the build Dir: $buildDir"
                println "hello from subproject 2"
            }
        }

    }
//}
Heinz
  • 913
  • 4
  • 12
  • 22

1 Answers1

1

Regarding the second point: because your code is run as part of the project configuration, which is always run, whatever the task being executed. If you want code being executed when a task is executed, then it should be inside the doLast closure of a task definition:

task someTask {
  doLast {
    ...
  }
}

Regarding the first point: the closure passed to subprojects is executed for every subproject. So, it's called once for the subproject 1, and configures subproject 1 and subproject 2, then it's called again for subproject 2, and reconfigures subproject 1 and subproject 2 again. You shouldn't have subprojects at all.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • great! I revised the build.gradle file as you suggested, it works as expected. thanks! – Heinz Dec 03 '16 at 06:30
  • I have a follow-up question: when I run gradle -q :subproj2:hello , the subproj1 and its task incr still gets executed. How I can I avoid that? – Heinz Dec 05 '16 at 16:26
  • Is it executed, or is it configured? The println "From subproj1 : ${newN}" is executed in the configuration phase, not in the execution phase – JB Nizet Dec 05 '16 at 16:42
  • it is executed in the config phase, but what matters is that the result is the same. I do not want the newN to be incremented when I extecute :subproj2.hello. I may use a filter configuration at the rootproj, but that seems to be quite inconvenient. – Heinz Dec 05 '16 at 17:11
  • *it is executed in the config phase*: that is unclear. The task will always be configured. So the println, which is part of the configuration phase since it's not inside the doLast closure, will always be executed. But the doLast closure itself shouldn't be executed. Do you observe that the file is modified? Or do you just observe the println? – JB Nizet Dec 05 '16 at 17:21
  • ok, I added a doLast {}closure with in task incr{ } seem correct the behavior. – Heinz Dec 05 '16 at 17:33
  • I can't reproduce that. Post a new question, with a complete build file reproducing the problem. Just use printlns instead of actually doing things in your tasks, to easily run the build locally. – JB Nizet Dec 05 '16 at 17:42