Rust: no_std application
#![no_std]
is a crate-level attribute that indicates that the crate will
link to the core-crate instead of the std-crate. The libcore crate in turn
is a platform-agnostic subset of the std crate which makes no assumptions
about the system the program will run on. As such, it provides APIs for
language primitives like floats, strings and slices, as well as APIs that
expose processor features like atomic operations and SIMD instructions.
Project
> cargo new shared --lib --vcs none
> cargo new program --bin --vcs none
> touch Cargo.toml .cargo/config.toml
> touch shared/src/_start.s
# Cargo.toml
[workspace]
members = [ "shared" , "launcher" ]
resolver = "2"
[profile.dev]
panic = "abort"
debug = true
incremental = true
lto = false
opt-level = 0
[profile.release]
panic = "abort"
debug = false
incremental = false
lto = true
opt-level = 3
codegen-units = 1
strip = "symbols"
# .config/config.toml
[target.'cfg(target_family="unix")']
rustflags =[
"-Cdefault-linker-libraries=off" ,
"-Clink-arg=-nostdlib"
]
[target.'cfg(target_family="windows")']
rustflags =[
"-Clink-arg=/NODEFAULTLIB" ,
"-Clink-arg=/SUBSYSTEM:WINDOWS" ,
"-Clink-arg=/ENTRY:_start"
]
; shared/src/_start.s
.global _start
.text
_start:
xor rbp , rbp
call start
mov edi , eax
mov eax , 0xe7
syscall
hlt
Shared
# shared/lib.rs
#![no_std]
use core :: arch :: global_asm ;
use core :: panic :: PanicInfo ;
#[cfg(all(target_arch= "x86_64" , target_os= "linux" ))]
global_asm! ( include_str! ( "_start.s" ));
#[panic_handler]
fn panic ( _ panic_info : & PanicInfo ) -> ! {
loop {}
}
#[no_mangle]
pub extern "C" fn start () -> i32 {
0
}
pub fn foo () -> i32 {
256
}
Program
# program/Cargo.toml
[dependencies]
shared = { path = "../shared" }
# program/main.rs
#![no_std]
#![no_main]
use shared ;
#[no_mangle]
extern fn main () -> i32 {
shared :: foo ()
}
Build
> cargo build
Compiling shared v0.1.0 (/media/dev/project/shared)
Compiling launcher v0.1.0 (/media/dev/project/program)
Finished dev [unoptimized + debuginfo] target(s) in 0.11s