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