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::into_iter_without_iter,
10 clippy::items_after_statements,
11 clippy::large_enum_variant,
12 clippy::map_clone,
13 clippy::match_bool,
14 clippy::match_on_vec_items,
15 clippy::match_same_arms,
16 clippy::module_name_repetitions,
17 clippy::needless_pass_by_value,
18 clippy::new_without_default,
19 clippy::nonminimal_bool,
20 clippy::or_fun_call,
21 clippy::redundant_else,
22 clippy::shadow_unrelated,
23 clippy::similar_names,
24 clippy::single_match_else,
25 clippy::struct_excessive_bools,
26 clippy::struct_field_names,
27 clippy::too_many_arguments,
28 clippy::too_many_lines,
29 clippy::toplevel_ref_arg
30 )]
31
32 mod app;
33 mod cfg;
34 mod gen;
35 mod output;
36 mod syntax;
37
38 use crate::cfg::{CfgValue, FlagsCfgEvaluator};
39 use crate::gen::error::{report, Result};
40 use crate::gen::fs;
41 use crate::gen::include::{self, Include};
42 use crate::output::Output;
43 use std::collections::{BTreeMap as Map, BTreeSet as Set};
44 use std::io::{self, Write};
45 use std::path::PathBuf;
46 use std::process;
47
48 #[derive(Debug)]
49 struct 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
main()58 fn main() {
59 if let Err(err) = try_main() {
60 let _ = writeln!(io::stderr(), "cxxbridge: {}", report(err));
61 process::exit(1);
62 }
63 }
64
65 enum Kind {
66 GeneratedHeader,
67 GeneratedImplementation,
68 Header,
69 }
70
try_main() -> Result<()>71 fn 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