Project Name When Modifying Root Task in Subproject

I need to bundle up the output of my sub-projects into a single archive at the root level. I found this helpful post from 2012 in the old forum archive which shows how to to do this by defining a task in the root project and then modifying that task in the sub-project to inject the contents from the sub-project back into the root archive.

Here’s the code I ended up with in my root build.gradle:

task bundleTar(type: Tar) {
  archiveName = 'bundle.tar'
}
subprojects {
  rootProject.bundleTar {
    from ...
    into this.project.name
  }
}

The problem is that this.project.name is returning the root project’s name, and not the sub-project’s name like I want. Based on the comments in that old post using this.project.name must have worked back then. But its not working for me now on 3.5.

How do I get the sub-project’s name for my into?
Is there an entirely different and better way to do this now 5 years later?

Thanks!
–Brian

Your code is in the root project’s build.gradle, but uses subprojects { } to apply to the subprojects. In the original post, this.project.name is being used in a build.gradle for each subproject. In both cases, this refers to the script class containing the code, which is different.

To handle proper scoping, I would expect your code to look more like this:

task bundleTar(type: Tar) {
    archiveName = 'bundle.tar'
}

subprojects { subproject ->
    rootProject.bundleTar {
        into(subproject.name) {
            from subproject.file('src')
        }
    }
}

However, I would generally prefer solutions that don’t interact with other projects’ tasks and instead expose what they want to expose through configurations.

Thanks James!

However, I would generally prefer solutions that don’t interact with other projects’ tasks and instead expose what they want to expose through configurations.

Could you give some more details of what this would look like using configurations? Or maybe even an example?

In the subprojects, you would create a configuration such as bundleContrib and declare an artifact with the files you want to contribute to the bundle.

configurations {
    bundleContrib
}

task prepareBundle(type: Sync) {
    from 'src'
    into "${buildDir}/bundle/${project.name}"
}

artifacts {
    bundleContrib(file("${buildDir}/bundle")) { builtBy prepareBundle }
}

In the root project, you create a configuration for and declare the dependencies that you want in the bundle. The task then just bundles everything from the configuration.

configurations {
    bundle
}

dependencies {
    bundle subprojects.collect {
        project(path: it.path, configuration: 'bundleContrib')
    }
}

task bundleTar(type: Tar) {
    archiveName = 'bundle.tar'
    from configurations.bundle
}

I generally like this better because dependencies and artifacts model exactly what these files are between the two projects. However, this example is both longer and less efficient compared to what I normally have when using this method. This doesn’t work as well in the case that you want the subproject contents in a folder name after the project unless you’re willing to have that path as part of the original src file structure due to needing the prepareBundle task.

Awesome, thank you for your help!