cross
“Zero setup” cross compilation and “cross testing” of Rust crates
This project is developed and maintained by the Tools team.
`cross test`ing a crate for the aarch64-unknown-linux-gnu target
cross
will provide all the ingredients needed for cross compilation without
touching your system installation.
cross
provides an environment, cross toolchain and cross compiled libraries
(e.g. OpenSSL), that produces the most portable binaries.
“cross testing”, cross
can test crates for architectures other than i686 and
x86_64.
The stable, beta and nightly channels are supported.
Docker. Note that on Linux non-sudo users need to be in the
docker
group. Read the official post-installation steps.
A Linux kernel with [binfmt_misc] support is required for cross testing.
$ cargo install cross
cross
has the exact same CLI as Cargo
but as it relies on Docker you'll have to start the daemon before you can use
it.
```
$ sudo systemctl start docker
$ cross build --target aarch64-unknown-linux-gnu
$ cross test --target mips64-unknown-linux-gnuabi64
$ cross rustc --target powerpc-unknown-linux-gnu --release -- -C lto ```
You can place a Cross.toml
file in the root of your Cargo project to tweak
cross
's behavior:
cross
provides default Docker images for the targets listed below. However, it
can't cover every single use case out there. For other targets, or when the
default image is not enough, you can use the target.{{TARGET}}.image
field in
Cross.toml
to use custom Docker image for a specific target:
toml
[target.aarch64-unknown-linux-gnu]
image = "my/image:tag"
In the example above, cross
will use a image named my/image:tag
instead of
the default one. Normal Docker behavior applies, so:
Docker will first look for a local image named my/image:tag
If it doesn't find a local image, then it will look in Docker Hub.
If only image:tag
is specified, then Docker won't look in Docker Hub.
If only tag
is omitted, then Docker will use the latest
tag.
It's recommended to base your custom image on the default Docker image that
cross uses: rustembedded/cross:{{TARGET}}-{{VERSION}}
(where {{VERSION}}
is cross's version).
This way you won't have to figure out how to install a cross C toolchain in your
custom image. Example below:
``` Dockerfile FROM rustembedded/cross:aarch64-unknown-linux-gnu-0.1.15
RUN dpkg --add-architecture arm64 && \ apt-get update && \ apt-get install libfoo:arm64 ```
$ docker build -t my/image:tag path/to/where/the/Dockerfile/resides
By default, cross
does not pass any 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.
In the instances that you do want to pass through environment variables, this
can be done via build.env.passthrough
in your Cross.toml
:
toml
[build.env]
passthrough = [
"RUST_BACKTRACE",
"RUST_LOG",
"TRAVIS",
]
To pass variables through for one target but not others, you can use this syntax instead:
toml
[target.aarch64-unknown-linux-gnu.env]
passthrough = [
"RUST_DEBUG",
]
By default, cross
uses cargo
to build your Cargo project unless you are
building for one of the thumbv*-none-eabi*
targets; in that case, it uses
xargo
. However, you can use the build.xargo
or target.{{TARGET}}.xargo
field
in Cross.toml
to force the use of xargo
:
``` toml
xargo
[build] xargo = true ```
Or,
``` toml
xargo
[target.aarch64-unknown-linux-gnu] xargo = true ```
Note that xargo = false
has no effect as you can't use cargo
with targets
that only support xargo
.
A target is considered as “supported” if cross
can cross compile a
“non-trivial” (binary) crate, usually Cargo, for that target.
Testing support (cross test
) is more complicated. It relies on [QEMU]
emulation, so testing may fail due to QEMU bugs rather than bugs in your crate.
That said, a target has a ✓ in test
column of the table below if it can run
the [compiler-builtins
] test suite.
Also, testing is very slow. cross test
runs units tests sequentially because
QEMU gets upset when you spawn multiple threads. This means that, if one of your
unit tests spawns threads, then it's more likely to fail or, worst, never
terminate.
| Target | libc | GCC | OpenSSL | C++ | QEMU | test
|
|--------------------------------------|--------|---------|---------|:---:|-------|:------:|
| aarch64-linux-android
[5] | N/A | 4.9 | 1.0.2p | ✓ | N/A | ✓ |
| aarch64-unknown-linux-gnu
| 2.19 | 4.8.2 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| aarch64-unknown-linux-musl
| 1.1.20 | 6.3.0 | 1.0.2p | | 2.8.0 | ✓ |
| arm-linux-androideabi
[5] | N/A | 4.9 | 1.0.2p | ✓ | N/A | ✓ |
| arm-unknown-linux-gnueabi
| 2.19 | 4.8.2 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| arm-unknown-linux-gnueabihf
| 2.27 | 7.3.0 | 1.0.2p | ✓ | 2.10 | ✓ |
| arm-unknown-linux-musleabi
| 1.1.20 | 6.3.0 | 1.0.2p | | 2.8.0 | ✓ |
| arm-unknown-linux-musleabihf
| 1.1.20 | 6.3.0 | 1.0.2p | | 2.8.0 | ✓ |
| armv5te-unknown-linux-musleabi
| 1.1.20 | 6.3.0 | N/A | | 2.8.0 | ✓ |
| armv7-linux-androideabi
[5] | N/A | 4.9 | 1.0.2p | ✓ | N/A | ✓ |
| armv7-unknown-linux-gnueabihf
| 2.15 | 4.6.2 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| armv7-unknown-linux-musleabihf
| 1.1.20 | 6.3.0 | 1.0.2p | | 2.8.0 | ✓ |
| asmjs-unknown-emscripten
[4] | 1.1.20 | 1.37.13 | N/A | ✓ | N/A | ✓ |
| i586-unknown-linux-gnu
| 2.23 | 5.3.1 | 1.0.2p | ✓ | N/A | ✓ |
| i586-unknown-linux-musl
| 1.1.20 | 6.3.0 | 1.0.2p | | N/A | ✓ |
| i686-linux-android
[5] | N/A | 4.9 | 1.0.2p | ✓ | N/A | ✓ |
| i686-pc-windows-gnu
| N/A | 7.3.0 | N/A | ✓ | N/A | ✓ |
| i686-unknown-freebsd
[1] | 10.2 | 5.3.0 | 1.0.2p | | N/A | |
| i686-unknown-linux-gnu
| 2.15 | 4.6.2 | 1.0.2p | ✓ | N/A | ✓ |
| i686-unknown-linux-musl
| 1.1.20 | 6.3.0 | 1.0.2p | | N/A | ✓ |
| mips-unknown-linux-gnu
| 2.23 | 5.3.1 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| mips-unknown-linux-musl
| 1.1.20 | 6.3.0 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| mips64-unknown-linux-gnuabi64
| 2.23 | 5.3.1 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| mips64el-unknown-linux-gnuabi64
| 2.23 | 5.3.1 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| mipsel-unknown-linux-gnu
| 2.23 | 5.3.1 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| mipsel-unknown-linux-musl
| 1.1.20 | 6.3.0 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| powerpc-unknown-linux-gnu
| 2.19 | 4.8.2 | 1.0.2p | ✓ | 2.7.1 | ✓ |
| powerpc64-unknown-linux-gnu
| 2.19 | 4.8.2 | 1.0.2p | ✓ | 2.7.1 | ✓ |
| powerpc64le-unknown-linux-gnu
| 2.19 | 4.8.2 | 1.0.2p | ✓ | 2.7.1 | ✓ |
| s390x-unknown-linux-gnu
| 2.23 | 5.3.1 | 1.0.2p | ✓ | 2.8.0 | |
| sparc64-unknown-linux-gnu
[2] | 2.23 | 5.3.1 | 1.0.2p | ✓ | 2.8.0 | ✓ |
| sparcv9-sun-solaris
[1] | 2.11 | 5.3.0 | 1.0.2p | ✓ | N/A | |
| thumbv6m-none-eabi
[3] | 2.2.0 | 5.3.1 | N/A | | N/A | |
| thumbv7em-none-eabi
[3] | 2.2.0 | 5.3.1 | N/A | | N/A | |
| thumbv7em-none-eabihf
[3] | 2.2.0 | 5.3.1 | N/A | | N/A | |
| thumbv7m-none-eabi
[3] | 2.2.0 | 5.3.1 | N/A | | N/A | |
| wasm32-unknown-emscripten
[4] | 1.1.15 | 1.37.13 | N/A | ✓ | N/A | ✓ |
| x86_64-linux-android
[5] | N/A | 4.9 | 1.0.2p | ✓ | N/A | ✓ |
| x86_64-pc-windows-gnu
| N/A | 7.3.0 | N/A | ✓ | N/A | ✓ |
| x86_64-sun-solaris
[1] | 2.11 | 5.3.0 | 1.0.2p | ✓ | N/A | |
| x86_64-unknown-dragonfly
[1] [2] | 4.6.0 | 5.3.0 | 1.0.2p | ✓ | N/A | |
| x86_64-unknown-freebsd
[1] | 10.2 | 5.3.0 | 1.0.2p | | N/A | |
| x86_64-unknown-linux-gnu
| 2.15 | 4.6.2 | 1.0.2p | ✓ | N/A | ✓ |
| x86_64-unknown-linux-musl
| 1.1.20 | 6.3.0 | 1.0.2p | | N/A | ✓ |
| x86_64-unknown-netbsd
[1] | 7.0 | 5.3.0 | 1.0.2p | ✓ | N/A | |
[1] For *BSD and Solaris targets, the libc column indicates the OS release version from where libc was extracted.
[2] No std
component available as of 2017-01-10
[3] libc = newlib
[4] libc = musl, gcc = emcc; Some projects that use libc may fail due to wrong definitions (will be fixed by https://github.com/rust-lang/libc/pull/610)
[5] Only works with native tests, that is, tests that do not depends on the
Android Runtime. For i686 some tests may fails with the error assertion
failed: signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR
, see
issue #140 for more
information.
You can set the QEMUSTRACE variable when you use cross run
to get a backtrace
of system calls from “foreign” (non x8664) binaries.
``` $ cargo new --bin hello && cd $_
$ QEMUSTRACE=1 cross run --target aarch64-unknown-linux-gnu 9 brk(NULL) = 0x0000004000023000 9 uname(0x4000823128) = 0 (..) 9 write(1,0xa06320,14)Hello, world! = 14 9 sigaltstack(0x4000823588,(nil)) = 0 9 munmap(0x0000004000b16000,16384) = 0 9 exitgroup(0) ```
path dependencies (in Cargo.toml) that point outside the Cargo project won't
work because cross
use docker containers only mounts the Cargo project so
the container doesn't have access to the rest of the filesystem.
cross
will mount the Cargo project as READ ONLY. Thus, if any crate attempts
to modify its “source”, the build will fail. Well behaved crates should only
ever write to $OUT_DIR
and never modify $CARGO_MANIFEST_DIR
though.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Contribution to this crate is organized under the terms of the Rust Code of Conduct, the maintainer of this crate, the Tools team, promises to intervene to uphold that code of conduct.