A Gradle project is a named
collection of tasks. You can think of it as a
build.gradle file, and all
other contents in that folder.
Commonly, you’ll define projects that represent a library or an application. In fact, this may be all you ever use Gradle for, and that’s fine.
But you can define a Gradle project to do pretty much anything. A project isn’t limited to just building code. For example, a project can spin up a web server and serve interal documentation to your team. Or a project can process art assets. Or, whatever really. Gradle build scripts are programs, so Gradle projects, by extension, are very flexible.
Overall, it’s easiest to think of a Gradle project as
script plus data. In fact, for every
build.gradle script, Gradle
creates a single
Project object that it
associates with it. The relationship is one-to-one.
You can access this object directly by referencing
in your script:
gradlew -q, where
qis short for
quiet. This cuts out a lot of chatty help text.
Gradle is designed so that multiple projects can work together to accomplish some larger goal. After all, if one project represents a library and another project represents an application, there needs to be a way to get the two of them to talk.
Gradle supports this by having you to declare a root project and configuring it with a list of target projects for it to manage. Often, these other projects are nested, which makes for a nice, hierarchical organization.
For the root project only, in addition to defining a
script, you also provide a
settings.gradle file. This
settings file defines all subprojects. If a target
project isn’t listed in there, the root project won’t
know about it.
Note the inclusion of a
gradlewbinary in the root folder, which is a standard convention.
Simply including the subproject names in your
all you need to do in most cases. Gradle automatically
searches the current path for matching subdirectories and
settings.gradlein it, it will be ignored. Only the root
settings.gradlefile will be considered in a Gradle run.
Now, we have multiple projects all with the same task
default, when you make a request to run a Gradle task, it
will fire all tasks that match.
If you want to target a task in a particular project, you will need to qualify its name. You do this by explicitly including the project name before the task,
is essentially a path separator, playing a similar role
in a directory path.
If you start a project name with a
:, that means start from the
root project. If you don’t, Gradle treats the task name
like a relative path, using the current directory to
figure out the active project scope.
starting from the root, you can reference any project’s
task from the directory of any other.
Projects can be nested more than one level deep. Just
be sure to qualify the project names correctly, such as
You may have noticed in the previous sections that I
duplicated a lot of script code. In particular, each
subproject had the exact same copy of the root project’s
script. Of course, we can do better than this and share
code across projects.
Gradle provides special blocks that are available to
the root project:
subprojects. Any logic within
blocks will be available both to the root project itself
as well as its subprojects. The
subprojects block does the
same, except excluding the root project.
For completion, you should also know you can target a
project directly using the
By using these blocks in your root script, you don’t
even need to have
build.gradle files in the
subproject folders at all. Perhaps you have a target
source code folder that you don’t own but still want to
decorate with Gradle tasks. You can do that all from a
Of course, if there are
build.gradle files in your
subprojects, the additional logic you define in the rot
project will simply be merged into them.
The above gradle script defines
printName in every project,
subprojects only, and
listTasks only in project
are a great place to set variables or define tasks that
are shared across projects. The
project selector may be useful
occasionally, but it is probably better to just put that
logic in the subproject
In short, if you find yourself repeating logic across subprojects, think about moving it to the root project instead.
In practice, it’s pretty common to have a root project that wants to reach outside of its own path to some external directory. For example, a project may commonly be laid out as follows, where the library directories are not children of the application directory:
To provide a custom path for a project, you can
override any default settings in the
settings.gradle in this way,
you not only can support complex project layouts, but
this abstracts hardcoded path details out of your build
script logic. For example, you can now safely change the
anytime. Simply update
settings.gradle and everything
will still compile.
As far as the root project is concerned, it thinks the organization is flat:
- A Gradle project is a folder containing a
gradle.buildscript plus its contents
- Multiproject layout is accomplished with a root project that manages target projects
- A root project is defined by a
gradle.buildscripts plus a
- To explicitly target the Gradle tasks of a
particular subproject, qualify its name using
- Projects can be nested as deeply as you want
- Gradle allows
subprojectsblocks in the root project to share code across scripts
- You can specify a project’s path in
settings.gradle, allowing Gradle to manage projects in external directories