aboutsummaryrefslogtreecommitdiff
path: root/build.rs
blob: ff8ed737c4ea3780034bf7f277f71878eb4dade3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/// 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();
}