<!--
  ~ Copyright 2015 the original author or authors.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->
<chapter id='intro_multi_project_builds'>
    <title>Introduction to multi-project builds</title>

    <para>Only the smallest of projects has a single build file and source tree, unless it happens to be a massive,
        monolithic application. It’s often much easier to digest and understand a project that has been split into
        smaller, inter-dependent modules. The word “inter-dependent” is important, though, and is why you typically
        want to link the modules together through a single build.</para>

    <para>Gradle supports this scenario through <firstterm>multi-project</firstterm> builds.</para>

    <section>
        <title>Structure of a multi-project build</title>
        <para>Such builds come in all shapes and sizes, but they do have some common characteristics:
        <itemizedlist>
            <listitem><para>A <filename>settings.gradle</filename> file in the root or <literal>master</literal>
                directory of the project</para>
            </listitem>
            <listitem><para>A <filename>build.gradle</filename> file in the root or <literal>master</literal>
                directory</para></listitem>
            <listitem><para>Child directories that have their own <filename>*.gradle</filename> build files
                (some multi-project builds may omit child project build scripts)</para>
            </listitem>
        </itemizedlist>
        </para>

        <para>The <filename>settings.gradle</filename> file tells Gradle how the project and subprojects are
            structured. Fortunately, you don’t have to read this file simply to learn what the project structure
            is as you can run the command <userinput>gradle projects</userinput>. Here's the output from using
            that command on the Java <emphasis>multiproject</emphasis> build in the Gradle samples:
            <sample id="listProjects" dir="java/multiproject" title="Listing the projects in a build">
                <output args="-q projects"/>
            </sample>
        </para>

        <para>This tells you that <emphasis>multiproject</emphasis> has three immediate child projects:
            <emphasis>api</emphasis>, <emphasis>services</emphasis> and <emphasis>shared</emphasis>. The
            <emphasis>services</emphasis> project then has its own children, <emphasis>shared</emphasis> and
            <emphasis>webservice</emphasis>. These map to the directory structure, so it’s easy to find them.
            For example, you can find <emphasis>webservice</emphasis> in
            <filename>&lt;root&gt;/services/webservice</filename>.</para>

        <para>Each project will usually have its own build file, but that's not necessarily the case. In the above
            example, the <emphasis>services</emphasis> project is just a container or grouping of other subprojects.
            There is no build file in the corresponding directory. However, <emphasis>multiproject</emphasis> does
            have one for the root project.</para>

        <para>The root <filename>build.gradle</filename> is often used to share common configuration between the
            child projects, for example by applying the same sets of plugins and dependencies to all the child
            projects. It can also be used to configure individual subprojects when it is preferable to have
            all the configuration in one place. This means you should always check the root build file when
            discovering how a particular subproject is being configured.</para>

        <para>Another thing to bear in mind is that the build files might not be called
            <filename>build.gradle</filename>. Many projects will name the build files after the subproject names,
            such as <filename>api.gradle</filename> and <filename>services.gradle</filename> from the previous
            example. Such an approach helps a lot in IDEs because it’s tough to work out which
            <filename>build.gradle</filename> file out of twenty possibilities is the one you want to open. This
            little piece of magic is handled by the <filename>settings.gradle</filename> file, but as a build user
            you don’t need to know the details of how it’s done. Just have a look through the child project
            directories to find the files with the <filename>.gradle</filename> suffix.</para>

        <para>Once you know what subprojects are available, the key question for a build user is how to execute the
            tasks within the project.</para>
    </section>

    <section>
        <title>Executing a multi-project build</title>
        <para>From a user's perspective, multi-project builds are still collections of tasks you can run. The
            difference is that you may want to control <emphasis>which</emphasis> project's tasks get executed.
            You have two options here:

            <itemizedlist>
                <listitem><para>Change to the directory corresponding to the subproject you’re interested in and
                    just execute <userinput>gradle &lt;task&gt;</userinput> as normal.</para></listitem>
                <listitem><para>Use a qualified task name from any directory, although this is usually done from
                    the root. For example: <userinput>gradle :services:webservice:build</userinput> will build the
                    <emphasis>webservice</emphasis> subproject and any subprojects it depends on.</para></listitem>
            </itemizedlist>
        </para>

        <para>The first approach is similar to the single-project use case, but Gradle works slightly differently
            in the case of a multi-project build. The command <userinput>gradle test</userinput> will execute the
            <literal>test</literal> task in any subprojects, relative to the current working directory, that have
            that task. So if you run the command from the root project directory, you’ll run <literal>test</literal>
            in <emphasis>api</emphasis>, <emphasis>shared</emphasis>, <emphasis>services:shared</emphasis> and
            <emphasis>services:webservice</emphasis>. If you run the command from the services project directory,
            you’ll only execute the task in <emphasis>services:shared</emphasis> and
            <emphasis>services:webservice</emphasis>.</para>

        <para>For more control over what gets executed, use qualified names (the second approach mentioned). These
            are paths just like directory paths, but use ‘:’ instead of ‘/’ or ‘\’. If the path begins with a ‘:’,
            then the path is resolved relative to the root project. In other words, the leading ‘:’ represents the
            root project itself. All other colons are path separators.</para>

        <para>This approach works for any task, so if you want to know what tasks are in a particular subproject,
            just use the <literal>tasks</literal> task, e.g. <userinput>gradle :services:webservice:tasks</userinput>
            .</para>

        <para>Regardless of which technique you use to execute tasks, Gradle will take care of building any
            subprojects that the target depends on. You don’t have to worry about the inter-project dependencies
            yourself. If you’re interested in how this is configured, you can read about writing multi-project builds
            <link linkend="multi_project_builds">later in the user guide</link>.</para>

        <para>There’s one last thing to note. When you’re using the Gradle wrapper, the first approach doesn’t work
            well because you have to specify the path to the wrapper script if you’re not in the project root. For
            example, if you’re in the <emphasis>webservice</emphasis> subproject directory, you would have to run
            <userinput>../../gradlew build</userinput>.</para>

        <para>That’s all you really need to know about multi-project builds as a build user. You can now identify whether
            a build is a multi-project one and you can discover its structure. And finally, you can execute tasks
            within specific subprojects.</para>
    </section>

</chapter>
