aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
blob: f3398db890503697d665a514365138e6ad547301 (plain)
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
105
106
107
108
109
110
111
112
113
extern crate bindgen;
#[cfg(feature = "logging")]
extern crate env_logger;
#[macro_use]
#[cfg(feature = "logging")]
extern crate log;
extern crate clap;

use bindgen::clang_version;
use std::env;
use std::panic;

#[macro_use]
#[cfg(not(feature = "logging"))]
mod log_stubs;

mod options;
use crate::options::builder_from_flags;

fn clang_version_check() {
    let version = clang_version();
    let expected_version = if cfg!(feature = "testing_only_libclang_9") {
        Some((9, 0))
    } else if cfg!(feature = "testing_only_libclang_5") {
        Some((5, 0))
    } else if cfg!(feature = "testing_only_libclang_4") {
        Some((4, 0))
    } else if cfg!(feature = "testing_only_libclang_3_9") {
        Some((3, 9))
    } else {
        None
    };

    info!(
        "Clang Version: {}, parsed: {:?}",
        version.full, version.parsed
    );

    if expected_version.is_some() {
        // assert_eq!(version.parsed, version.parsed);
    }
}

pub fn main() {
    #[cfg(feature = "logging")]
    env_logger::init();

    match builder_from_flags(env::args()) {
        Ok((builder, output, verbose)) => {
            clang_version_check();
            let builder_result = panic::catch_unwind(|| {
                builder.generate().expect("Unable to generate bindings")
            });

            if builder_result.is_err() {
                if verbose {
                    print_verbose_err();
                }
                std::process::exit(1);
            }

            let bindings = builder_result.unwrap();
            bindings.write(output).expect("Unable to write output");
        }
        Err(error) => {
            println!("{}", error);
            std::process::exit(1);
        }
    };
}

fn print_verbose_err() {
    println!("Bindgen unexpectedly panicked");
    println!(
        "This may be caused by one of the known-unsupported \
         things (https://rust-lang.github.io/rust-bindgen/cpp.html), \
         please modify the bindgen flags to work around it as \
         described in https://rust-lang.github.io/rust-bindgen/cpp.html"
    );
    println!(
        "Otherwise, please file an issue at \
         https://github.com/rust-lang/rust-bindgen/issues/new"
    );
}

#[cfg(test)]
mod test {
    fn build_flags_output_helper(builder: &bindgen::Builder) {
        let mut command_line_flags = builder.command_line_flags();
        command_line_flags.insert(0, "bindgen".to_string());

        let flags_quoted: Vec<String> = command_line_flags
            .iter()
            .map(|x| format!("{}", shlex::quote(x)))
            .collect();
        let flags_str = flags_quoted.join(" ");
        println!("{}", flags_str);

        let (builder, _output, _verbose) =
            crate::options::builder_from_flags(command_line_flags.into_iter())
                .unwrap();
        builder.generate().expect("failed to generate bindings");
    }

    #[test]
    fn commandline_multiple_headers() {
        let bindings = bindgen::Builder::default()
            .header("tests/headers/char.h")
            .header("tests/headers/func_ptr.h")
            .header("tests/headers/16-byte-alignment.h");
        build_flags_output_helper(&bindings);
    }
}