Configuring a multi project using an external build script

Can sections 41.2 and 41.3 of the User’s guide be combined? In other words, I want to externally define some tasks, and then apply them in the parent project, with all the subprojects having access to them. Something like this:

External file (rpm_defaults.gradle):

println "configuring $project" task hiya << { task -> println 'hiya from rpm_defaults in $project'}

Base directory build.gradle:

subprojects { apply from: '../../rpm_defaults/rpm_defaults.gradle' }

Base directory settings.gradle
include 'p1','p2','p3'

result:
$ gradle -q hiya configuring project ':p1' configuring project ':p2' configuring project ':p3' hiya from rpm_defaults in $project hiya from rpm_defaults in $project hiya from rpm_defaults in $project
As a newbie I’m trying to wrap my head around the idea that the name of a subproject could be known at configuration time and seemingly “forgotten” when the task runs. Is the $notation something that is only known at config time?

I want those project references to be filled out at run time as they are at configure time. How can this be done?

Update:
Ok, this is really weird. If I change rpm_defaults.gradle as follows from the content shown above, to:

projectName=$project println "configuring " + projectName task hiya << { task -> println 'hiya from rpm_defaults in ' + projectName}

then I get an error:

$ gradle clean hiya

FAILURE: Build failed with an exception.

Where:
Script '/home/sc1478/rpm_defaults/rpm_defaults.gradle' line: 1

What went wrong:
A problem occurred evaluating script.
Could not find property '$project' on project ':p1'.

Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Now this really makes no sense to my poor newby brain.
With the line

println "configuring $project"

gradle has no difficult handling $project

but with the line

projectName=$project

$project is unknown and produces an error.

I’m totally confused. Help!

OK, solved everything. If only I completely understood.

projectName=$project

fails because the $whatever notation fails outside of a string context. this does not produce an error:

projectName='$project'

But it still doesn’t work right. We need to force the $project to be evaluated, like this:

projectName="$project"

But in order to work correctly, we need to get the projectName variable into the namespace, which we can do with def.

So here is the total solution:

def projectName="$project"
println "configuring " + projectName
task hiya << { task -> println 'hiya from rpm_defaults in ' + projectName}

Still got a few questions, though:

  1. Is there a simpler way to do this particular thing that I’m missing? Seems to me the name of the running project should be accessible somehow without defining a property.
  2. What tools are available that would let me understand what is happening here under the covers. This task is obviously a very small prototype, and I would like to implement more complex behavior through this basic mechanism.

If you want the project’s name, just call project.name

task hiya << { task -> println 'hiya from rpm_defaults in ' + project.name}

Now, on to explaining the errors you saw:

  1. Using the $ notation for replacements only works in GStrings (double quotes). In simple Strings (single quotes), the $ is just kept verbatim. Outside of Strings, the $ has no special meaning at all, so writing $foo just looks for a variable that has a Dollar in its name.

  2. When you do "$project", you are lazily invoking project.toString(), when the GString is evaluated. This works accidentally, because project.toString() == project.path

Thank you very much. GStrings, I see, is a Groovy thing. Didn’t expect to need to dive so quickly into Groovy.

One slight difference: “$project” produces :p1 whereas project.name produces p1.

You’re right, the toString() representation returns the logical path, not the name of the project.