Skip to content

Configuration

Emil Gardström edited this page Jan 31, 2023 · 32 revisions

Documentation for how to configure cross through config files and environment variables.

Table of Contents

Config File

You can place a Cross.toml file in the root of your Cargo project or use a CROSS_CONFIG environment variable to tweak cross's behavior. You can also use package.metadata.cross.KEY in Cargo.toml, and the priority of settings is environment variables override Cross.toml options, which override Cargo.toml options. An annotated examples of both Cross.toml and Cargo.toml are provided

For example, the [build] table in Cross.toml is identical to setting [package.metadata.cross.build] in Cargo.toml.

Format

The cross configuration in the Cross.toml file, can contain the following elements:

build

The build key allows you to set global variables, e.g.:

[build]
build-std = false                              # do not build the std library. has precedence over xargo
xargo = true                                   # enable the use of xargo by default
zig = false                                    # do not use zig cc for the builds
default-target = "x86_64-unknown-linux-gnu"    # use this target if none is explicitly provided
pre-build = [                                  # additional commands to run prior to building the package
    "dpkg --add-architecture $CROSS_DEB_ARCH", 
    "apt-get update && apt-get --assume-yes install libssl-dev:$CROSS_DEB_ARCH"
]                 

build.env

With the build.env key you can globally set volumes that should be mounted in the Docker container or environment variables that should be passed through. For example:

[build.env]
volumes = ["VOL1_ARG", "VOL2_ARG=/path/to/volume"]
passthrough = ["VAR1_ARG", "VAR2_ARG=VALUE"]

Note how in the environment variable passthrough, we can provide a definition for the variable as well. VAR1_ARG will be the value of the environment variable on the host, while VAR2_ARG will be VALUE. Likewise, the path to the volume for VOL1_ARG will be the value of the environment variable on the host, while VOL2_ARG will be /path/to/volume.

build.dockerfile

The build.dockerfile key lets you provide a custom Docker image for all targets, except those specified target.TARGET.dockerfile. You probably do not mean to use this. The value can be provided as either a table or a string. If build.dockerfile is set to a string, it's equivalent to setting build.dockerfile.file to that value. For example, using only a string:

[build]
dockerfile = "./Dockerfile"

Or using a table:

[build.dockerfile]
file = "./Dockerfile"         # the dockerfile to use relative to the `Cargo.toml`
context = "."                 # the context folder to build the script in. defaults to `.`
build-args = { ARG1 = "foo" } # https://docs.docker.com/engine/reference/builder/#arg

cross will provide the argument CROSS_BASE_IMAGE which points to the image cross would use for the target. Example:

ARG CROSS_BASE_IMAGE
FROM $CROSS_BASE_IMAGE
RUN ...

build.zig

The build.zig key lets you use zig cc as a cross-compiler, enabling cross-compilation to numerous architectures and glibc versions using a single Docker image. Note that zig cc doesn't support all targets: only a subset of our Linux GNU targets, so it might be better to set these values in target.TARGET.zig instead. The value can be provided as either a table, a bool, or a string. If build.zig is set to a string, it's equivalent to setting build.zig.version to that value and build.zig.enable to true:

[build]
zig = "2.17"

If build.zig is set to a bool, it's equivalent to setting build.zig.enable to that value:

[build]
zig = true

Or using a table:

[build.zig]
enable = true                 # enable or disable the use of zig cc
version = "2.17"              # the glibc version to use
image = "myimage"             # a custom image containing zig to use

target.TARGET

The target key allows you to specify parameters for specific compilation targets.

[target.aarch64-unknown-linux-gnu]
build-std = false          # always build the std library. has precedence over xargo
xargo = false              # disable the use of xargo
image = "test-image"       # use a different image for the target
runner = "qemu-user"       # wrapper to run the binary (must be `qemu-system`, `qemu-user`, or `native`).

target.TARGET.pre-build

The pre-build field can also reference a file to copy and run. This file is relative to the container context, which would be the workspace root, or the current directory if --manifest-path is used. For more involved scripts, consider using target.TARGET.dockerfile instead to directly control the execution.

