You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需修改Cargo.toml同时构建ARM裸机静态库与x86_64可执行程序?

我来帮你解决这个问题!核心思路是同时保留[lib]和[[bin]]配置,并通过调整条件编译逻辑和构建命令,彻底避免每次修改Cargo.toml的麻烦。下面是具体的实现步骤:

1. 修正Cargo.toml配置

让库默认以rlib类型构建(方便Rust内部引用,用于测试和二进制目标),构建嵌入式静态库时通过命令行临时覆盖crate-type。完整配置如下:

[package]
name = "foobar"
version = "0.1.0"
authors = ["..."]
edition = "2018"

# 保留二进制目标,用于开发调试和测试
[[bin]]
name = "foobar"
path = "src/main.rs"
test = true
bench = false

# 库目标默认用rlib,确保Rust代码能正常引用
[lib]
name = "foobar"
path = "src/lib.rs"
crate-type = ["rlib"]

[features]
default = []
EMBEDDED = []

2. 调整lib.rs的条件编译逻辑

之前的代码在启用EMBEDDED特性时会隐藏foo模块,导致二进制目标找不到引用。我们修改为始终导出foo模块,仅在EMBEDDED特性下启用no_std和 panic 处理:

#![feature(core_intrinsics)]
#![cfg_attr(feature = "EMBEDDED", no_std)]

#[cfg(feature = "EMBEDDED")]
use core::intrinsics;
#[cfg(feature = "EMBEDDED")]
use core::panic::PanicInfo;

#[cfg(feature = "EMBEDDED")]
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    unsafe { intrinsics::abort() }
}

// 始终导出foo模块,确保二进制目标和测试能正常访问
pub mod foo;

3. (可选)优化foo.rs的测试代码

给测试代码加上#[cfg(not(feature = "EMBEDDED"))],避免在no_std环境下编译测试(因为测试依赖std库):

pub struct Bar;

impl Bar {
    pub fn new() -> Self { Bar{} }
    pub fn do_something(&self) -> u32 { 42 }
}

#[no_mangle]
pub extern "C" fn call_from_c_prog() -> u32 {
    let bar = Bar::new();
    bar.do_something()
}

#[cfg(not(feature = "EMBEDDED"))]
#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn foo_test() {
        let bar = Bar::new();
        let ret = bar.do_something();
        assert_eq!(ret, 42);
    }
}

4. 执行构建和测试命令

现在你完全不需要修改Cargo.toml就能完成两种操作:

开发/单元测试(x86_64)

直接运行以下命令即可构建并测试:

cargo test --target x86_64-unknown-linux-gnu
# 或者直接运行二进制程序
cargo run --target x86_64-unknown-linux-gnu

构建ARM裸机静态库

通过--crate-type staticlib临时覆盖库类型,生成可链接到C程序的静态库:

cargo build --lib --release --features EMBEDDED --target thumbv7em-none-eabihf --crate-type staticlib

生成的静态库文件路径通常为target/thumbv7em-none-eabihf/release/libfoobar.a,可以直接链接到你的C程序中。

方案原理说明

  • 默认用rlib类型构建库,允许同一个包的二进制目标和测试代码正常引用它;
  • 构建嵌入式版本时,通过命令行指定--crate-type staticlib生成适合C链接的静态库,同时启用EMBEDDED特性切换到no_std环境;
  • 调整条件编译逻辑后,不管是否启用EMBEDDED,foo模块都能被访问,彻底解决了之前的引用错误问题。

内容的提问来源于stack exchange,提问作者Kaj G.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:52:41