43 个发布版本
使用旧的 Rust 2015
0.3.26 | 2022年6月1日 |
---|---|
0.3.25 | 2022年3月26日 |
0.3.24 | 2021年9月22日 |
0.3.23 | 2021年5月8日 |
0.1.3 | 2016年4月25日 |
171 在 开发工具 中排名
每月 1,333 次下载
245KB
1.5K SLoC
注意:Xargo 正处于维护模式
xargo
系统根管理器,让您构建和自定义
std
为 i686-unknown-linux-gnu 编译 `std`
Xargo 构建和管理 "系统根"(参看 rustc --print sysroot
)。这使得为没有标准库二进制发布的目标(例如 thumbv*m-none-eabi*
目标)交叉编译 Rust 库变得容易。它还允许您为目标构建定制的 std
库,例如使用 -C panic=abort
编译。
依赖项
-
您可以使用
rustup component add rust-src
安装的rust-src
组件。 -
Rust 和 Cargo。
安装
$ cargo install xargo
使用方法
no_std
xargo
与 cargo
完全相同的 CLI。
# This Just Works
$ xargo build --target thumbv6m-none-eabi
Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)
Finished release [optimized] target(s) in 11.61 secs
Compiling lib v0.1.0 (file://$PWD)
Finished debug [unoptimized + debuginfo] target(s) in 0.5 secs
xargo
会缓存系统根,在本例中为 core
库,因此下一个 build
命令将非常快。
$ xargo build --target thumbv6m-none-eabi
Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
默认情况下,xargo
只会为目标编译 core
包。如果您需要更大的标准包子集,请在 Cargo 项目的根目录下(紧挨着 Cargo.toml
)的 Xargo.toml
文件中指定依赖项。
$ cat Xargo.toml
# Alternatively you can use [build.dependencies]
# the syntax is the same as Cargo.toml's; you don't need to specify path or git
[target.thumbv6m-none-eabi.dependencies]
collections = {}
$ xargo build --target thumbv6m-none-eabi
Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)
Compiling alloc v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/liballoc)
Compiling std_unicode v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libstd_unicode)
Compiling collections v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcollections)
Finished release [optimized] target(s) in 15.26 secs
Compiling lib v0.1.0 (file://$PWD)
Finished debug [unoptimized + debuginfo] target(s) in 0.5 secs
std
您还可以编译自定义的 std
包,只需指定要启用的 Cargo 功能即可。
# Build `std` with `-C panic=abort` (default) and with jemalloc as the default
# allocator
$ cat Xargo.toml
[target.i686-unknown-linux-gnu.dependencies.std]
features = ["jemalloc"]
# Needed to compile `std` with `-C panic=abort`
$ tail -n2 Cargo.toml
[profile.release]
panic = "abort"
$ xargo run --target i686-unknown-linux-gnu --release
Updating registry `https://github.com/rust-lang/crates.io-index`
Compiling libc v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/rustc/libc_shim)
Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)
Compiling build_helper v0.1.0 (file://$SYSROOT/lib/rustlib/src/rust/src/build_helper)
Compiling gcc v0.3.41
Compiling unwind v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libunwind)
Compiling std v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libstd)
Compiling compiler_builtins v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcompiler_builtins)
Compiling alloc_jemalloc v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/liballoc_jemalloc)
Compiling alloc v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/liballoc)
Compiling rand v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/librand)
Compiling std_unicode v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libstd_unicode)
Compiling alloc_system v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/liballoc_system)
Compiling panic_abort v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libpanic_abort)
Compiling collections v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcollections)
Finished release [optimized] target(s) in 33.49 secs
Compiling hello v0.1.0 (file://$PWD)
Finished release [optimized] target(s) in 0.28 secs
Running `target/i686-unknown-linux-gnu/release/hello`
Hello, world!
如果您想了解 xargo
在底层做了什么,请向其传递详细的 -v
标志。
$ xargo build --target thumbv6m-none-eabi -v
+ "rustc" "--print" "target-list"
+ "rustc" "--print" "sysroot"
+ "cargo" "build" "--release" "--manifest-path" "/tmp/xargo.lTBXKnaUGicV/Cargo.toml" "--target" "thumbv6m-none-eabi" "-v" "-p" "core"
Compiling core v0.0.0 (file://$SYSROOT/lib/rustlib/src/rust/src/libcore)
Running `rustc --crate-name core $SYSROOT/lib/rustlib/src/rust/src/libcore/lib.rs --crate-type lib -C opt-level=3 -C metadata=a5c596f87f7d486b -C extra-filename=-a5c596f87f7d486b --out-dir /tmp/xargo.lTBXKnaUGicV/target/thumbv6m-none-eabi/release/deps --emit=dep-info,link --target thumbv6m-none-eabi -L dependency=/tmp/xargo.lTBXKnaUGicV/target/thumbv6m-none-eabi/release/deps -L dependency=/tmp/xargo.lTBXKnaUGicV/target/release/deps`
Finished release [optimized] target(s) in 11.50 secs
+ "cargo" "build" "--target" "thumbv6m-none-eabi" "-v"
Compiling lib v0.1.0 (file://$PWD)
Running `rustc --crate-name lib src/lib.rs --crate-type lib -g -C metadata=461fd0b398821543 -C extra-filename=-461fd0b398821543 --out-dir $PWD/target/thumbv6m-none-eabi/debug/deps --emit=dep-info,link --target thumbv6m-none-eabi -L dependency=$PWD/target/thumbv6m-none-eabi/debug/deps -L dependency=$PWD/lib/target/debug/deps --sysroot $HOME/.xargo`
Finished debug [unoptimized + debuginfo] target(s) in 0.5 secs
开发渠道
哦,如果您想使用 xargo
通过 "开发" rustc
编译 std
,即从源代码编译的 rust,您可以使用 XARGO_RUST_SRC
环境变量来告诉 xargo
Rust 源代码的位置。
# `$XARGO_RUST_SRC` must point to the `library` subfolder of a Rust checkout.
$ export XARGO_RUST_SRC=/path/to/rust/library
$ xargo build --target msp430-none-elf
注意 这也适用于夜间渠道,但不建议使用,因为 Rust 源代码可能与编译器能够编译的内容不同,因为它可能使用了编译器不理解的较新功能。
使用自定义 rustc 标志编译 sysroot
Xargo 使用适用于目标 Cargo 项目的相同自定义 rustc 标志。因此,您可以使用 RUSTFLAGS
环境变量或 .cargo/config
配置文件来指定自定义 rustc 标志。
# build the sysroot with debug information
$ RUSTFLAGS='-g' xargo build --target x86_64-unknown-linux-gnu
# Alternatively
$ edit .cargo/config && cat $_
[build]
rustflags = ["-g"]
# Then you can omit RUSTFLAGS
$ xargo build --target x86_64-unknown-linux-gnu
为自定义目标编译 sysroot
在某个时候,您可能想为 rustc 官方不支持的目标开发程序。Xargo 会支持您!它通过目标规范文件支持自定义目标,这些文件在其他地方没有文档记录,只有编译器的源代码中才有记录。幸运的是,您不必从头开始编写规范文件;您可以从现有的一个开始。
例如,假设您想为使用 uclibc 而不是 glibc 的 PowerPC Linux 系统交叉编译程序。在编译器支持的列表中有类似的目标 -- 查看 rustc --print target-list
-- 那是 powerpc-unknown-linux-gnu
。因此,您可以首先将此目标的规范输出到文件中
$ rustc -Z unstable-options --print target-spec-json --target powerpc-unknown-linux-gnu | tee powerpc-unknown-linux-uclibc.json
{
"arch": "powerpc",
"data-layout": "E-m:e-p:32:32-i64:64-n32",
"dynamic-linking": true,
"env": "gnu",
"executables": true,
"has-elf-tls": true,
"has-rpath": true,
"is-builtin": true,
"linker-flavor": "gcc",
"linker-is-gnu": true,
"llvm-target": "powerpc-unknown-linux-gnu",
"max-atomic-width": 32,
"os": "linux",
"position-independent-executables": true,
"pre-link-args": {
"gcc": [
"-Wl,--as-needed",
"-Wl,-z,noexecstack",
"-m32"
]
},
"target-endian": "big",
"target-family": "unix",
"target-pointer-width": "32",
"vendor": "unknown"
}
您肯定会想删除 is-builtin
字段,因为该字段是为在编译器中定义的目标保留的。除此之外,您在此情况下唯一需要修改的是将 env
字段从 gnu
(glibc)更改为 uclibc
。
"arch": "powerpc",
"data-layout": "E-m:e-p:32:32-i64:64-n32",
"dynamic-linking": true,
- "env": "gnu",
+ "env": "uclibc",
"executables": true,
"has-elf-tls": true,
"has-rpath": true,
- "is-builtin": true,
"linker-flavor": "gcc",
"linker-is-gnu": true,
"llvm-target": "powerpc-unknown-linux-gnu",
一旦您有了目标规范文件,您只需调用 Xargo 并指定正确的目标三元组;确保规范文件与您调用 Xargo 的同一文件夹相同,因为 rustc 期望它在那里。
$ ls powerpc-unknown-linux-uclibc.json
powerpc-unknown-linux-uclibc.json
$ xargo build --target powerpc-unknown-linux-uclibc
您的构建可能会失败,因为如果 rustc 不支持您的目标,那么标准库可能也不支持它。在这种情况下,您将必须修改标准库的源代码。Xargo 也会帮助您做这件事,因为您可以复制原始源代码 -- 查看 rustc --print sysroot
,修改它,然后使用 XARGO_RUST_SRC
环境变量将其指向 Xargo。
多阶段构建
一些标准crate之间存在隐式依赖关系。例如,test
crate隐式依赖于std
。这里的“隐式”意味着test crate的Cargo.toml文件中没有将其列为依赖项。[查看更多](https://github.com/rust-lang/rust/blob/1.17.0/src/libtest/Cargo.toml) 。为了编译包含此类crate的sysroot,您可以通过在Xargo.toml文件中指定每个阶段属于哪些crate,分阶段执行构建。
[dependencies.std]
stage = 0
[dependencies.test]
stage = 1
这将编译一个中间sysroot,阶段0 sysroot,包含std
crate,然后它将使用该中间sysroot编译test
crate。最终的sysroot,阶段1 sysroot,将包含std
和test
crate及其依赖项。
创建包含自定义crate的sysroot
Xargo允许您创建包含自定义crate的sysroot。您可以将任何crate虚拟地放入sysroot中。然而,此功能主要用于创建[替代std
封装][rust-3ds],以及用支持no_std
目标的crate替换test
crate。[查看更多](https://github.com/japaric/utest)。要指定sysroot的内容,只需像处理Cargo.toml一样在Xargo.toml文件中列出依赖项即可。
# First build some standard crates.
[dependencies.alloc]
[dependencies.panic_abort]
[dependencies.panic_unwind]
# Then build our custom facade. It (implicitly) requires the crates above to
# already be in the sysroot, so we need to set the `stage`.
[dependencies.std]
git = "https://github.com/rust3ds/ctru-rs"
stage = 1
修补sysroot crate
Xargo还支持Cargo的patch
功能。这允许您在sysroot的依赖树中强制使用自定义crate。这可以特别有用,以强制使用自定义的libc
或compiler_builtins
,而无需对每个传递依赖项进行侵入性更改。
[patch.crates-io.libc]
path = "path/to/custom/libc"
注意,您不应该将修补的crate列为[dependencies]
![dependencies]
决定了首先构建哪些crate;[patch]
允许您用您的选择替换它们的(传递)依赖项。同时将crate列入两个列表可能会导致crate重复。
仅检查sysroot构建
Xargo支持通过xargo-check
命令执行sysroot的“检查构建”。此命令的调用方式与xargo
完全相同,但在构建sysroot时将调用cargo check
而不是cargo build
。
这仅适用于非常专业的应用程序,例如Miri。生成的libstd将不能用于正常构建,因为不会执行代码生成。您几乎总是应该运行xargo check
(注意空格),这将执行正常的sysroot构建,然后执行您的应用程序的“检查”构建。
注意事项/注意事项
-
当与稳定或beta Rust一起使用时,Xargo不会构建sysroot。这是因为
std
和其他标准crate依赖于不稳定的功能,因此无法使用稳定或beta构建sysroot。 -
std
被构建为rlib 和 dylib。dylib需要一个panic库和一个分配器。如果您没有指定panic-unwind
功能,您必须在Cargo.toml
中将panic = "abort"
设置。 -
要在构建时禁用
jemalloc
功能,请在Xargo.toml
中包含以下内容:[dependencies.std] features = ["force_alloc_system"]
此标志的含义是,使用此libstd编译的每个程序只能使用系统分配器。如果您的程序尝试设置自己的分配器,则编译会失败,因为现在有两个分配器被设置(一个由libstd设置,一个由您的程序设置)。有关此问题的更多信息,请参阅rust-lang/rust#43637。
-
建议始终使用
--target
选项来使用xargo
。这是因为即使编译宿主平台时也必须提供此选项,因为Cargo处理编译器插件(例如serde_derive
)和构建脚本(例如build.rs
)的方式。这也适用于所有使用编译器插件或构建脚本的依赖项包的编译。您可以使用以下命令确定宿主机的目标三元组:rustc -vV
。在*nix上,以下命令将提取三元组:rustc -vV | egrep '^host: ' | sed 's/^host: //'
。 -
请注意,
core
和std
将被隐式链接到您的crate,但其他所有sysroot crate则不会被链接。这意味着如果您的Xargo.toml包含像alloc
这样的crate,那么您必须在依赖图中的某个位置添加一个extern crate alloc
(要么在您的当前crate中,要么在其依赖项中)。 -
请注意,rustc将始终隐式链接
compiler_builtins
到您的最终二进制文件,但不会像core
和std
那样使其可用。因此,如果您需要手动调用compiler_builtins
函数,您仍然需要在您的crate中手动添加一个extern crate compiler_builtins
。 -
必须注意,不要在sysroot中有任何“顶级”crate(
core
、std
、compiler-builtins
)重复两次。这样做会导致Cargo在构建时出错,错误信息如下:multiple matching crates for core
。sysroot中的重复crate通常发生在多阶段构建过程中,同一个crate以不同的功能构建两次时。
许可证
根据您的选择,许可如下:
- Apache License,版本2.0(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT 或 http://opensource.org/licenses/MIT)
。
贡献
除非您明确声明,否则您提交给工作内容的任何贡献,根据Apache-2.0许可证的定义,应按上述方式双许可,不附加任何额外的条款或条件。
依赖项
~1–10MB
~85K SLoC