This script will be invoked as RUN ./pre-build-script $CROSS_TARGET where $CROSS_TARGET is the target triple.

[target.aarch64-unknown-linux-gnu]
pre-build = "./scripts/my-script.sh"
$ cat ./scripts/my-script.sh
#!/usr/bin/env bash

apt-get install libssl-dev -y

target.TARGET.image

[target.aarch64-unknown-linux-gnu]
image = "my_image:latest"

The image key can also take the toolchains/platforms supported by the image.

[target.aarch64-unknown-linux-gnu]
image.name = "alpine:edge"
image.toolchain = ["x86_64-unknown-linux-musl", "linux/arm64=aarch64-unknown-linux-musl"] # Defaults to `x86_64-unknown-linux-gnu`

target.TARGET.env

The target key allows you to specify environment variables that should be used for a specific compilation target. This is similar to build.env, but allows you to be more specific per target.

[target.x86_64-unknown-linux-gnu.env]
volumes = ["VOL1_ARG", "VOL2_ARG=/path/to/volume"]
passthrough = ["VAR1_ARG", "VAR2_ARG=VALUE"]

target.TARGET.dockerfile

The target.(...).dockerfile key lets you provide a custom Docker image for the given target. The value can be provided as either a table or a string. If target.TARGET.dockerfile is set to a string, it's equivalent to setting target.(...).dockerfile.file to that value. For example, using only a string:

[target.aarch64-unknown-linux-gnu]
dockerfile = "./Dockerfile"

Or using a table:

[target.aarch64-unknown-linux-gnu.dockerfile]
file = "./Dockerfile"         # the dockerfile to use relative to the `Cargo.toml`
context = "."                 # the context folder to build the script in. defaults to `.`
build-args = { ARG1 = "foo" } # https://docs.docker.com/engine/reference/builder/#arg

target.TARGET.zig

The target.TARGET.zig key lets you use zig cc as a cross-compiler, enabling cross-compilation to numerous architectures and glibc versions using a single Docker image. The value can be provided as either a table, a bool, or a string. If target.TARGET.zig is set to a string, it's equivalent to setting target.TARGET.zig.version to that value and target.TARGET.zig.enable to true:

[target.aarch64-unknown-linux-gnu]
zig = "2.17"

If target.TARGET.zig is set to a bool, it's equivalent to setting target.TARGET.zig.enable to that value:

[target.aarch64-unknown-linux-gnu]
zig = true

Or using a table:

[target.aarch64-unknown-linux-gnu.zig]
enable = true                 # enable or disable the use of zig cc
version = "2.17"              # the glibc version to use
image = "myimage"             # a custom image containing zig to use

Custom Images

Custom images generated from config dockerfile or pre-build keys will export CROSS_DEB_ARCH, which allows you to install packages from Ubuntu/Debian repositories without having to specify the exact architecture. For example, to install OpenSSL for the target, you can do:

[target.aarch64-unknown-linux-gnu]
pre-build = [
  "dpkg --add-architecture $CROSS_DEB_ARCH", 
  "apt-get update && apt-get --assume-yes install libssl-dev:$CROSS_DEB_ARCH"
]

Here, CROSS_DEB_ARCH will automatically evaluate to arm64, without you having to explicitly provide it.

Environment Variables

