/// Generate rust constants for linux riscv syscall numbers. /// /// Syscall numbers are parsed from the `linux/unistd.h` header. /// This script uses the `riscv64-linux-gnu-*` tools to find to header, make sure those tools are /// in the PATH. /// /// For simplicity, this script unwraps any Option/Result because we want to fail in case of any /// error. fn main() { // Get sysroot to find header location. let out = std::process::Command::new("riscv64-linux-gnu-gcc") .arg("-print-sysroot") .output() .unwrap(); let sysroot = std::str::from_utf8(&out.stdout).unwrap(); let header = format!("{}/include/linux/unistd.h", sysroot.trim_end()); // The header should "basically" never change. println!("cargo:rerun-if-changed={}", header); // Run header through preprocessor and dump macro definitions. let out = std::process::Command::new("riscv64-linux-gnu-cpp") .arg("-dM") .arg(header) .output() .unwrap(); let defines = std::str::from_utf8(&out.stdout).unwrap(); let mut output = String::with_capacity(256); // Parse out lines of the format // #define __NR_<syscall> <nr> // and generate output strings. for line in defines.lines() { let line = match line.strip_prefix("#define __NR_") { Some(line) => line, None => continue, }; let (sys, nr) = match line.split_once(' ') { Some(split) => split, None => continue, }; let nr = match nr.parse::<usize>() { Ok(nr) => nr, Err(_) => continue, }; output.push_str(&format!( "#[allow(unused)] const SYS_{}: usize = {};\n", sys.to_uppercase(), nr )); } // Write out rust file with syscall numbers. let outfile = format!("{}/syscalls.rs", std::env::var("OUT_DIR").unwrap()); std::fs::write(outfile, output).unwrap(); }