将裸机 ARM 的 Rust 代码正确编译为静态库和 x86_64 的二进制文件?
Compile Rust Code properly for bare-metal ARM as static lib and as binary for x86_64?
我想做的事情:
我有一段 Rustcode,我想构建
- 作为裸机 ARM 的静态库,因此它可以链接到现有的 c 程序,并且
- 作为 x86_64 的可执行文件,所以我可以进行开发、单元测试等
我可以两者都做,但不幸的是我每次都必须更改 Cargo.toml。
main.rs
use foobar::foo::Bar;
fn main() {
let bar = Bar::new();
let ret = bar.do_something();
// ...
}
lib.rs
#![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() }
}
#[cfg(not(feature = "EMBEDDED"))]
pub mod foo;
foo.rs
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(test)]
mod test {
use super::*;
#[test]
fn foo_test() {
let bar = Bar::new();
let ret = bar.do_something();
assert_eq!(ret, 42);
}
}
Cargo.toml
[package]
name = "foobar"
version = "0.1.0"
authors = ["..."]
edition = "2018"
[dependencies]
#[[bin]]
#name = "foobar"
#path = "src/main.rs"
#test = true
#bench = false
[lib]
name = "foobar"
path = "src/lib.rs"
crate-type = ["staticlib"] # Creates static lib
#crate-type = ["cdylib"] # Creates synamic lib
[features]
default = []
EMBEDDED = []
有了这个 Cargo.toml,我可以通过 运行ning cargo
将代码构建为静态库
cargo build --lib --release --features EMBEDDED --target thumbv7em-none-eabihf
但是当我尝试使用
为 x86_64 构建代码时
cargo test --target x86_64-unknown-linux-gnu
我收到这个错误:
error[E0433]: failed to resolve: use of undeclared type or module `foobar`
--> src/main.rs:1:5
|
1 | use foobar::foo::Bar;
| ^^^^^^ use of undeclared type or module `foobar`
error[E0433]: failed to resolve: use of undeclared type or module `Bar`
--> src/main.rs:4:15
|
4 | let bar = Bar::new();
| ^^^ use of undeclared type or module `Bar`
error: aborting due to 2 previous errors
启用两个部分 ([[bin]] + [lib]) 时出现相同的错误。
所以,当我现在将 Cargo.toml 更改为
[[bin]]
name = "foobar"
path = "src/main.rs"
test = true
bench = false
#[lib]
#name = "foobar"
#path = "src/lib.rs"
#crate-type = ["staticlib"] # Creates static lib
##crate-type = ["cdylib"] # Creates synamic lib
我可以构建 运行 代码
cargo test --target x86_64-unknown-linux-gnu
但是如果运行现在
cargo build --lib --release --features EMBEDDED --target thumbv7em-none-eabihf
我得到一个 .rlib,这很明显,因为该部分已被注释掉。
所以,我现在的问题是:
我怎样才能做到这两件事,而不是每次都改变 Cargo.toml ?我还没有找到合适的方法。
此致
--manifest-path PATH
Path to the Cargo.toml file. By default, Cargo searches for the Cargo.toml file in the current directory or any parent directory.
只要有两个Cargo.toml
文件,用--manifest-path
指定manifest文件即可。还对两个构建使用不同的 --target-dir
,以同时构建两者。
我想做的事情: 我有一段 Rustcode,我想构建
- 作为裸机 ARM 的静态库,因此它可以链接到现有的 c 程序,并且
- 作为 x86_64 的可执行文件,所以我可以进行开发、单元测试等
我可以两者都做,但不幸的是我每次都必须更改 Cargo.toml。
main.rs
use foobar::foo::Bar;
fn main() {
let bar = Bar::new();
let ret = bar.do_something();
// ...
}
lib.rs
#![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() }
}
#[cfg(not(feature = "EMBEDDED"))]
pub mod foo;
foo.rs
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(test)]
mod test {
use super::*;
#[test]
fn foo_test() {
let bar = Bar::new();
let ret = bar.do_something();
assert_eq!(ret, 42);
}
}
Cargo.toml
[package]
name = "foobar"
version = "0.1.0"
authors = ["..."]
edition = "2018"
[dependencies]
#[[bin]]
#name = "foobar"
#path = "src/main.rs"
#test = true
#bench = false
[lib]
name = "foobar"
path = "src/lib.rs"
crate-type = ["staticlib"] # Creates static lib
#crate-type = ["cdylib"] # Creates synamic lib
[features]
default = []
EMBEDDED = []
有了这个 Cargo.toml,我可以通过 运行ning cargo
将代码构建为静态库cargo build --lib --release --features EMBEDDED --target thumbv7em-none-eabihf
但是当我尝试使用
为 x86_64 构建代码时cargo test --target x86_64-unknown-linux-gnu
我收到这个错误:
error[E0433]: failed to resolve: use of undeclared type or module `foobar`
--> src/main.rs:1:5
|
1 | use foobar::foo::Bar;
| ^^^^^^ use of undeclared type or module `foobar`
error[E0433]: failed to resolve: use of undeclared type or module `Bar`
--> src/main.rs:4:15
|
4 | let bar = Bar::new();
| ^^^ use of undeclared type or module `Bar`
error: aborting due to 2 previous errors
启用两个部分 ([[bin]] + [lib]) 时出现相同的错误。
所以,当我现在将 Cargo.toml 更改为
[[bin]]
name = "foobar"
path = "src/main.rs"
test = true
bench = false
#[lib]
#name = "foobar"
#path = "src/lib.rs"
#crate-type = ["staticlib"] # Creates static lib
##crate-type = ["cdylib"] # Creates synamic lib
我可以构建 运行 代码
cargo test --target x86_64-unknown-linux-gnu
但是如果运行现在
cargo build --lib --release --features EMBEDDED --target thumbv7em-none-eabihf
我得到一个 .rlib,这很明显,因为该部分已被注释掉。
所以,我现在的问题是: 我怎样才能做到这两件事,而不是每次都改变 Cargo.toml ?我还没有找到合适的方法。
此致
--manifest-path PATH
Path to the Cargo.toml file. By default, Cargo searches for the Cargo.toml file in the current directory or any parent directory.
只要有两个Cargo.toml
文件,用--manifest-path
指定manifest文件即可。还对两个构建使用不同的 --target-dir
,以同时构建两者。