Cross can be further customized by setting certain environment variables. In-depth documentation with examples can be found here.

  • CROSS_CONTAINER_ENGINE: The container engine to run cross in. Defaults to docker then podman, whichever is found first (example: docker, see the FAQ).
  • XARGO_HOME: Home for xargo (example: ~/.xargo).
  • NIX_STORE: The directory for the Nix store (example: /nix/store).
  • CROSS_CONTAINER_UID: Set the user identifier for the cross command (example: 1000).
  • CROSS_CONTAINER_GID: Set the group identifier for the cross command (example: 1000).
  • CROSS_CONTAINER_IN_CONTAINER: Inform cross that it is running inside a container (example: true, see the FAQ).
  • CROSS_CONTAINER_OPTS: Additional arguments to provide to the container engine during $engine run (example: --env MYVAR=1 where engine=docker).
  • CROSS_CONFIG: Specify the path to the cross config file (see Config File).
  • CROSS_BUILD_OPTS: Space separated flags to add when building a custom image, i.e --network=host
  • CROSS_DEBUG: Print debugging information for cross.
  • CROSS_COMPATIBILITY_VERSION: Use older cross behavior (example: 0.2.1).
  • CROSS_CUSTOM_TOOLCHAIN: Specify that rustup is using a custom toolchain, and therefore should not try to add targets/install components. Useful with cargo-bisect-rustc.
  • CROSS_REMOTE: Inform cross it is using a remote container engine, and use data volumes rather than local bind mounts. See Remote for more information using remote container engines.
  • QEMU_STRACE: Get a backtrace of of system calls from “foreign” (non x86_64) binaries when using cross run.
  • CARGO_BUILD_TARGET: Sets the default target, similar to specifying --target.
  • CROSS_ROOTLESS_CONTAINER_ENGINE: Specify whether to container engine runs as root or is rootless. If set to auto or not provided, it assumes docker runs as root and all other container engines are rootless.
  • CROSS_CONTAINER_USER_NAMESPACE: Custom the container user namespace. If set to none, user namespaces will be disabled. If not provided or set to auto, it will use the default namespace.
  • CROSS_CUSTOM_TOOLCHAIN_COMPAT: A descriptive name for a custom toolchain so cross can convert it to a fully-qualified toolchain name.
  • CROSS_CONTAINER_ENGINE_NO_BUILDKIT: The container engine does not have buildx command (or BuildKit support) when building custom images.

All config file options can also be specified using environment variables. For example, setting CROSS_BUILD_XARGO=1 is identical to setting build.xargo = true, and CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO=1 is identical to target.aarch64-unknown-linux-gnu.xargo = true.

Cargo Configuration

When cross-compiling, cargo does not use environment variables such as RUSTFLAGS, and must be provided using CARGO_TARGET_${TARGET}_${OPTION}. Please note that some of these may be provided by the image themselves, such as runners, and should be provided with caution. A list of important flags includes:

  • CARGO_TARGET_${TARGET}_LINKER: specify a custom linker passed to rustc.
  • CARGO_TARGET_${TARGET}_RUNNER: specify the wrapper to run executables.
  • CARGO_TARGET_${TARGET}_RUSTFLAGS: add additional flags passed to rustc.

Any of the following flags can be provided, and are converted to uppercase. For example, changing foo-bar would be provided as CARGO_TARGET_${TARGET}_FOO_BAR.

For example, to run binaries on i686-unknown-linux-gnu with Qemu, first create a custom image containing Qemu, and run with the following command:

CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_RUNNER=qemu-i386 cross run ...

Environment Variable Passthrough

By default, cross does not pass most environment variables into the build environment from the calling shell. This is chosen as a safe default as most use cases will not want the calling environment leaking into the inner execution environment. There are, however, some notable exceptions: most environment variables cross or cargo reads are passed through automatically to the build environment. The major exceptions are variables that are set by cross or conflict with our build environment, including:

  • CARGO_HOME
  • CARGO_TARGET_DIR
  • CARGO_BUILD_TARGET_DIR
  • CARGO_BUILD_RUSTC
  • CARGO_BUILD_RUSTC_WRAPPER
  • CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER
  • CARGO_BUILD_RUSTDOC
  • CROSS_RUNNER
  • CROSS_RUSTC_MAJOR_VERSION
  • CROSS_RUSTC_MINOR_VERSION
  • CROSS_RUSTC_PATCH_VERSION

Otherwise, any environment variables that start with CARGO_ or CROSS_, and a few others, will be available in the build environment. For example, RUSTFLAGS and CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS will both be automatically available in the build environment.

Unstable Features

Certain unstable features can enable additional functionality useful to cross-compiling. Note that these are unstable, and may be removed at any time (particularly if the feature is stabilized or removed), and will only be used on a nightly channel.

  • CROSS_UNSTABLE_ENABLE_DOCTESTS: enable or disable running doctests (example: true).