<!--
  ~ Copyright 2009 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='organizing_build_logic' xmlns:xi="http://www.w3.org/2001/XInclude">
    <title>Organizing Build Logic</title>
    <para>Gradle offers a variety of ways to organize your build logic. First of all you can put your build logic
        directly in the action closure of a task. If a couple of tasks share the same logic you can extract this logic
        into a method. If multiple projects of a multi-project build share some logic you can define this method in the
        parent project. If the build logic gets too complex for being properly modeled by methods you want have an OO
        Model.
        <footnote>
            <para>Which might range from a single class to something very complex.
            </para>
        </footnote>
        Gradle makes this very easy. Just drop your classes in a certain folder and Gradle automatically compiles them
        and puts them in the classpath of your build script.
    </para>
    <section id='sec:build_sources'>
        <title>Build sources</title>
        <para>If you run Gradle, it checks for the existence of a folder called <literal>buildSrc</literal>. Just put
            your build source code in this folder and stick to the layout convention for a Java/Groovy project (see
            <xref linkend='javalayout'/>). Gradle then automatically compiles and tests this code and puts it in
            the classpath of your build script. You don't need to provide any further instruction. For multi-project
            builds there can be only one <literal>buildSrc</literal> directory which has to be in the root project.
        </para>
        <para>This is probably good enough for most of the cases. If you need more flexibility, you can provide a
            <filename>build.gradle</filename> and a <filename>settings.gradle</filename> file in the
            <filename>buildSrc</filename> folder. If you like, you can even have a multi-project build in there.
        </para>
    </section>
    <section id='sec:external_dependencies'>
        <title>External dependencies for the build script</title>
        <para>If your build script needs to use external libraries, you can add them to the script's classpath in the
            build script itself. You do this using the <literal>buildscript()</literal> method, passing in a closure which
            declares the build script classpath.
        </para>
        <sample id="declareExternalBuildDependency" dir="userguide/organizeBuildLogic/externalDependency" title="Declaring external dependencies for the build script">
            <sourcefile file="build.gradle" snippet="declare-classpath"/>
        </sample>
        <para>The closure passed to the <literal>buildscript()</literal> method configures a
            <apilink class="org.gradle.api.initialization.dsl.ScriptHandler"/> instance. You declare the build script
            classpath by adding dependencies to the <literal>classpath</literal> configuration. This is the same way
            you declare, for example, the Java compilation classpath. You can use any of the dependency types described
            in <xref linkend='sec:how_to_declare_your_dependencies'/>, except project dependencies.</para>
        <para>Having declared the build script classpath, you can use the classes in your build script as you would
            any other classes on the classpath. The following example adds to the previous example, and uses classes
            from the build script classpath.</para>
        <sample id="externalBuildDependency" dir="userguide/organizeBuildLogic/externalDependency" title="A build script with external dependencies">
            <sourcefile file="build.gradle"/>
            <output args="-q encode"/>
        </sample>
        <para>
            For multi-project builds, the dependencies declared in the a project's build script, are available to the
            build scripts of all sub-projects.
        </para>
    </section>
    <section id='sec:ant_optional_dependencies'>
        <title>Ant optional dependencies</title>
        <para>For reasons we don't fully understand yet, external dependencies are not picked up by Ant's optional
            tasks. But you can easily do it in another way.
            <footnote>
                <para>In fact, we think this is anyway the nicer solution. Only if your buildscript and Ant's optional
                    task need the <emphasis>same</emphasis> library you would have to define it two times. In such a
                    case it would be nice, if Ant's optional task would automatically pickup the classpath defined
                    in the <literal>gradesettings</literal>.
                </para>
            </footnote>
        </para>
        <sample id="buildLogic" dir="userguide/organizeBuildLogic" title="Ant optional dependencies">
            <sourcefile file="build.gradle"/>
        </sample>
        <para>This is also nice example for the usage of client modules. The pom.xml in maven central for the
        ant-commons-net task does not provide the right information for this use case.</para>
    </section>
    <section id='sec:philosophy'>
        <title>Summary</title>
        <para>Gradle offers you a variety of ways of organizing your build logic. You can choose what is right for your
            domain and find the right balance between unnecessary indirections, and avoiding redundancy and a hard to
            maintain code base. It is our experience that even very complex custom build logic is rarely shared between
            different builds. Other build tools enforce a separation of this build logic into a separate project. Gradle
            spares you this unnecessary overhead and indirection.
        </para>
    </section>
</chapter>
