# Chapter 54. Building native binaries

The Gradle support for building native binaries is currently incubating. Please be aware that the DSL and other configuration may change in later Gradle versions.

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.

## 54.1. Tool chain support

Gradle offers the ability to execute the same build using different tool chains. You can control 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.

The following tool chains are supported:

Operating System | Tool Chain | Notes
Linux | GCC |
Linux | Clang |
Mac OS X | GCC | Using GCC distributed with XCode.
Mac OS X | Clang | Using Clang distributed with XCode.
Windows | Visual C++ | Windows XP and later, Visual C++ 2010 and later.
Windows | GCC | Windows XP and later, using GCC distributed with Cygwin.
Windows | MinGW | Windows XP and later.

## 54.2. Component model

A native binary project defines a set of `Executable` and `Library` components, each of which Gradle maps to a number of `NativeBinary` outputs. For each `executable` or `library` defined, Gradle adds a `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.

To build either a static or shared native library binary, a `Library` component is added to the `libraries` container. Each `library` component can produce at least one `SharedLibraryBinary` and at least one `StaticLibraryBinary`.

Example 54.1. Defining a library component

`build.gradle`

    libraries {
        hello {}
    }

To build an executable binary, an `Executable` component is added to the `executables` container and associated with a set of sources.

Example 54.2. Defining executable components

`build.gradle`

    executables {
        main {}
    }

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 `variant`. Binary variants are discussed in detail below.

## 54.3. Tasks

For each `NativeBinary` that can be produced by a build, a single lifecycle task is constructed that can be used to create that binary, together with a set of other tasks that do the actual work of compiling, linking or assembling the binary.

Component Type | Native Binary Type | Lifecycle task | Location of created binary
`Executable` | `ExecutableBinary` | ``$component.name`Executable` | ``$buildDir`/binaries/`$binary.name`/`$component.name``
`Library` | `SharedLibraryBinary` | ``$component.name`SharedLibrary` | ``$buildDir`/binaries/`$binary.name`/lib`$component.name`.so`
`Library` | `StaticLibraryBinary` | ``$component.name`StaticLibrary` | ``$buildDir`/binaries/`$binary.name`/`$component.name`.a`

### 54.3.1. Working with shared libraries

For each executable binary produced, the `cpp` plugin provides an `install${binary.name}` 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.

## 54.4. Core language support: C, C++ and Assembler

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 `FunctionalSourceSet` instances (eg 'main', 'test', etc), each of which can contain `LanguageSourceSet`s containing C++, C or Assembler source files.

### 54.4.1. C++ sources

C++ language support is provided by means of the `'cpp'` plugin.

Example 54.3. The 'cpp' plugin

`build.gradle`

    apply plugin: 'cpp'

C++ sources to be included in a native binary are provided via a `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 `CppSourceSet` contains `.cpp` source files in `src/${name}/cpp`, and header files in `src/${name}/headers`.

While the `cpp` plugin defines these default locations for each `CppSourceSet`, it is possible to extend or override these defaults to allow for a different project layout.

Example 54.4. C++ source set

`build.gradle`

    sources {
        main {
            cpp {
                source {
                    srcDir "src/source"
                    include "**/*.cpp"
                }
            }
        }
    }

For a library named 'main', files in `src/main/headers` are considered the “public” or “exported” headers. Header files that should not be exported (but are used internally) should be placed inside the `src/main/cpp` directory (though be aware that such header files should always be referenced in a manner relative to the file including them).

### 54.4.2. C sources

C language support is provided by means of the `'c'` plugin.

Example 54.5. The 'c' plugin

`build.gradle`

    apply plugin: 'c'

