Include Assembler Source Files In Rust Project (and Build with Cargo)
Recently I stumbled upon a Rust project, where
*.rs-files were side by side in the same Cargo src-directory and I was like: “What the heck, I always wanted this!” This was a pure and lucky coincidence, really. If you programmed in C/++ before, you probably know this. The
gcc (or to be more specific, the linker) can consume object files generated from
*.S files, where the latter means files written in GAS (GNU Assembler).
When writing firmware or operating systems, it’s important to be able to do this. For example you can construct an aligned
multiboot2-header using assembly or initialize the stack and other things before you jump into the code of a higher level language like C or Rust. Whole function definitions also must live in the “global_asm”-space, because inline assembly in Rust is not capable of doing this.
The trick to achieve this in Rust is the experimental and poorly (or better to say, not all at) documented
global_asm-feature. It allows you to include assembly as it was in a separate file and compiled along. There is no documentation at all, but due to my findings, it consumes only GAS (GNU Assembler), which requires
gcc on your system. Perhaps it uses the default assembly syntax flavor + compiler on Windows, I didn’t tested this.
// works definitely with rustc 1.55-nightly // Add this in your main.rs or lib.rs #![feature(global_asm)] // include_str! copies the file content (written in GNU assembly) // file path starts relative in "src/" directory global_asm!(include_str!("gnu_asm.S"));
This is the complete trick. This means that
cargo build will also take care of the assembly files. Furthermore, cargo notices if one of these files changed and recompile the necessary parts. I didn’t trace the internal process but I guess it creates a separate object file and links it together with the object files from the files written in Rust.