xref: /third_party/rust/crates/cxx/gen/cmd/src/main.rs (revision 33d722a9)
1#![allow(
2    clippy::cast_sign_loss,
3    clippy::cognitive_complexity,
4    clippy::default_trait_access,
5    clippy::derive_partial_eq_without_eq,
6    clippy::enum_glob_use,
7    clippy::if_same_then_else,
8    clippy::inherent_to_string,
9    clippy::items_after_statements,
10    clippy::large_enum_variant,
11    clippy::match_bool,
12    clippy::match_on_vec_items,
13    clippy::match_same_arms,
14    clippy::module_name_repetitions,
15    clippy::needless_pass_by_value,
16    clippy::new_without_default,
17    clippy::nonminimal_bool,
18    clippy::option_if_let_else,
19    clippy::or_fun_call,
20    clippy::redundant_else,
21    clippy::shadow_unrelated,
22    clippy::similar_names,
23    clippy::single_match_else,
24    clippy::struct_excessive_bools,
25    clippy::too_many_arguments,
26    clippy::too_many_lines,
27    clippy::toplevel_ref_arg,
28    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983
29    clippy::wrong_self_convention
30)]
31
32mod app;
33mod cfg;
34mod gen;
35mod output;
36mod syntax;
37
38use crate::cfg::{CfgValue, FlagsCfgEvaluator};
39use crate::gen::error::{report, Result};
40use crate::gen::fs;
41use crate::gen::include::{self, Include};
42use crate::output::Output;
43use std::collections::{BTreeMap as Map, BTreeSet as Set};
44use std::io::{self, Write};
45use std::path::PathBuf;
46use std::process;
47
48#[derive(Debug)]
49struct Opt {
50    input: Option<PathBuf>,
51    header: bool,
52    cxx_impl_annotations: Option<String>,
53    include: Vec<Include>,
54    outputs: Vec<Output>,
55    cfg: Map<String, Set<CfgValue>>,
56}
57
58fn main() {
59    if let Err(err) = try_main() {
60        let _ = writeln!(io::stderr(), "cxxbridge: {}", report(err));
61        process::exit(1);
62    }
63}
64
65enum Kind {
66    GeneratedHeader,
67    GeneratedImplementation,
68    Header,
69}
70
71fn try_main() -> Result<()> {
72    let opt = app::from_args();
73
74    let mut outputs = Vec::new();
75    let mut gen_header = false;
76    let mut gen_implementation = false;
77    for output in opt.outputs {
78        let kind = if opt.input.is_none() {
79            Kind::Header
80        } else if opt.header
81            || output.ends_with(".h")
82            || output.ends_with(".hh")
83            || output.ends_with(".hpp")
84        {
85            gen_header = true;
86            Kind::GeneratedHeader
87        } else {
88            gen_implementation = true;
89            Kind::GeneratedImplementation
90        };
91        outputs.push((output, kind));
92    }
93
94    let gen = gen::Opt {
95        include: opt.include,
96        cxx_impl_annotations: opt.cxx_impl_annotations,
97        gen_header,
98        gen_implementation,
99        cfg_evaluator: Box::new(FlagsCfgEvaluator::new(opt.cfg)),
100        ..Default::default()
101    };
102
103    let generated_code = if let Some(input) = opt.input {
104        gen::generate_from_path(&input, &gen)
105    } else {
106        Default::default()
107    };
108
109    for (output, kind) in outputs {
110        let content = match kind {
111            Kind::GeneratedHeader => &generated_code.header,
112            Kind::GeneratedImplementation => &generated_code.implementation,
113            Kind::Header => include::HEADER.as_bytes(),
114        };
115        match output {
116            Output::Stdout => drop(io::stdout().write_all(content)),
117            Output::File(path) => fs::write(path, content)?,
118        }
119    }
120
121    Ok(())
122}
123