File: build.rs

package info (click to toggle)
rust-gbm-sys 0.4.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 144 kB
  • sloc: ansic: 238; makefile: 4
file content (104 lines) | stat: -rw-r--r-- 3,025 bytes parent folder | download
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
extern crate bindgen;

fn main() {
    use std::{env, path::Path};

    const TMP_BIND_PREFIX: &str = "__BINDGEN_TMP_";
    const TMP_BIND_PREFIX_REG: &str = "_BINDGEN_TMP_.*";

    const INCLUDES: &[&str] = &["gbm.h"];

    const MACROS: &[&str] = &[
        "GBM_BO_IMPORT_WL_BUFFER",
        "GBM_BO_IMPORT_EGL_IMAGE",
        "GBM_BO_IMPORT_FD",
        "GBM_BO_IMPORT_FD_MODIFIER",
    ];

    // Applies a formatting function over a slice of strings,
    // concatenating them on separate lines into a single String
    fn apply_formatting<I, F>(iter: I, f: F) -> String
    where
        I: Iterator,
        I::Item: AsRef<str>,
        F: Fn(&str) -> String,
    {
        iter.fold(String::new(), |acc, x| acc + &f(x.as_ref()) + "\n")
    }

    // Create a name for a temporary value
    fn tmp_val(name: &str) -> String {
        format!("{}{}", TMP_BIND_PREFIX, name)
    }

    // Create a C include directive
    fn include(header: &str) -> String {
        format!("#include <{}>", header)
    }

    // Create a C constant
    fn decl_const(ty: &str, name: &str, value: &str) -> String {
        format!("const {} {} = {};", ty, name, value)
    }

    // Create a C macro definition
    fn define_macro(name: &str, val: &str) -> String {
        format!("#define {} {}", name, val)
    }

    // Create a C undefinition
    fn undefine_macro(name: &str) -> String {
        format!("#undef {}", name)
    }

    // Rebind a C macro as a constant
    // Required for some macros that won't get generated
    fn rebind_macro(name: &str) -> String {
        let tmp_name = tmp_val(name);
        format!(
            "{}\n{}\n{}\n{}",
            decl_const("unsigned int", &tmp_name, name),
            undefine_macro(name),
            decl_const("unsigned int", name, &tmp_name),
            define_macro(name, name)
        )
    }

    // Fully create the header
    fn create_header() -> String {
        apply_formatting(INCLUDES.iter(), include) + &apply_formatting(MACROS.iter(), rebind_macro)
    }

    // Setup bindings builder
    let generated = bindgen::builder()
        .clang_arg("-Iinclude")
        .header_contents("bindings.h", &create_header())
        .blocklist_type(TMP_BIND_PREFIX_REG)
        .ctypes_prefix("libc")
        .allowlist_type("^gbm_.*$")
        .allowlist_function("^gbm_.*$")
        .allowlist_var("GBM_.*|gbm_.*")
        .constified_enum_module("^gbm_.*$")
        // Layout tests are incorrect across architectures
        .layout_tests(false)
        .generate()
        .unwrap();

    println!("cargo:rerun-if-changed=include/gbm.h");

    // Generate the bindings
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("bindings.rs");

    generated.write_to_file(dest_path).unwrap();

    #[cfg(feature = "update_bindings")]
    {
        use std::fs;

        let bind_file = Path::new(&out_dir).join("bindings.rs");
        let dest_file = "src/bindings.rs";

        fs::copy(bind_file, dest_file).unwrap();
    }
}