-1

I have a multiple module gradle project.

I am trying to run DependencyReportTask for each subproject (actually for each allprojects)....and then concatenate to a single file.

If I do it like this:

allprojects {    
    
    /* create a .txt file for each subproject (and the root project */
    task generateSingleProjectDependencies(type: DependencyReportTask) {
        outputFile = file('singleproject.dependencies.txt')
    }

}


task concatenateAllProjectsDependencyFiles {
    doLast {
        /* create a FileTree with all the subproject .txt files */
        FileTree singleProjectsFileTree = fileTree('.') {
            include 'singleproject.dependencies.txt'
        }
        if (singleProjectsFileTree.empty) {
            println 'singleProjectsFileTree was empty'
        } else {
            copy {
                println 'allprojects.dependencies.txt is being created, how many times did I fire?'
                /* write out the multiple single-file-txts into a master .txt file */
                def outputFileName = "allprojects.dependencies.txt"
                def output = new File(outputFileName)
                output.write('')
                singleProjectsFileTree.each {
                    f -> output << f.text
                }
            }
        }
    }
}

/* use dependsOn to get the sequence correct */
concatenateAllProjectsDependencyFiles.dependsOn generateSingleProjectDependencies

/* now "finalize" the over-all "build" task..with our custom dependency-all task */
build.finalizedBy concatenateAllProjectsDependencyFiles

where "concatenateAllProjectsDependencyFiles" is OUTSIDE the "allprojects", I only get the root project's results.

(so that is not quite right) :(

===========

If I move concatenateAllProjectsDependencyFiles to inside the "allprojects"

allprojects {

    /* create a .txt file for each subproject (and the root project */
    task generateSingleProjectDependencies(type: DependencyReportTask) {
        outputFile = file('singleproject.dependencies.txt')
    }


    task concatenateAllProjectsDependencyFiles {
        doLast {
            /* create a FileTree with all the subproject .txt files */
            FileTree singleProjectsFileTree = fileTree('.') {
                include 'singleproject.dependencies.txt'
            }
            if (singleProjectsFileTree.empty) {
                println 'singleProjectsFileTree was empty'
            } else {
                copy {
                    println 'allprojects.dependencies.txt is being created, how many times did I fire?'
                    /* write out the multiple single-file-txts into a master .txt file */
                    def outputFileName = "allprojects.dependencies.txt"
                    def output = new File(outputFileName)
                    output.write('')
                    singleProjectsFileTree.each {
                        f -> output << f.text
                    }
                }
            }
        }
    }

/* use dependsOn to get the sequence correct */
    concatenateAllProjectsDependencyFiles.dependsOn generateSingleProjectDependencies

/* now "finalize" the over-all "build" task..with our custom dependency-all task */
    build.finalizedBy concatenateAllProjectsDependencyFiles



}

I get

allprojects.dependencies.txt is being created, how many times did I fire?

showing up N+1 times (N for subproject count plus one root project).

(so that is not quite right) :(

and it isn't just that is fires N+1 times, I get mixed results....maybe a thread race condition with the generation of the singleproject.dependencies.txt creation.

how can I get concatenateAllProjectsDependencyFiles to fire only once, and "find" all the subproject's "singleproject.dependencies.txt" files?

granadaCoder
  • 26,328
  • 10
  • 113
  • 146

1 Answers1

0

I figured it out. It took a little voodoo.

This answer gave the most important hint:

https://discuss.gradle.org/t/task-depends-on-subproject-tasks/15893

I'll post the answer (from the above gradle.org) to avoid d3adlink syndrome.

Well you could use a little Groovy syntax sugar to make it prettier like so:

task publishAndSayHi {
    subprojects.each { dependsOn("${it.name}:publishToMavenLocal") }
    dependsOn('sayHi')
}
Alternatively, if you don’t want to do this for all subprojects you can just define an Array.

Now, my "it works" code below.

allprojects {

    /* other stuff here */

    /* define a task that will create a .txt file for each subproject (and the root project) */
    task generateSingleProjectDependencies(type: DependencyReportTask) {
        outputFile = file('singleproject.dependencies.txt')
    }

}

task concatenateAllProjectsDependencyFiles {

    /* call the root project task */
    dependsOn("generateSingleProjectDependencies")

    /* call each subproject generateSingleProjectDependencies manually.  since 'empty-folders' show up in the allproject list, use a "scr" folder exists trick */
    subprojects.findAll { new File(it.projectDir, "src").exists() }.each { dependsOn("${it.path}:generateSingleProjectDependencies") }

    doLast {

        /* create a FileTree with all the subproject .txt files */
        FileTree singleProjectsFileTree = fileTree('.') {
            include '**/singleproject.dependencies.txt'
        }

        println "singleProjectsFileTree print each item START"
        singleProjectsFileTree.each { println "singleProjectsFileTree.each::::::>>>>>>'${it.path}'" }
        println "singleProjectsFileTree print each item END"

        if (singleProjectsFileTree.empty) {
            println 'singleProjectsFileTree was empty'
        } else {

            copy {
                println 'allprojects.dependencies.txt is being created.'
                /* write out the multiple single-file-txts into a master .txt file */
                def outputFileName = "allprojects.dependencies.txt"
                def output = new File(outputFileName)
                output.write('')
                singleProjectsFileTree.each {
                    f -> output << f.text
                }
            }
        }
    }
}


/* now "finalize" the over-all "build" task..with our custom dependency-all task */
build.finalizedBy concatenateAllProjectsDependencyFiles

Maybe that helps someone in the future.

But now all N+1 (subproject count = N and the one root module/project) are being written out.

keywords

gradle dependency list report root task depends on allprojects subprojects task subprojects contains empty folders

other helpful answers:

How do I concatenate multiple files in Gradle?

How to make tasks execute one after another?

https://discuss.gradle.org/t/i-want-to-copy-the-output-from-gradlew-dependencies-into-a-file-at-build-time/21981

https://github.com/kensipe/gradle-samples/blob/master/dot-report/build.gradle

granadaCoder
  • 26,328
  • 10
  • 113
  • 146