# Compilers and cross-compilation

To use a compiler in your project, it's best to use the `${{ compiler('lang')
}}` template function. The compiler function works by taking a language,
determining the configured compiler for that language, and adding some
information about the target platform to the selected compiler. To configure a
compiler for a specific language, the `variants.yaml` file can be used.

For example, in a recipe that uses a C-compiler, you can use the following code:

```yaml
requirements:
  build:
    - ${{ compiler('c') }}
```

To set the compiler that you want to use, create a variant config that looks
like the following:

```yaml
c_compiler:
  - gcc

# optionally you can specify a version
c_compiler_version:
  - 9.3.0
```

When the template function is evaluated, it will look something like:
`gcc_linux-64 9.3.0`. You can define your own compilers. For example, for Rust
you can use `${{ compiler('rust') }}` and `rust_compiler_{version}` in your
variant config.

### Default compilers

If no `{lang}_compiler` is set in the variant config, `compiler('c')` and
`compiler('cxx')` fall back to a per-platform default:

| Target platform             | `compiler('c')` | `compiler('cxx')` |
|-----------------------------|-----------------|-------------------|
| Windows                     | `vs2022`        | `vs2022`          |
| macOS, iOS, Android         | `clang`         | `clangxx`         |
| `emscripten-wasm32`         | `emscripten`    | `emscripten`      |
| Linux (and everything else) | `gcc`           | `gxx`             |

For `compiler('fortran')` the default is `flang` on Windows and `gfortran`
elsewhere. Any other language passes through unchanged, so `compiler('rust')`
resolves to `rust_{target_platform}`.

## Cross-compilation

Cross-compilation is supported by Rattler-Build and the compiler template
function is part of what makes it possible. When you want to cross-compile from
`linux-64` to `linux-aarch64` (i.e. intel to ARM), you can pass `--target-platform
linux-aarch64` to the `rattler-build` command. This will cause the compiler
template function to select a compiler that is configured for `linux-aarch64`.
The above example would resolve to `gcc_linux-aarch64 9.3.0`. Provided that the
package is available for `linux-64` (your build platform), the compilation
should succeed.

The distinction between the `build` and `host` sections begins to make sense when
thinking about cross-compilation. The `build` environment is resolved to
packages that need to _run_ at compilation time. For example, `cmake`, `gcc`,
and `autotools` are all tools that need to be executed. Therefore, the `build`
environment resolves to packages for the `linux-64` architecture (in our
example). On the other hand, the `host` packages resolve to `linux-aarch64` -
those are packages that we want to link against.

```yaml
# packages that need to run at build time (cmake, gcc, autotools, etc.)
# in the platform that Rattler-Build is executed on (the build_platform)
build:
  - cmake
  - ${{ compiler('c') }}
# packages that we want to link against in the architecture we are
# cross-compiling to the target_platform
host:
  - libcurl
  - openssl
```

### Builtin codesigning for macOS cross-compilation

When cross-compiling **to** macOS from a non-macOS host (e.g. Linux), the
system `codesign` tool is not available. In this case you can enable the
built-in ad-hoc codesigning by setting the `RATTLER_BUILD_BUILTIN_CODESIGN`
environment variable:

```bash
RATTLER_BUILD_BUILTIN_CODESIGN=1 rattler-build build --target-platform osx-arm64
```

This uses a pure-Rust implementation to ad-hoc sign Mach-O binaries after
relinking, removing the dependency on Apple's `codesign` utility.
