23 个版本
0.2.5 | 2023 年 2 月 4 日 |
---|---|
0.2.4 | 2022 年 7 月 10 日 |
0.2.2 | 2022 年 6 月 25 日 |
0.2.1 | 2020 年 6 月 30 日 |
0.1.2 | 2016 年 12 月 31 日 |
#13 in 构建工具
69,007 个月下载
用于 2 crates
510KB
9K SLoC
cross
“零配置”交叉编译和 Rust crate 的“交叉测试”
该项目由 cross-rs 团队开发和维护。之前由 Rust 嵌入式工作组工具团队维护。欢迎新贡献者!请加入我们的 Matrix 房间 并打个招呼。
`cross test` aarch64-unknown-linux-gnu 目标上的 crate
特性
-
cross
将提供所有交叉编译所需的组件,而无需触及您的系统安装。 -
cross
提供一个环境、交叉工具链和交叉编译的库,可以产生最可移植的二进制文件。 -
“交叉测试”,
cross
可以测试除了 i686 和 x86_64 之外的架构的 crate。 -
支持稳定、Beta 和 Nightly 通道。
依赖关系
-
需要具有 binfmt_misc 支持的 Linux 内核进行交叉测试。
需要以下之一容器引擎。如果两个都安装了,cross
将默认使用 docker
。
- Podman。需要版本 1.6.3 或更高。
安装
$ cargo install cross --git https://github.com/cross-rs/cross
使用方法
cross
与 Cargo 完全相同的 CLI,但依赖于 Docker 或 Podman。对于 Docker,您必须启动守护进程才能使用它。
# (ONCE PER BOOT, on Linux)
# Start the Docker daemon, if it's not already running using systemd
# on WSL2 and other systems using SysVinit, use `sudo service docker start`.
$ sudo systemctl start docker
# MAGIC! This Just Works
$ cross build --target aarch64-unknown-linux-gnu
# EVEN MORE MAGICAL! This also Just Works
$ cross test --target mips64-unknown-linux-gnuabi64
# Obviously, this also Just Works
$ cross rustc --target powerpc-unknown-linux-gnu --release -- -C lto
更多文档可以在维基百科上找到。
配置
您有三种方式配置cross
。所有这些选项都使用TOML格式进行配置,可能的配置值在此文档中进行了说明。
选项1:在您的Cargo.toml
中直接配置cross
您可以直接在Cargo.toml
文件中设置配置值,在[package.metadata.cross]
表中,即键前缀下。一个示例配置片段如下
[package.metadata.cross.target.aarch64-unknown-linux-gnu]
xargo = false
image = "test-image"
runner = "custom-runner"
选项2:通过Cross.toml
文件配置cross
您可以将配置放入项目根目录下的Cross.toml
文件中。
选项3:使用CROSS_CONFIG
指定配置文件的位置
通过设置环境变量CROSS_CONFIG
,您可以告诉cross
在哪里搜索配置文件。这样您就不仅限于项目根目录下的Cross.toml
文件。
自定义Docker镜像
cross
为以下目标提供了默认Docker镜像。然而,它无法涵盖每一个使用场景。对于其他目标或当默认镜像不足时,您可以在Cross.toml
中使用target.{{TARGET}}.image
字段来使用特定目标的自定义Docker镜像
[target.aarch64-unknown-linux-gnu]
image = "my/image:tag"
在上面的示例中,cross
将使用名为my/image:tag
的镜像而不是默认镜像。正常Docker行为适用,所以
-
Docker将首先寻找本地名为
my/image:tag
的镜像 -
如果找不到本地镜像,则会在Docker Hub中寻找。
-
如果只指定了
image:tag
,则Docker不会在Docker Hub中寻找。 -
如果省略了
tag
,则Docker将使用latest
标签。
Dockerfile
如果您使用自定义Dockerfile,可以使用target.{{TARGET}}.dockerfile
来自动构建它
[target.aarch64-unknown-linux-gnu]
dockerfile = "./path/to/where/the/Dockerfile/resides"
cross
将构建并使用构建的镜像而不是默认镜像。
建议您基于跨平台使用的默认Docker镜像创建自定义镜像:ghcr.io/cross-rs/{{TARGET}}:{{VERSION}}
(其中 {{VERSION}}
是cross的版本)。这样您就不必在自定义镜像中了解如何安装cross C工具链。
FROM ghcr.io/cross-rs/aarch64-unknown-linux-gnu:latest
RUN dpkg --add-architecture arm64 && \
apt-get update && \
apt-get install --assume-yes libfoo:arm64
如果您想由cross提供FROM
指令,可以执行以下操作
ARG CROSS_BASE_IMAGE
FROM $CROSS_BASE_IMAGE
RUN ...
预构建钩子
cross
允许您在使用镜像之前添加依赖项并运行其他必要命令。此操作将被添加到使用的镜像中,因此每次使用cross
时都不会运行/构建。
[target.x86_64-unknown-linux-gnu]
pre-build = ["dpkg --add-architecture arm64 && apt-get update && apt-get install --assume-yes libfoo:arm64"]
Docker in Docker
当在容器内运行cross
时,cross
需要访问宿主机的docker守护进程本身。这通常是通过挂载docker守护进程套接字/var/run/docker.sock
来实现的。例如
$ docker run -v /var/run/docker.sock:/var/run/docker.sock -v .:/project \
-w /project my/development-image:tag cross build --target mips64-unknown-linux-gnuabi64
运行cross
的镜像需要安装rust开发工具。
使用此设置,cross
必须找到并挂载正确的宿主路径到用于交叉编译的容器中。这包括原始项目目录以及父容器的根路径,以便访问rust构建工具。
为了通知cross
它正在容器内运行,请设置CROSS_CONTAINER_IN_CONTAINER=true
。
可以创建如下开发或CI容器
FROM rust:1
# set CROSS_CONTAINER_IN_CONTAINER to inform `cross` that it is executed from within a container
ENV CROSS_CONTAINER_IN_CONTAINER=true
# install `cross`
RUN cargo install cross
...
限制:目前只有overlayfs2存储驱动程序可以找到容器根目录的挂载点。为了访问父容器的rust设置,子容器挂载了父容器的overlayfs。在子容器启动之前,父容器不得停止,因为如果子容器仍在访问它,Docker无法正确卸载overlayfs。
显式选择容器引擎
默认情况下,cross
会尝试按顺序使用Docker或Podman。如果您想显式选择容器引擎,可以使用CROSS_CONTAINER_ENGINE
环境变量设置二进制名称(或路径)。
例如,如果您想使用Podman,可以设置CROSS_CONTAINER_ENGINE=podman
。
将环境变量传递到构建环境
默认情况下,cross
不会将任何环境变量从调用shell传递到构建环境。这是一个安全默认值,因为大多数用例不会希望调用环境泄露到内部执行环境。
在确实需要传递环境变量的情况下,您可以通过build.env.passthrough
在您的Cross.toml
中完成此操作
[build.env]
passthrough = [
"RUST_BACKTRACE",
"RUST_LOG",
"TRAVIS",
]
要为单个目标传递变量而不传递给其他目标,可以使用此语法
[target.aarch64-unknown-linux-gnu.env]
passthrough = [
"RUST_DEBUG",
]
不稳定功能
某些不稳定功能可以启用对交叉编译有用的附加功能。请注意,这些功能是不稳定的,并且可能会在任何时候删除(尤其是如果功能已稳定或删除),并且仅在夜间频道中使用。
CROSS_UNSTABLE_ENABLE_DOCTESTS=true
:同时运行文档测试。
将卷挂载到构建环境中
除了传递环境变量外,还可以指定指向应挂载到容器中的路径的环境变量
[target.aarch64-unknown-linux-gnu.env]
volumes = [
"BUILD_DIR",
]
使用 Xargo 代替 Cargo
默认情况下,cross
仅使用 xargo
为所有非标准目标(即 rustc/rustup 未报告的目标)构建您的 Cargo 项目。但是,您可以在 Cross.toml
中使用 build.xargo
或 target.{{TARGET}}.xargo
字段来强制使用 xargo
# all the targets will use `xargo`
[build]
xargo = true
或者,
# only this target will use `xargo`
[target.aarch64-unknown-linux-gnu]
xargo = true
xargo = false
将以相反的方式工作(始终选择 cargo)并且在为已知与 cargo 一起工作的自定义目标构建时非常有用。
支持的目标
如果 cross
可以针对该目标交叉编译一个“非平凡”的(二进制)crate(通常是 Cargo),则认为该目标为“受支持的”。
测试支持(cross test
)更复杂。它依赖于 QEMU 模拟,因此测试可能会因为 QEMU 的错误而不是 crate 的错误而失败。话虽如此,如果目标可以在下表的 test
列中运行 compiler-builtins
测试套件,则该目标有一个 ✓。
此外,测试非常慢。由于 QEMU 在您生成多个线程时会变得不高兴,因此 cross test
会按顺序运行单元测试。这意味着,如果您的单元测试中生成了线程,那么它更有可能失败,或者最糟糕的是,永远不会终止。
目标 | libc | GCC | C++ | QEMU | 测试 |
---|---|---|---|---|---|
aarch64-linux-android [1] |
9.0.8 | 9.0.8 | ✓ | 6.1.0 | ✓ |
aarch64-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
aarch64-unknown-linux-musl |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
arm-linux-androideabi [1] |
9.0.8 | 9.0.8 | ✓ | 6.1.0 | ✓ |
arm-unknown-linux-gnueabi |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
arm-unknown-linux-gnueabihf |
2.17 | 8.3.0 | ✓ | 6.1.0 | ✓ |
arm-unknown-linux-musleabi |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
arm-unknown-linux-musleabihf |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
armv5te-unknown-linux-gnueabi |
2.27 | 7.5.0 | ✓ | 6.1.0 | ✓ |
armv5te-unknown-linux-musleabi |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
armv7-linux-androideabi [1] |
9.0.8 | 9.0.8 | ✓ | 6.1.0 | ✓ |
armv7-unknown-linux-gnueabi |
2.27 | 7.5.0 | ✓ | 6.1.0 | ✓ |
armv7-unknown-linux-gnueabihf |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
armv7-unknown-linux-musleabi |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
armv7-unknown-linux-musleabihf |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
i586-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | N/A | ✓ |
i586-unknown-linux-musl |
1.1.24 | 9.2.0 | ✓ | N/A | ✓ |
i686-unknown-freebsd |
1.5 | 6.4.0 | ✓ | N/A | |
i686-linux-android [1] |
9.0.8 | 9.0.8 | ✓ | 6.1.0 | ✓ |
i686-pc-windows-gnu |
N/A | 7.5 | ✓ | N/A | ✓ |
i686-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
i686-unknown-linux-musl |
1.1.24 | 9.2.0 | ✓ | N/A | ✓ |
mips-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
mips-unknown-linux-musl |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
mips64-unknown-linux-gnuabi64 |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
mips64-unknown-linux-muslabi64 |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
mips64el-unknown-linux-gnuabi64 |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
mips64el-unknown-linux-muslabi64 |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
mipsel-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
mipsel-unknown-linux-musl |
1.1.24 | 9.2.0 | ✓ | 6.1.0 | ✓ |
powerpc-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
powerpc64-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
powerpc64le-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
riscv64gc-unknown-linux-gnu |
2.27 | 7.5.0 | ✓ | 6.1.0 | ✓ |
s390x-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
sparc64-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
sparcv9-sun-solaris |
1.22.7 | 8.4.0 | ✓ | N/A | |
thumbv6m-none-eabi [4] |
2.2.0 | 4.9.3 | N/A | ||
thumbv7em-none-eabi [4] |
2.2.0 | 4.9.3 | N/A | ||
thumbv7em-none-eabihf [4] |
2.2.0 | 4.9.3 | N/A | ||
thumbv7m-none-eabi [4] |
2.2.0 | 4.9.3 | N/A | ||
thumbv7neon-linux-androideabi [1] |
9.0.8 | 9.0.8 | ✓ | 6.1.0 | ✓ |
thumbv7neon-unknown-linux-gnueabihf |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
wasm32-unknown-emscripten [6] |
3.1.14 | 15.0.0 | ✓ | N/A | ✓ |
x86_64-linux-android [1] |
9.0.8 | 9.0.8 | ✓ | 6.1.0 | ✓ |
x86_64-pc-windows-gnu |
N/A | 7.3 | ✓ | N/A | ✓ |
x86_64-sun-solaris |
1.22.7 | 8.4.0 | ✓ | N/A | |
x86_64-unknown-freebsd |
1.5 | 6.4.0 | ✓ | N/A | |
x86_64-unknown-dragonfly [2] [3] |
6.0.1 | 5.3.0 | ✓ | N/A | |
x86_64-unknown-illumos |
1.20.4 | 8.4.0 | ✓ | N/A | |
x86_64-unknown-linux-gnu |
2.23 | 5.4.0 | ✓ | 5.1.0 | ✓ |
x86_64-unknown-linux-gnu:centos [5] |
2.17 | 4.8.5 | ✓ | 4.2.1 | ✓ |
x86_64-unknown-linux-musl |
1.1.24 | 9.2.0 | ✓ | N/A | ✓ |
x86_64-unknown-netbsd [3] |
9.2.0 | 9.4.0 | ✓ | N/A |
[1] libc = bionic; 仅适用于原生测试,即不依赖于Android运行时的测试。对于i686,一些测试可能因错误 assertion failed: signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR
而失败,更多信息请参阅 问题 #140。
[2] 无 std
组件可用。
[3] 对于一些 *BSD 和 Solaris 目标,libc 列表示从其中提取 libc 的操作系统发布版本。
[4] libc = newlib
[5] 必须在 Cross.toml
中将 [target.x86_64-unknown-linux-gnu]
中的 image = "x86_64-unknown-linux-gnu:main-centos"
修改为使用兼容 CentOS7 的目标。
[6] libc = emscripten 和 GCC = clang
其他目标的额外 Dockerfile 可以在 cross-toolchains 中找到。这些包括我们无法提供预构建镜像的 MSVC 和 Apple Darwin 目标。
调试
QEMU_STRACE (v0.1.9+)
当您使用 cross run
时,可以设置 QEMU_STRACE 变量以获取“外国”(非 x86_64)二进制的系统调用回溯。
$ cargo new --bin hello && cd $_
$ QEMU_STRACE=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 exit_group(0)
最低支持 Rust 版本 (MSRV)
此包保证在稳定 Rust 1.58.1 及以上版本中编译。它 可能 可以使用较旧版本编译,但可能会在任何新补丁版本中更改。
某些交叉编译目标需要更高的 Rust 版本,使用 Xargo 需要 nightly Rust 工具链。
许可
根据您的选择,许可为以下之一
- Apache License,版本 2.0 (LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
。
贡献
除非您明确声明,否则您提交的任何旨在包含在作品中的贡献,根据 Apache-2.0 许可证的定义,将根据上述方式双许可,不附加任何额外条款或条件。
行为准则
依赖关系
~9–20MB
~289K SLoC