C sources to be included in a native binary are provided via a `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 `CSourceSet` contains `.c` source files in `src/${name}/c`, and header files in `src/${name}/headers`.

While the `c` plugin defines these default locations for each `CSourceSet`, it is possible to extend or override these defaults to allow for a different project layout.

Example 54.6. C source set

`build.gradle`

    sources {
        hello {
            c {
                source {
                    srcDir "src/source"
                    include "**/*.c"
                }
                exportedHeaders {
                    srcDir "src/include"
                }
            }
        }
    }

For a library named 'main', files in `src/main/headers` are considered the “public” or “exported” headers. Header files that should not be exported (but are used internally) should be placed inside the `src/main/c` directory (though be aware that such header files should always be referenced in a manner relative to the file including them).

### 54.4.3. Assembler sources

Assembly language support is provided by means of the `'assembler'` plugin.

Example 54.7. The 'assembler' plugin

`build.gradle`

    apply plugin: 'assembler'

Assembler sources to be included in a native binary are provided via a `AssemblerSourceSet`, which defines a set of Assembler source files. By default, for any named component the `AssemblerSourceSet` contains `.s` source files under `src/${name}/asm`.

## 54.5. Configuring the compiler, assembler and linker

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.

Example 54.8. Settings that apply to all binaries

`build.gradle`

    binaries.all {
        // Define a preprocessor macro for every binary
        cppCompiler.define "NDEBUG"

        // Define toolchain-specific compiler and linker options
        if (toolChain in Gcc) {
            cppCompiler.args "-O2", "-fno-access-control"
            linker.args "-S"
        }
        if (toolChain in VisualCpp) {
            cppCompiler.args "/Zi"
            linker.args "/DEBUG"
        }
    }

Each binary is associated with a particular `ToolChain`, allowing settings to be targeted based on this value.

It is easy to apply settings to all binaries of a particular type:

Example 54.9. Settings that apply to all shared libraries

`build.gradle`

    // For any shared library binaries built with Visual C++, define the DLL_EXPORT macro
    binaries.withType(SharedLibraryBinary) {
        if (toolChain in VisualCpp) {
            cCompiler.args "/Zi"
            cCompiler.define "DLL_EXPORT"
        }
    }

Furthermore, it is possible to specify settings that apply to all binaries produces for a particular `executable` or `library` component:

Example 54.10. Settings that apply to all binaries produced for the 'main' executable component

`build.gradle`

    executables {
        main {
            binaries.all {
                if (toolChain in VisualCpp) {
                    assembler.args "/Zi"
                } else {
                    assembler.args "-g"
                }
            }
        }
    }

The above example will apply the supplied configuration to all `executable` binaries built.

Similarly, settings can be specified to target binaries for a component that are of a particular type: eg all `shared libraries` for the `main library` component.

Example 54.11. Settings that apply only to shared libraries produced for the 'main' library component

`build.gradle`

    libraries {
        main {
            binaries.withType(SharedLibraryBinary) {
                // Define a preprocessor macro that only applies to shared libraries
                cppCompiler.define "DLL_EXPORT"
            }
        }
    }

## 54.6. Windows Resources

When using the `VisualCpp` tool chain, Gradle is able to compile Window Resource (`rc`) files and link them into a native binary. This functionality is provided by the `'windows-resources'` plugin.

Example 54.12. The 'windows-resources' plugin

`build.gradle`

    apply plugin: 'windows-resources'

Windows resources to be included in a native binary are provided via a `WindowsResourceSet`, which defines a set of Windows Resource source files. By default, for any named component the `WindowsResourceSet` contains `.rc` source files under `src/${name}/rc`.

As with other source types, you can configure the location of the windows resources that should in included in the binary.

Example 54.13. Configuring the location of Windows resource sources

`build-resource-only-dll.gradle`

    sources {
        helloResources {
            rc {
                source {
                    srcDirs "src/hello/rc"
                }
                exportedHeaders {
                    srcDirs "src/hello/headers"
                }
            }
        }
    }

You are able to construct a resource-only library by providing Windows Resource sources with no other language sources, and configure the linker as appropriate:

Example 54.14. Building a resource-only dll

`build-resource-only-dll.gradle`

    libraries {
        helloResources {
            binaries.all {
                rcCompiler.args "/v"
                linker.args "/noentry", "/machine:x86"
            }
        }
    }

The above example also demonstrates the mechanism of passing extra command-line arguments to the resource compiler. The `rcCompiler` extension is of type `PreprocessingTool`.

## 54.7. Library Dependencies

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.

### 54.7.1. Dependencies within the same project

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.

Such a library dependency can be easily provided to source set associated with the `executable` component:

Example 54.15. Providing a library dependency to the source set

`build.gradle`

    sources {
        main {
            cpp {
                lib libraries.hello
            }
        }
    }

Alternatively, a library dependency can be provided directly to the `ExecutableBinary` for the `executable`.

Example 54.16. Providing a library dependency to the binary

`build.gradle`

    executables {
        main {
            binaries.all {
                // Each executable binary produced uses the 'hello' static library binary
                lib libraries.hello.static
            }
        }
    }

### 54.7.2. Project Dependencies

For a component produced in a different Gradle project, the notation is similar.

Example 54.17. Declaring project dependencies

`build.gradle`

    project(":lib") {
        apply plugin: "cpp-lib"
    }

    project(":exe") {
        apply plugin: "cpp-exe"
        evaluationDependsOn(":lib")

        sources {
            main {
                cpp {
                    lib project(":lib").libraries.main
                }
            }
        }
    }

## 54.8. Native Binary Variants

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.

Binaries produced by Gradle can be differentiated on build type, target platform, flavor and tool chain.

### 54.8.1. Build type

The `build type` 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.

Example 54.18. Defining build types

`build.gradle`

    buildTypes {
        debug {}
        release {}
    }

For a build type, a Gradle project will typically define a set of compiler/linker flags per tool chain.

Example 54.19. Configuring debug binaries

`build.gradle`

    binaries.all {
        if (toolChain in Gcc && buildType == buildTypes.debug) {
            cppCompiler.args "-g"
        }
        if (toolChain in VisualCpp && buildType == buildTypes.debug) {
            cppCompiler.args '/Zi'
            cppCompiler.define 'DEBUG'
            linker.args '/DEBUG'
        }
    }

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.

If no build types are defined for a component, then all binaries are built with a single, default build type called 'debug'.

### 54.8.2. Target platform

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 `Platform`, and a project may be configured with different `targetPlatforms`.

Example 54.20. Defining target platforms

`build.gradle`

    targetPlatforms {
        x86 {
            architecture "x86"
        }
        x64 {
            architecture "x86_64"
        }
        itanium {
            architecture "ia-64"
        }
    }

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 `operatingSystem` 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.

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.

Tool Chain | Architectures
GCC | x86, x86_64
Clang | x86, x86_64
Visual C++ | x86, x86_64, ia-64

Cross-compiling is possible with the `Gcc` and `Clang` tool chains, by programmatically adding support for additional target platforms. This is done using the `PlatformConfigurableToolChain` API. Each added `TargetPlatformConfiguration` defines support for a particular target platform, and supplies additional tool arguments that are required to target this platform.

There is no direct support for cross platform source configuration (à la autoconf) at this time.

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

### 54.8.3. Flavor

Each component can have a set of named `flavors`, and a separate binary variant can be produced for each flavor. While the `build type` and `target platform` 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.

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.

Example 54.21. Defining component flavors

`build.gradle`

    libraries {
        hello {
            flavors {
                english {}
                french {}
            }
            binaries.all {
                if (flavor == flavors.french) {
                    cppCompiler.define "FRENCH"
                }
            }
            source sources.lib
        }
    }

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.

If no flavor is defined for a component, then a single default flavor named 'default' is used.

### 54.8.4. Tool chain

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.

Example 54.22. Defining tool chains

`build.gradle`

    toolChains {
        visualCpp(VisualCpp) {
            // Specify the installDir if Visual Studio cannot be located by default
            // installDir "C:/Apps/Microsoft Visual Studio 10.0"
        }
        gcc(Gcc) {
            // Uncomment to use a GCC install that is not in the PATH
            // path "/usr/bin/gcc"
        }
        clang(Clang)
    }

The supported tool chain types are:

- `Gcc`

- `Clang`

- `VisualCpp`

Each tool chain implementation allows for a certain degree of configuration (see the API documentation for more details).

### 54.8.5. Building all possible variants

When a set of build types, target platforms, flavors and tool chains is defined for a component, a `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.

If a binary variant cannot be built for any reason, then the `NativeBinary` associated with that variant will not be `buildable`. It is possible to use this property to create a task to generate all possible variants on a particular machine.

Example 54.23. Building all possible variants

`build.gradle`

    task buildAllExecutables {
        dependsOn binaries.withType(ExecutableBinary).matching {
            it.buildable
        }
    }