std 之下
本节介绍通常由 std crate 提供、且 #![no_std] 开发者在构建 #![no_std] 二进制 crate 时必须处理(即提供)的特性。
使用 libc
为了构建一个 #[no_std] 可执行文件,我们需要将 libc 作为依赖项。我们可以使用 Cargo.toml 文件来指定它。
[dependencies]
libc = { version = "0.2.146", default-features = false }
请注意,默认特性已被禁用。这是关键的一步——libc 的默认特性包含 std crate,因此必须被禁用。
此外,我们可以使用不稳定的 rustc_private 私有特性以及 extern crate libc; 声明,如下面的示例所示。请注意,windows-msvc 目标不需要 libc,因此在其 sysroot 中没有 libc crate。我们不需要下面的 extern crate libc;,并且将其用于 windows-msvc 目标将导致编译错误。
编写不依赖 std 的可执行文件
我们可能需要一个 nightly 版本的编译器来生成 #![no_std] 可执行文件,因为在许多平台上,我们必须提供 eh_personality 语言项(lang item),它是非稳定的。
您需要为适合您目标的入口点定义一个符号。例如,main、_start、WinMain,或适合您目标的任何起始点。此外,您需要使用 #![no_main] 属性来阻止编译器自身尝试生成入口点。
此外,还需要定义一个 恐慌处理函数(panic handler function)。
#![feature(lang_items, core_intrinsics, rustc_private)] #![allow(internal_features)] #![no_std] #![no_main] // Necessary for `panic = "unwind"` builds on cfg(unix) platforms. #![feature(panic_unwind)] extern crate unwind; // Pull in the system libc library for what crt0.o likely requires. #[cfg(not(windows))] extern crate libc; use core::ffi::{c_char, c_int}; use core::panic::PanicInfo; // Entry point for this program. #[unsafe(no_mangle)] // ensure that this symbol is included in the output as `main` extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int { 0 } // These functions are used by the compiler, but not for an empty program like this. // They are normally provided by `std`. #[lang = "eh_personality"] fn rust_eh_personality() {} #[panic_handler] fn panic_handler(_info: &PanicInfo) -> ! { core::intrinsics::abort() }
如果您正在使用的目标没有通过 rustup 提供标准库的二进制版本(这可能意味着您正在自己构建 core crate),并且需要 compiler-rt 内置函数(这意味着您在构建可执行文件时可能会遇到链接错误:undefined reference to `__aeabi_memcpy'),您需要手动链接到 compiler_builtins crate 来获取这些内置函数并解决链接错误。