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 构建工具

Download history 20669/week @ 2024-03-14 19973/week @ 2024-03-21 16021/week @ 2024-03-28 18651/week @ 2024-04-04 20120/week @ 2024-04-11 18020/week @ 2024-04-18 19023/week @ 2024-04-25 22314/week @ 2024-05-02 17862/week @ 2024-05-09 19845/week @ 2024-05-16 20957/week @ 2024-05-23 18376/week @ 2024-05-30 16920/week @ 2024-06-06 18446/week @ 2024-06-13 17521/week @ 2024-06-20 13806/week @ 2024-06-27

69,007 个月下载
用于 2 crates

MIT/Apache

510KB
9K SLoC

Rust 7.5K SLoC // 0.0% comments Shell 1.5K SLoC // 0.1% comments

crates.io crates.io CI Matrix

cross

“零配置”交叉编译和 Rust crate 的“交叉测试”

该项目由 cross-rs 团队开发和维护。之前由 Rust 嵌入式工作组工具团队维护。欢迎新贡献者!请加入我们的 Matrix 房间 并打个招呼。

`cross test`ing a crate for the aarch64-unknown-linux-gnu target
`cross test` aarch64-unknown-linux-gnu 目标上的 crate

特性

  • cross 将提供所有交叉编译所需的组件,而无需触及您的系统安装。

  • cross 提供一个环境、交叉工具链和交叉编译的库,可以产生最可移植的二进制文件。

  • “交叉测试”,cross 可以测试除了 i686 和 x86_64 之外的架构的 crate。

  • 支持稳定、Beta 和 Nightly 通道。

依赖关系

需要以下之一容器引擎。如果两个都安装了,cross 将默认使用 docker

  • Docker。注意,在 Linux 上,非 sudo 用户需要加入 docker 组。请阅读官方的 安装步骤。需要版本 1.24 或更高。
  • Podman。需要版本 1.6.3 或更高。

安装

$ cargo install cross --git https://github.com/cross-rs/cross

使用方法

crossCargo 完全相同的 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会尝试按顺序使用DockerPodman。如果您想显式选择容器引擎,可以使用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.xargotarget.{{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-2.0 许可证的定义,将根据上述方式双许可,不附加任何额外条款或条件。

行为准则

此包的贡献受 Rust 行为准则 的约束,此包的维护者 cross-rs 团队承诺介入以维护该行为准则。

依赖关系

~9–20MB
~289K SLoC