<!--
  ~ Copyright 2010 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='nativeBinaries'>
    <title>Building native binaries</title>

    <note>
        <para>
            The Gradle support for building native binaries is currently <link linkend="feature_lifecycle">incubating</link>. Please be aware that the DSL and other configuration may change in later Gradle versions.
        </para>
    </note>

    <para>
        The various native binary plugins add support for building native software components from C++, C and Assembler sources.
        While many excellent build tools exist for this space of software development, Gradle offers developers it's trademark power and flexibility
        together with the dependency management practices more traditionally found in the JVM development space.
    </para>

    <section>
        <title>Tool chain support</title>
        <para>
            Gradle offers the ability to execute the same build using different tool chains. You can ontrol which tool chain will be used to build
            by changing the operating system PATH to include the desired tool chain compiler. Alternatively, you can configure the tool chains directly,
            as described in the `Native Binary Variants` section, below.
        </para>
        <para>
            The following tool chains are supported:
        </para>
        <table>
            <thread>
                <tr><td>Operating System</td><td>Tool Chain</td><td>Notes</td></tr>
            </thread>
            <tr>
                <td>Linux</td><td><ulink url="http://gcc.gnu.org/">GCC</ulink></td><td></td>
            </tr>
            <tr>
                <td>Linux</td><td><ulink url="http://clang.llvm.org">Clang</ulink></td><td></td>
            </tr>
            <tr>
                <td>Mac OS X</td><td><ulink url="http://gcc.gnu.org/">GCC</ulink></td><td>Using GCC distributed with XCode.</td>
            </tr>
            <tr>
                <td>Mac OS X</td><td><ulink url="http://clang.llvm.org">Clang</ulink></td><td>Using Clang distributed with XCode.</td>
            </tr>
            <tr>
                <td>Windows</td><td><ulink url="http://www.microsoft.com/visualstudio/en-us">Visual C++</ulink></td><td>Windows XP and later, Visual C++ 2010 and later.</td>
            </tr>
            <tr>
                <td>Windows</td><td><ulink url="http://gcc.gnu.org/">GCC</ulink></td><td>Windows XP and later, using GCC distributed with Cygwin.</td>
            </tr>
            <tr>
                <td>Windows</td><td><ulink url="http://www.mingw.org/">MinGW</ulink></td><td>Windows XP and later.</td>
            </tr>
        </table>
    </section>

    <section>
        <title>Component model</title>
        <para>
            A native binary project defines a set of <apilink class="org.gradle.nativebinaries.Executable"/> and <apilink class="org.gradle.nativebinaries.Library"/> components,
            each of which Gradle maps to a number of <apilink class="org.gradle.nativebinaries.NativeBinary"/> outputs.
            For each <literal>executable</literal> or <literal>library</literal> defined, Gradle adds a <apilink class="org.gradle.language.base.FunctionalSourceSet"/> with the same name.
            Each of these functional source sets will contain a language-specific source set for each of the languages supported by the project.
        </para>
        <para>
            To build either a static or shared native library binary,
            a <apilink class="org.gradle.nativebinaries.Library"/> component is added to the <literal>libraries</literal> container.
            Each <literal>library</literal> component can produce at least one <apilink class="org.gradle.nativebinaries.SharedLibraryBinary"/>
            and at least one <apilink class="org.gradle.nativebinaries.StaticLibraryBinary"/>.
        </para>
        <sample id="cppLibraries" dir="native-binaries/c" title="Defining a library component">
            <sourcefile file="build.gradle" snippet="libraries"/>
        </sample>
        <para>
            To build an executable binary,
            an <apilink class="org.gradle.nativebinaries.Executable"/> component is added to the <literal>executables</literal> container
            and associated with a set of sources.
        </para>
        <sample id="cppExecutables" dir="native-binaries/c" title="Defining executable components">
            <sourcefile file="build.gradle" snippet="executables"/>
        </sample>
        <para>
            In many cases, more than one native binary can be produced for a component.
            These binaries may vary based on the tool chain used to build, the compiler/linker flags supplied, the dependencies
            provided, or additional source files provided. Each native binary produced for a component is referred to as <literal>variant</literal>.
            Binary variants are discussed in detail below.
        </para>
    </section>

    <section>
        <title>Tasks</title>
        <para>
            For each <apilink class="org.gradle.nativebinaries.NativeBinary"/> that can be produced by a build,
            a single <literal>lifecycle task</literal> is constructed that can be used to create that binary, together with a set of sub-tasks that do the actual
            work of compiling, linking or assembling the binary.
        </para>
        <table>
            <thread>
                <tr><td>Component Type</td><td>Native Binary Type</td><td>Lifecycle task</td><td>Location of created binary</td></tr>
            </thread>
            <tr>
                <td><apilink class="org.gradle.nativebinaries.Executable"/></td><td><apilink class="org.gradle.nativebinaries.ExecutableBinary"/></td><td><literal>mainExecutable</literal></td><td><filename><replaceable>$buildDir</replaceable>/binaries/<replaceable>$project.name</replaceable></filename></td>
            </tr>
            <tr>
                <td><apilink class="org.gradle.nativebinaries.Library"/></td><td><apilink class="org.gradle.nativebinaries.SharedLibraryBinary"/></td><td><literal>mainSharedLibrary</literal></td><td><filename><replaceable>$buildDir</replaceable>/binaries/lib<replaceable>$project.name</replaceable>.so</filename></td>
            </tr>
            <tr>
                <td><apilink class="org.gradle.nativebinaries.Library"/></td><td><apilink class="org.gradle.nativebinaries.StaticLibraryBinary"/></td><td><literal>mainStaticLibrary</literal></td><td><filename><replaceable>$buildDir</replaceable>/binaries/<replaceable>$project.name</replaceable>.a</filename></td>
            </tr>
        </table>

        <section>
            <title>Working with shared libraries</title>
            <para>
                For each executable binary produced, the <literal>cpp</literal> plugin provides an <literal>install${binary.name}</literal> task,
                which creates a development install of the executable, along with the shared libraries it requires.
                This allows you to run the executable without needing to install the shared libraries in their final locations.
            </para>
        </section>
    </section>

    <section id="native_binaries:languages">
        <title>Supported Languages: C, C++ and Assembler</title>
        <para>
            Presently, Gradle supports building native binaries from any combination of C++, C and Assembler sources.
            A native binary project will contain one or more named <literal>FunctionalSourceSet</literal> instances (eg 'main', 'test', etc),
            each of which can contain <literal>LanguageSourceSet</literal>s containing C++, C or Assembler source files.
        </para>

        <section>
            <title>C++ support</title>
            <para>
                C++ language support is provided by means of the <literal>'cpp'</literal> plugin.
            </para>
            <sample id="cppPlugin" dir="native-binaries/cpp" title="The 'cpp' plugin">
                <sourcefile file="build.gradle" snippet="apply-plugin"/>
            </sample>
            <para>
                C++ sources to be included in a native binary are provided via a <apilink class="org.gradle.language.cpp.CppSourceSet"/>,
                which defines a set of C++ source files and optionally a set of exported header files (for a library).
                By default, for any named component the <apilink class="org.gradle.language.cpp.CppSourceSet"/> contains
                <filename>.cpp</filename> source files in <filename>src/${name}/cpp</filename>,
                and header files in <filename>src/${name}/headers</filename>.
            </para>
            <para>
                While the <literal>cpp</literal> plugin defines these default locations for each <apilink class="org.gradle.language.cpp.CppSourceSet"/>,
                it is possible to extend or override these defaults to allow for a different project layout.
            </para>
            <sample id="cppSourceSet" dir="native-binaries/custom-layout" title="C++ source set">
                <sourcefile file="build.gradle" snippet="cpp-sources"/>
            </sample>
            <para>
                For a library named 'main', files in <filename>src/main/headers</filename> are considered the “public” or “exported” headers.
                Header files that should not be exported (but are used internally) should be placed inside the <filename>src/main/cpp</filename> directory (though be aware that
                such header files should always be referenced in a manner relative to the file including them).
            </para>
        </section>

        <section>
            <title>C support</title>
            <para>
                C language support is provided by means of the <literal>'c'</literal> plugin.
            </para>
            <sample id="cPlugin" dir="native-binaries/c" title="The 'c' plugin">
                <sourcefile file="build.gradle" snippet="apply-plugin"/>
            </sample>
            <para>
                C sources to be included in a native binary are provided via a <apilink class="org.gradle.language.c.CSourceSet"/>,
                which defines a set of C source files and optionally a set of exported header files (for a library).
                By default, for any named component the <apilink class="org.gradle.language.c.CSourceSet"/> contains
                <filename>.c</filename> source files in <filename>src/${name}/c</filename>,
                and header files in <filename>src/${name}/headers</filename>.
            </para>
            <para>
                While the <literal>c</literal> plugin defines these default locations for each <apilink class="org.gradle.language.c.CSourceSet"/>,
                it is possible to extend or override these defaults to allow for a different project layout.
            </para>
            <sample id="cSourceSet" dir="native-binaries/custom-layout" title="C source set">
                <sourcefile file="build.gradle" snippet="c-sources"/>
            </sample>
            <para>
                For a library named 'main', files in <filename>src/main/headers</filename> are considered the “public” or “exported” headers.
                Header files that should not be exported (but are used internally) should be placed inside the <filename>src/main/c</filename> directory (though be aware that
                such header files should always be referenced in a manner relative to the file including them).
            </para>
        </section>

        <section>
            <title>Assembler support</title>
            <para>
                Assembly language support is provided by means of the <literal>'assembler'</literal> plugin.
            </para>
            <sample id="assemblerPlugin" dir="native-binaries/assembler" title="The 'assembler' plugin">
                <sourcefile file="build.gradle" snippet="apply-plugin"/>
            </sample>
            <para>
                Assembler sources to be included in a native binary are provided via a <apilink class="org.gradle.language.assembler.AssemblerSourceSet"/>,
                which defines a set of Assembler source files.
                By default, for any named component the <apilink class="org.gradle.language.assembler.AssemblerSourceSet"/> contains
                <filename>.s</filename> source files under <filename>src/${name}/asm</filename>.
            </para>
        </section>
    </section>

    <section>
        <title>Configuring the compiler, assembler and linker</title>
        <para>
            Each binary to be produced is associated with a set of compiler and linker settings, which include command-line arguments as well as macro definitions.
            These settings can be applied to all binaries, an individual binary, or selectively to a group of binaries based on some criteria.
        </para>
        <sample id="allBinarySettings" dir="native-binaries/cpp" title="Settings that apply to all binaries">
            <sourcefile file="build.gradle" snippet="all-binaries"/>
        </sample>
        <para>
            Each binary is associated with a particular <apilink class="org.gradle.nativebinaries.ToolChain"/>, allowing settings to be targeted based on
            this value.
        </para>
        <para>
            It is easy to apply settings to all binaries of a particular type:
        </para>
        <sample id="allSharedLibraryBinarySettings" dir="native-binaries/c" title="Settings that apply to all shared libraries">
            <sourcefile file="build.gradle" snippet="all-shared-libraries"/>
        </sample>
        <para>
            Furthermore, it is possible to specify settings that apply to all binaries produces for a particular <literal>executable</literal>
            or <literal>library</literal> component:
        </para>
        <sample id="componentBinarySettings" dir="native-binaries/assembler" title="Settings that apply to all binaries produced for the 'main' executable component">
            <sourcefile file="build.gradle" snippet="assembler-args"/>
        </sample>
        <para>
            The above example will apply the supplied configuration to all <literal>executable</literal> binaries built.
        </para>
        <para>
            Similarly, settings can be specified to target binaries for a component that are of a particular type:
            eg all <literal>shared libraries</literal> for the <literal>main library</literal> component.
        </para>
        <sample id="sharedLibraryArgs" dir="native-binaries/cpp-lib" title="Settings that apply only to shared libraries produced for the 'main' library component">
            <sourcefile file="build.gradle" snippet="args"/>
        </sample>
    </section>

    <section>
        <title>Library Dependencies</title>
        <para>
            Dependencies for C++ projects are binary libraries that export header files. The header files are used during compilation, with the compiled
            binary dependency being used during the linking.
        </para>
        <section>
           <title>Dependencies within the same project</title>
           <para>
               A set of sources may depend on header files provided by another binary component within the same project.
               A common example is a native executable component that uses functions provided by a separate native library component.
           </para>
           <para>
               Such a library dependency can be easily provided to source set associated with the <literal>executable</literal> component:
           </para>
           <sample id="cppSourceLibrary" dir="native-binaries/cpp" title="Providing a library dependency to the source set">
               <sourcefile file="build.gradle" snippet="source-library"/>
           </sample>
           <para>
               Alternatively, a library dependency can be provided directly to the <literal>ExecutableBinary</literal> for the <literal>executable</literal>.
           </para>
           <sample id="cppBinaryLibrary" dir="native-binaries/custom-layout" title="Providing a library dependency to the binary">
               <sourcefile file="build.gradle" snippet="binary-library"/>
           </sample>
        </section>
        <section>
            <title>Project Dependencies</title>
            <para>
                For a component produced in a different Gradle project, the notation is similar.
            </para>
            <sample id="cppProjectDependencies" dir="native-binaries/multi-project" title="Declaring project dependencies">
                <sourcefile file="build.gradle" snippet="project-dependencies"/>
            </sample>
        </section>
        <section>
            <title>External Dependencies</title>
            <para>
                External dependencies (i.e. from a repository, not a subproject) are specified using the following syntax:
            </para>
            <sample id="cppExternalDependencies" dir="native-binaries/dependencies" title="Declaring dependencies">
                <sourcefile file="build.gradle" snippet="declaring-dependencies"/>
            </sample>
            <para>
                Each dependency must be specified with the <literal>dependency</literal> method as above and must be declared as part of the source set. The
                <literal>group</literal>, <literal>name</literal> and <literal>version</literal> arguments <emphasis>must</emphasis> be supplied.
            </para>
            <para>
                For each declared dependency, two actual dependencies are created. One with the classifier “<literal>headers</literal>” and extension
                “<literal>zip</literal>” which is a zip file of the exported headers, and another with the classifier “<literal>so</literal>” and extension
                “<literal>so</literal>” which is the compiled library binary to link against (which is supplied as a direct input to the g++ link operation).
            </para>
        </section>
    </section>

    <section id="native_binaries:variants">
        <title>Native Binary Variants</title>
        <para>
            For each executable or library defined, Gradle is able to build a number of different native binary variants.
            Examples of different variants include debug vs release binaries, 32-bit vs 64-bit binaries, and binaries produced
            by GCC vs binaries produced by Clang.
        </para>
        <para>
            Binaries produced by Gradle can be differentiated on
                <link linkend="native_binaries:build_type">build type</link>,
                <link linkend="native_binaries:target_platform">target platform</link>,
                <link linkend="native_binaries:flavor">flavor</link> and
                <link linkend="native_binaries:tool_chain">tool chain</link>.
        </para>

        <section id="native_binaries:build_type">
            <title>Build type</title>
            <para>
                The <literal>build type</literal> determines various non-functional aspects of a binary, such as whether debug information is included,
                or what optimisation level the binary is compiled with. Typical build types are 'debug' and 'release', but a project
                is free to define any set of build types.
            </para>
            <sample id="buildTypes" dir="native-binaries/variants" title="Defining build types">
                <sourcefile file="build.gradle" snippet="build-types"/>
            </sample>
            <para>
                For a build type, a Gradle project will typically define a set of compiler/linker flags per tool chain.
            </para>
            <sample id="buildTypeConfig" dir="native-binaries/variants" title="Configuring debug binaries">
                <sourcefile file="build.gradle" snippet="build-type-config"/>
            </sample>
            <note>
                At this stage, it is completely up to the build script to configure the relevant compiler/linker flags for each
                build type. Future versions of Gradle will automatically include the appropriate debug flags for any 'debug' build
                type, and may be aware of various levels of optimisation as well.
            </note>
            <para>
                If no build types are defined for a component, then all binaries are built with a single, default build type called 'debug'.
            </para>
        </section>

        <section id="native_binaries:target_platform">
            <title>Target platform</title>
            <para>
                An executable or library can be built to run on different operating systems and cpu architectures, with a variant being
                produced for each target platform.
                Gradle defines each target OS/architecture combination as a <apilink class="org.gradle.nativebinaries.Platform"/>, and
                a project may be configured with different <literal>targetPlatforms</literal>.
            </para>
            <sample id="targetPlatforms" dir="native-binaries/variants" title="Defining target platforms">
                <sourcefile file="build.gradle" snippet="target-platforms"/>
            </sample>
            <note>
                When a platform does not define an architecture or operating system, the default target of the tool chain
                is assumed. In the example above, the <literal>operatingSystem</literal> is not defined, so Gradle will assume that the tool chain
                is configured to build for the correct operating system, and will not supply any specific
                compiler/linker flags to target a particular operating system.
            </note>
            <para>
                The core Gradle tool chains support the following architectures out of the box. There is not currently any core
                support for building for different operating systems.
            </para>
            <table>
                <thread>
                    <tr><td>Tool Chain</td><td>Architectures</td></tr>
                </thread>
                <tr>
                    <td>GCC</td><td>x86, x86_64</td>
                </tr>
                <tr>
                    <td>Clang</td><td>x86, x86_64</td>
                </tr>
                <tr>
                    <td>Visual C++</td><td>x86, x86_64, ia-64</td>
                </tr>
            </table>

            <para>
                Cross-compiling is possible with the <apilink class="org.gradle.nativebinaries.toolchain.Gcc"/> and <apilink class="org.gradle.nativebinaries.toolchain.Clang"/> tool chains,
                by programmatically adding support for additional target platforms.
                This is done using the <apilink class="org.gradle.nativebinaries.toolchain.PlatformConfigurableToolChain"/> API.
                Each added <apilink class="org.gradle.nativebinaries.toolchain.TargetPlatformConfiguration"/> defines support for a particular target platform,
                and supplies additional tool arguments that are required to target this platform.
            </para>

            <note>
                There is no direct support for cross platform source configuration (à la <ulink url="http://www.gnu.org/s/autoconf/">autoconf</ulink>) at this time.
            </note>

            <para>
                If no target platforms are defined for a project, then all binaries are built to target a default platform
                which does not specify an <literal>architecture</literal> or <literal>operatingSystem</literal>, hence using the tool chain default.
            </para>
        </section>

        <section id="native_binaries:flavor">
            <title>Flavor</title>
            <para>
                Each component can have a set of named <literal>flavors</literal>, and a separate binary variant can be produced for each flavor.
                While the <literal>build type</literal> and <literal>target platform</literal> variant dimensions have a defined meaning in Gradle,
                each project is free to define any number of flavors and apply meaning to them in any way.
            </para>
            <para>
                An example of component flavors might differentiate between 'demo', 'paid' and 'enterprise' editions of the component,
                where the same set of sources is used to produce binaries with different functions.
            </para>
            <sample id="flavors" dir="native-binaries/flavors" title="Defining component flavors">
                <sourcefile file="build.gradle" snippet="flavors"/>
            </sample>
            <para>
                In the above example, a library is defined with a 'english' and 'french' flavor. When compiling the 'french'
                variant, a separate macro is defined which leads to a different binary being produced.
            </para>
            <para>
                If no flavor is defined for a component, then a single default flavor named 'default' is used.
            </para>
        </section>
        <section id="native_binaries:tool_chain">
            <title>Tool chain</title>
            <para>
                Within a single build it is possible to build the same component with different tool chains. To do so, the set
                of tool chains for a project must be explicitly configured, and a separate variant will be produced for each
                available tool chain. Attempting to build the variant for a tool chain that is not available on the current
                machine will result in an error.
            </para>
            <sample id="toolChains" dir="native-binaries/tool-chains" title="Defining tool chains">
                <sourcefile file="build.gradle" snippet="toolChains"/>
            </sample>
            <para>
                The supported tool chain types are:
            </para>
            <itemizedlist>
                <listitem>
                    <para><apilink class="org.gradle.nativebinaries.toolchain.Gcc"/></para>
                </listitem>
                <listitem>
                    <para><apilink class="org.gradle.nativebinaries.toolchain.Clang"/></para>
                </listitem>
                <listitem>
                    <para><apilink class="org.gradle.nativebinaries.toolchain.VisualCpp"/></para>
                </listitem>
            </itemizedlist>
            <para>
                Each tool chain implementation allows for a certain degree of configuration (see the API documentation for more details).
            </para>
        </section>
        <section>
            <title>Building all possible variants</title>
            <para>
                When a set of build types, target platforms, flavors and tool chains is defined for a component,
                a <apilink class="org.gradle.nativebinaries.NativeBinary"/> model element is created for every possible
                combination of these. However, in many cases it is not possible to build a particular variant, perhaps because
                the tool chain for that variant is not available on the current machine, or the tool chain is not able to build
                for the specified target architecture.
            </para>
            <para>
                If a binary variant cannot be built for any reason, then the <apilink class="org.gradle.nativebinaries.NativeBinary"/>
                associated with that variant will not be <literal>buildable</literal>. It is possible to use this property to create a task
                to generate all possible variants on a particular machine.
            </para>
            <sample id="buildable" dir="native-binaries/tool-chains" title="Building all possible variants">
                <sourcefile file="build.gradle" snippet="buildable"/>
            </sample>
        </section>
    </section>

    <section>
        <title>Publishing</title>
        <para>
            The <literal>cpp-exe</literal> and <literal>cpp-lib</literal> plugins configure their respective output binaries to be publishable as part of the
            <literal>archives</literal> configuration. To publish, simply configure the <literal>uploadArchives</literal> task as per usual.
        </para>
        <sample id="cppPublish" dir="native-binaries/dependencies" title="Uploading exe or lib">
            <sourcefile file="build.gradle" snippet="upload"/>
        </sample>
        <para>
            The <literal>cpp-exe</literal> plugin publishes a single artifact with extension “<literal>exe</literal>”. The <literal>cpp-lib</literal> plugin
            publishes two artifacts; one with classifier “<literal>headers</literal>” and extension “<literal>zip</literal>”, and one with classifier
            “<literal>so</literal>” and extension “<literal>so</literal>” (which is the format used when consuming dependencies).
        </para>
        <note>
            <para>
                Currently, there is no support for publishing the dependencies of artifacts in POM or Ivy files. Future versions will support this.
            </para>
        </note>
    </section>

</chapter>