From 6bc13e0b08c637fa381718aefd6a34637beb3b0d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 12 Apr 2021 17:37:55 -0400 Subject: [PATCH] Move top-level crate inside a pub module in prep for multi-crate bindings This wraps the lightning crate inside a `pub mod lightning` wrapper in genbindings.sh, and modifies the binding generator to handle it. It ends up removing some code in the main TypeResolver, at the cost of some extra handling of imports in the ImportResolver, which focuses the amount of code that needs to be aware of the top-level crate name down to a much smaller area. This preps us for creating bindings for multiple crates at once. --- c-bindings-gen/src/main.rs | 58 ++++++++-------- c-bindings-gen/src/types.rs | 135 +++++++++++++++++++++--------------- genbindings.sh | 17 +++-- 3 files changed, 122 insertions(+), 88 deletions(-) diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index f0c5db3..0d002bb 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -58,7 +58,7 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path } match &t as &str { - "util::ser::Writeable" => { + "lightning::util::ser::Writeable" => { writeln!(w, "#[no_mangle]").unwrap(); writeln!(w, "/// Serialize the {} object into a byte array which can be read by {}_read", for_obj, for_obj).unwrap(); writeln!(w, "pub extern \"C\" fn {}_write(obj: &{}) -> crate::c_types::derived::CVec_u8Z {{", for_obj, full_obj_path).unwrap(); @@ -82,7 +82,7 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path writeln!(w, "}}").unwrap(); } }, - "util::ser::Readable"|"util::ser::ReadableArgs" => { + "lightning::util::ser::Readable"|"lightning::util::ser::ReadableArgs" => { // Create the Result syn::Type let mut err_segs = syn::punctuated::Punctuated::new(); err_segs.push(syn::PathSegment { ident: syn::Ident::new("ln", Span::call_site()), arguments: syn::PathArguments::None }); @@ -110,7 +110,7 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path write!(w, "pub extern \"C\" fn {}_read(ser: crate::c_types::u8slice", for_obj).unwrap(); let mut arg_conv = Vec::new(); - if t == "util::ser::ReadableArgs" { + if t == "lightning::util::ser::ReadableArgs" { write!(w, ", arg: ").unwrap(); assert!(trait_path.leading_colon.is_none()); let args_seg = trait_path.segments.iter().last().unwrap(); @@ -133,7 +133,7 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path types.write_c_type(w, &res_ty, Some(generics), false); writeln!(w, " {{").unwrap(); - if t == "util::ser::ReadableArgs" { + if t == "lightning::util::ser::ReadableArgs" { w.write(&arg_conv).unwrap(); write!(w, ";\n\tlet res: ").unwrap(); // At least in one case we need type annotations here, so provide them. @@ -162,7 +162,7 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path /// single function (eg for serialization). fn convert_trait_impl_field(trait_path: &str) -> (&'static str, String, &'static str) { match trait_path { - "util::ser::Writeable" => ("Serialize the object into a byte array", "write".to_owned(), "crate::c_types::derived::CVec_u8Z"), + "lightning::util::ser::Writeable" => ("Serialize the object into a byte array", "write".to_owned(), "crate::c_types::derived::CVec_u8Z"), _ => unimplemented!(), } } @@ -171,7 +171,7 @@ fn convert_trait_impl_field(trait_path: &str) -> (&'static str, String, &'static /// `for_obj` which implements the the trait at `trait_path`. fn write_trait_impl_field_assign(w: &mut W, trait_path: &str, for_obj: &syn::Ident) { match trait_path { - "util::ser::Writeable" => { + "lightning::util::ser::Writeable" => { writeln!(w, "\t\twrite: {}_write_void,", for_obj).unwrap(); }, _ => unimplemented!(), @@ -182,8 +182,8 @@ fn write_trait_impl_field_assign(w: &mut W, trait_path: &str, fn do_write_impl_trait(w: &mut W, trait_path: &str, _trait_name: &syn::Ident, for_obj: &str) { eprintln!("{}", trait_path); match trait_path { - "util::ser::Writeable" => { - writeln!(w, "impl lightning::{} for {} {{", trait_path, for_obj).unwrap(); + "lightning::util::ser::Writeable" => { + writeln!(w, "impl {} for {} {{", trait_path, for_obj).unwrap(); writeln!(w, "\tfn write(&self, w: &mut W) -> Result<(), ::std::io::Error> {{").unwrap(); writeln!(w, "\t\tlet vec = (self.write)(self.this_arg);").unwrap(); writeln!(w, "\t\tw.write_all(vec.as_slice())").unwrap(); @@ -503,9 +503,10 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty let mut module_iter = s.rsplitn(2, "::"); module_iter.next().unwrap(); let supertrait_module = module_iter.next().unwrap(); - let imports = ImportResolver::new(supertrait_module, &types.crate_types.lib_ast.modules.get(supertrait_module).unwrap().items); - let resolver = TypeResolver::new("lightning", &supertrait_module, imports, types.crate_types); // TODO: Drop hard-coded crate name here - writeln!(w, "impl lightning::{} for {} {{", s, trait_name).unwrap(); // TODO: Drop hard-coded crate name here + let imports = ImportResolver::new(supertrait_module.splitn(2, "::").next().unwrap(), &types.crate_types.lib_ast.dependencies, + supertrait_module, &types.crate_types.lib_ast.modules.get(supertrait_module).unwrap().items); + let resolver = TypeResolver::new(&supertrait_module, imports, types.crate_types); + writeln!(w, "impl {} for {} {{", s, trait_name).unwrap(); impl_trait_for_c!(supertrait, format!(".{}", i), &resolver); writeln!(w, "}}").unwrap(); walk_supertraits!(supertrait, Some(&types), ( @@ -520,7 +521,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty ) ); // Finally, implement the original Rust trait for the newly created mapped trait. - writeln!(w, "\nuse {}::{}::{} as rust{};", types.orig_crate, types.module_path, t.ident, trait_name).unwrap(); + writeln!(w, "\nuse {}::{} as rust{};", types.module_path, t.ident, trait_name).unwrap(); write!(w, "impl rust{}", t.ident).unwrap(); maybe_write_generics(w, &t.generics, types, false); writeln!(w, " for {} {{", trait_name).unwrap(); @@ -550,7 +551,7 @@ fn writeln_opaque(w: &mut W, ident: &syn::Ident, struct_name: // If we directly read the original type by its original name, cbindgen hits // https://github.com/eqrion/cbindgen/issues/286 Thus, instead, we import it as a temporary // name and then reference it by that name, which works around the issue. - write!(w, "\nuse {}::{}::{} as native{}Import;\ntype native{} = native{}Import", types.orig_crate, types.module_path, ident, ident, ident, ident).unwrap(); + write!(w, "\nuse {}::{} as native{}Import;\ntype native{} = native{}Import", types.module_path, ident, ident, ident, ident).unwrap(); maybe_write_generics(w, &generics, &types, true); writeln!(w, ";\n").unwrap(); writeln!(extra_headers, "struct native{}Opaque;\ntypedef struct native{}Opaque LDKnative{};", ident, ident, ident).unwrap(); @@ -884,9 +885,9 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ t_gen_args += "_" } if takes_self { - write!(w, ">::{}(unsafe {{ &mut *(this_arg as *mut native{}) }}, ", ident, types.orig_crate, $trait_path, t_gen_args, $m.sig.ident, ident).unwrap(); + write!(w, ">::{}(unsafe {{ &mut *(this_arg as *mut native{}) }}, ", ident, $trait_path, t_gen_args, $m.sig.ident, ident).unwrap(); } else { - write!(w, ">::{}(", ident, types.orig_crate, $trait_path, t_gen_args, $m.sig.ident).unwrap(); + write!(w, ">::{}(", ident, $trait_path, t_gen_args, $m.sig.ident).unwrap(); } let mut real_type = "".to_string(); @@ -1020,7 +1021,7 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ } else if takes_self { write!(w, "unsafe {{ &*this_arg.inner }}.{}(", m.sig.ident).unwrap(); } else { - write!(w, "{}::{}::{}(", types.orig_crate, resolved_path, m.sig.ident).unwrap(); + write!(w, "{}::{}(", resolved_path, m.sig.ident).unwrap(); } write_method_call_params(w, &m.sig, "", types, Some(&meth_gen_types), &ret_type, false); writeln!(w, "\n}}\n").unwrap(); @@ -1146,7 +1147,7 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type if var.discriminant.is_some() { unimplemented!(); } writeln!(w, ",").unwrap(); } - writeln!(w, "}}\nuse {}::{}::{} as native{};\nimpl {} {{", types.orig_crate, types.module_path, e.ident, e.ident, e.ident).unwrap(); + writeln!(w, "}}\nuse {}::{} as native{};\nimpl {} {{", types.module_path, e.ident, e.ident, e.ident).unwrap(); macro_rules! write_conv { ($fn_sig: expr, $to_c: expr, $ref: expr) => { @@ -1287,7 +1288,7 @@ fn writeln_fn<'a, 'b, W: std::io::Write>(w: &mut W, f: &'a syn::ItemFn, types: & write_method_params(w, &f.sig, "", types, Some(&gen_types), false, true); write!(w, " {{\n\t").unwrap(); write_method_var_decl_body(w, &f.sig, "", types, Some(&gen_types), false); - write!(w, "{}::{}::{}(", types.orig_crate, types.module_path, f.sig.ident).unwrap(); + write!(w, "{}::{}(", types.module_path, f.sig.ident).unwrap(); write_method_call_params(w, &f.sig, "", types, Some(&gen_types), "", false); writeln!(w, "\n}}\n").unwrap(); } @@ -1329,6 +1330,7 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a> if module == "" { // Special-case the top-level lib.rs with various lint allows and a pointer to the c_types // and bitcoin hand-written modules. + writeln!(out, "//! C Bindings").unwrap(); writeln!(out, "#![allow(unknown_lints)]").unwrap(); writeln!(out, "#![allow(non_camel_case_types)]").unwrap(); writeln!(out, "#![allow(non_snake_case)]").unwrap(); @@ -1351,8 +1353,8 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a> eprintln!("Converting {} entries...", module); - let import_resolver = ImportResolver::new(module, items); - let mut type_resolver = TypeResolver::new(orig_crate, module, import_resolver, crate_types); + let import_resolver = ImportResolver::new(orig_crate, &libast.dependencies, module, items); + let mut type_resolver = TypeResolver::new(module, import_resolver, crate_types); for item in items.iter() { match item { @@ -1385,7 +1387,7 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a> if type_resolver.is_primitive(&resolved_path) { writeln_docs(&mut out, &c.attrs, ""); writeln!(out, "\n#[no_mangle]").unwrap(); - writeln!(out, "pub static {}: {} = {}::{}::{};", c.ident, resolved_path, orig_crate, module, c.ident).unwrap(); + writeln!(out, "pub static {}: {} = {}::{};", c.ident, resolved_path, module, c.ident).unwrap(); } } } @@ -1427,11 +1429,11 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a> } } -fn walk_private_mod<'a>(module: String, items: &'a syn::ItemMod, crate_types: &mut CrateTypes<'a>) { - let import_resolver = ImportResolver::new(&module, &items.content.as_ref().unwrap().1); +fn walk_private_mod<'a>(ast_storage: &'a FullLibraryAST, orig_crate: &str, module: String, items: &'a syn::ItemMod, crate_types: &mut CrateTypes<'a>) { + let import_resolver = ImportResolver::new(orig_crate, &ast_storage.dependencies, &module, &items.content.as_ref().unwrap().1); for item in items.content.as_ref().unwrap().1.iter() { match item { - syn::Item::Mod(m) => walk_private_mod(format!("{}::{}", module, m.ident), m, crate_types), + syn::Item::Mod(m) => walk_private_mod(ast_storage, orig_crate, format!("{}::{}", module, m.ident), m, crate_types), syn::Item::Impl(i) => { if let &syn::Type::Path(ref p) = &*i.self_ty { if let Some(trait_path) = i.trait_.as_ref() { @@ -1452,11 +1454,11 @@ fn walk_private_mod<'a>(module: String, items: &'a syn::ItemMod, crate_types: &m } /// Walk the FullLibraryAST, deciding how things will be mapped and adding tracking to CrateTypes. -fn walk_ast<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a>) { +fn walk_ast<'a>(ast_storage: &'a FullLibraryAST, orig_crate: &str, crate_types: &mut CrateTypes<'a>) { for (module, astmod) in ast_storage.modules.iter() { let ASTModule { ref attrs, ref items, submods: _ } = astmod; assert_eq!(export_status(&attrs), ExportStatus::Export); - let import_resolver = ImportResolver::new(module, items); + let import_resolver = ImportResolver::new(orig_crate, &ast_storage.dependencies, module, items); for item in items.iter() { match item { @@ -1562,7 +1564,7 @@ fn walk_ast<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a } } }, - syn::Item::Mod(m) => walk_private_mod(format!("{}::{}", module, m.ident), m, crate_types), + syn::Item::Mod(m) => walk_private_mod(ast_storage, orig_crate, format!("{}::{}", module, m.ident), m, crate_types), _ => {}, } } @@ -1607,7 +1609,7 @@ fn main() { // ...then walk the ASTs tracking what types we will map, and how, so that we can resolve them // when parsing other file ASTs... let mut libtypes = CrateTypes::new(&mut derived_templates, &libast); - walk_ast(&libast, &mut libtypes); + walk_ast(&libast, &args[2], &mut libtypes); // ... finally, do the actual file conversion/mapping, writing out types as we go. convert_file(&libast, &libtypes, &args[1], &args[2], &mut header_file, &mut cpp_header_file); diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index acfcc1d..edd993f 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -321,33 +321,46 @@ pub enum DeclType<'a> { } pub struct ImportResolver<'mod_lifetime, 'crate_lft: 'mod_lifetime> { + crate_name: &'mod_lifetime str, + dependencies: &'mod_lifetime HashSet, module_path: &'mod_lifetime str, imports: HashMap, declared: HashMap>, priv_modules: HashSet, } impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'crate_lft> { - fn process_use_intern(imports: &mut HashMap, u: &syn::UseTree, partial_path: &str, mut path: syn::punctuated::Punctuated) { + fn process_use_intern(crate_name: &str, dependencies: &HashSet, imports: &mut HashMap, + u: &syn::UseTree, partial_path: &str, mut path: syn::punctuated::Punctuated) { + + let new_path; + macro_rules! push_path { + ($ident: expr, $path_suffix: expr) => { + if partial_path == "" && !dependencies.contains(&$ident) { + new_path = format!("{}::{}{}", crate_name, $ident, $path_suffix); + path.push(syn::PathSegment { ident: syn::Ident::new(crate_name, Span::call_site()), arguments: syn::PathArguments::None }); + } else { + new_path = format!("{}{}{}", partial_path, $ident, $path_suffix); + } + path.push(syn::PathSegment { ident: $ident.clone(), arguments: syn::PathArguments::None }); + } + } match u { syn::UseTree::Path(p) => { - let new_path = format!("{}{}::", partial_path, p.ident); - path.push(syn::PathSegment { ident: p.ident.clone(), arguments: syn::PathArguments::None }); - Self::process_use_intern(imports, &p.tree, &new_path, path); + push_path!(p.ident, "::"); + Self::process_use_intern(crate_name, dependencies, imports, &p.tree, &new_path, path); }, syn::UseTree::Name(n) => { - let full_path = format!("{}{}", partial_path, n.ident); - path.push(syn::PathSegment { ident: n.ident.clone(), arguments: syn::PathArguments::None }); - imports.insert(n.ident.clone(), (full_path, syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path })); + push_path!(n.ident, ""); + imports.insert(n.ident.clone(), (new_path, syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path })); }, syn::UseTree::Group(g) => { for i in g.items.iter() { - Self::process_use_intern(imports, i, partial_path, path.clone()); + Self::process_use_intern(crate_name, dependencies, imports, i, partial_path, path.clone()); } }, syn::UseTree::Rename(r) => { - let full_path = format!("{}{}", partial_path, r.ident); - path.push(syn::PathSegment { ident: r.ident.clone(), arguments: syn::PathArguments::None }); - imports.insert(r.rename.clone(), (full_path, syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path })); + push_path!(r.ident, ""); + imports.insert(r.rename.clone(), (new_path, syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path })); }, syn::UseTree::Glob(_) => { eprintln!("Ignoring * use for {} - this may result in resolution failures", partial_path); @@ -355,24 +368,24 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr } } - fn process_use(imports: &mut HashMap, u: &syn::ItemUse) { + fn process_use(crate_name: &str, dependencies: &HashSet, imports: &mut HashMap, u: &syn::ItemUse) { if let syn::Visibility::Public(_) = u.vis { // We actually only use these for #[cfg(fuzztarget)] eprintln!("Ignoring pub(use) tree!"); return; } if u.leading_colon.is_some() { eprintln!("Ignoring leading-colon use!"); return; } - Self::process_use_intern(imports, &u.tree, "", syn::punctuated::Punctuated::new()); + Self::process_use_intern(crate_name, dependencies, imports, &u.tree, "", syn::punctuated::Punctuated::new()); } fn insert_primitive(imports: &mut HashMap, id: &str) { let ident = syn::Ident::new(id, Span::call_site()); let mut path = syn::punctuated::Punctuated::new(); path.push(syn::PathSegment { ident: ident.clone(), arguments: syn::PathArguments::None }); - imports.insert(ident, (id.to_owned(), syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path })); + imports.insert(ident, (id.to_owned(), syn::Path { leading_colon: None, segments: path })); } - pub fn new(module_path: &'mod_lifetime str, contents: &'crate_lft [syn::Item]) -> Self { + pub fn new(crate_name: &'mod_lifetime str, dependencies: &'mod_lifetime HashSet, module_path: &'mod_lifetime str, contents: &'crate_lft [syn::Item]) -> Self { let mut imports = HashMap::new(); // Add primitives to the "imports" list: Self::insert_primitive(&mut imports, "bool"); @@ -395,7 +408,7 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr for item in contents.iter() { match item { - syn::Item::Use(u) => Self::process_use(&mut imports, &u), + syn::Item::Use(u) => Self::process_use(crate_name, dependencies, &mut imports, &u), syn::Item::Struct(s) => { if let syn::Visibility::Public(_) = s.vis { match export_status(&s.attrs) { @@ -438,7 +451,7 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr } } - Self { module_path, imports, declared, priv_modules } + Self { crate_name, dependencies, module_path, imports, declared, priv_modules } } pub fn get_declared_type(&self, ident: &syn::Ident) -> Option<&DeclType<'crate_lft>> { @@ -476,9 +489,14 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr } else { p_arg }; if p.leading_colon.is_some() { - Some(p.segments.iter().enumerate().map(|(idx, seg)| { + let mut res: String = p.segments.iter().enumerate().map(|(idx, seg)| { format!("{}{}", if idx == 0 { "" } else { "::" }, seg.ident) - }).collect()) + }).collect(); + let firstseg = p.segments.iter().next().unwrap(); + if !self.dependencies.contains(&firstseg.ident) { + res = self.crate_name.to_owned() + "::" + &res; + } + Some(res) } else if let Some(id) = p.get_ident() { self.maybe_resolve_ident(id) } else { @@ -555,6 +573,7 @@ pub struct ASTModule { /// A struct containing the syn::File AST for each file in the crate. pub struct FullLibraryAST { pub modules: HashMap, + pub dependencies: HashSet, } impl FullLibraryAST { fn load_module(&mut self, module: String, attrs: Vec, mut items: Vec) { @@ -579,6 +598,11 @@ impl FullLibraryAST { } }, syn::Item::Mod(_) => panic!("--pretty=expanded output should never have non-body modules"), + syn::Item::ExternCrate(c) => { + if export_status(&c.attrs) == ExportStatus::Export { + self.dependencies.insert(c.ident); + } + }, _ => { non_mod_items.push(item); } } } @@ -587,7 +611,7 @@ impl FullLibraryAST { pub fn load_lib(lib: syn::File) -> Self { assert_eq!(export_status(&lib.attrs), ExportStatus::Export); - let mut res = Self { modules: HashMap::default() }; + let mut res = Self { modules: HashMap::default(), dependencies: HashSet::new() }; res.load_module("".to_owned(), lib.attrs, lib.items); res } @@ -647,7 +671,6 @@ impl<'a> CrateTypes<'a> { /// A struct which tracks resolving rust types into C-mapped equivalents, exists for one specific /// module but contains a reference to the overall CrateTypes tracking. pub struct TypeResolver<'mod_lifetime, 'crate_lft: 'mod_lifetime> { - pub orig_crate: &'mod_lifetime str, pub module_path: &'mod_lifetime str, pub crate_types: &'mod_lifetime CrateTypes<'crate_lft>, types: ImportResolver<'mod_lifetime, 'crate_lft>, @@ -679,8 +702,8 @@ enum ContainerPrefixLocation { } impl<'a, 'c: 'a> TypeResolver<'a, 'c> { - pub fn new(orig_crate: &'a str, module_path: &'a str, types: ImportResolver<'a, 'c>, crate_types: &'a CrateTypes<'c>) -> Self { - Self { orig_crate, module_path, types, crate_types } + pub fn new(module_path: &'a str, types: ImportResolver<'a, 'c>, crate_types: &'a CrateTypes<'c>) -> Self { + Self { module_path, types, crate_types } } // ************************************************* @@ -756,7 +779,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::secp256k1::Error" if !is_ref => Some("crate::c_types::Secp256k1Error"), "bitcoin::blockdata::script::Script" if is_ref => Some("crate::c_types::u8slice"), "bitcoin::blockdata::script::Script" if !is_ref => Some("crate::c_types::derived::CVec_u8Z"), - "bitcoin::blockdata::transaction::OutPoint" => Some("crate::chain::transaction::OutPoint"), + "bitcoin::blockdata::transaction::OutPoint" => Some("crate::lightning::chain::transaction::OutPoint"), "bitcoin::blockdata::transaction::Transaction" => Some("crate::c_types::Transaction"), "bitcoin::blockdata::transaction::TxOut" if !is_ref => Some("crate::c_types::TxOut"), "bitcoin::network::constants::Network" => Some("crate::bitcoin::network::Network"), @@ -769,15 +792,15 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::hash_types::BlockHash" if is_ref => Some("*const [u8; 32]"), "bitcoin::hash_types::BlockHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), "bitcoin::secp256k1::Message" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), - "ln::channelmanager::PaymentHash" if is_ref => Some("*const [u8; 32]"), - "ln::channelmanager::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), - "ln::channelmanager::PaymentPreimage" if is_ref => Some("*const [u8; 32]"), - "ln::channelmanager::PaymentPreimage" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), - "ln::channelmanager::PaymentSecret" if is_ref => Some("crate::c_types::ThirtyTwoBytes"), - "ln::channelmanager::PaymentSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), + "lightning::ln::channelmanager::PaymentHash" if is_ref => Some("*const [u8; 32]"), + "lightning::ln::channelmanager::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), + "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some("*const [u8; 32]"), + "lightning::ln::channelmanager::PaymentPreimage" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), + "lightning::ln::channelmanager::PaymentSecret" if is_ref => Some("crate::c_types::ThirtyTwoBytes"), + "lightning::ln::channelmanager::PaymentSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"), // Override the default since Records contain an fmt with a lifetime: - "util::logger::Record" => Some("*const std::os::raw::c_char"), + "lightning::util::logger::Record" => Some("*const std::os::raw::c_char"), _ => None, } @@ -832,11 +855,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::hash_types::Txid" if is_ref => Some("&::bitcoin::hash_types::Txid::from_slice(&unsafe { &*"), "bitcoin::hash_types::Txid" if !is_ref => Some("::bitcoin::hash_types::Txid::from_slice(&"), "bitcoin::hash_types::BlockHash" => Some("::bitcoin::hash_types::BlockHash::from_slice(&"), - "ln::channelmanager::PaymentHash" if !is_ref => Some("::lightning::ln::channelmanager::PaymentHash("), - "ln::channelmanager::PaymentHash" if is_ref => Some("&::lightning::ln::channelmanager::PaymentHash(unsafe { *"), - "ln::channelmanager::PaymentPreimage" if !is_ref => Some("::lightning::ln::channelmanager::PaymentPreimage("), - "ln::channelmanager::PaymentPreimage" if is_ref => Some("&::lightning::ln::channelmanager::PaymentPreimage(unsafe { *"), - "ln::channelmanager::PaymentSecret" => Some("::lightning::ln::channelmanager::PaymentSecret("), + "lightning::ln::channelmanager::PaymentHash" if !is_ref => Some("::lightning::ln::channelmanager::PaymentHash("), + "lightning::ln::channelmanager::PaymentHash" if is_ref => Some("&::lightning::ln::channelmanager::PaymentHash(unsafe { *"), + "lightning::ln::channelmanager::PaymentPreimage" if !is_ref => Some("::lightning::ln::channelmanager::PaymentPreimage("), + "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some("&::lightning::ln::channelmanager::PaymentPreimage(unsafe { *"), + "lightning::ln::channelmanager::PaymentSecret" => Some("::lightning::ln::channelmanager::PaymentSecret("), // List of traits we map (possibly during processing of other files): "crate::util::logger::Logger" => Some(""), @@ -884,11 +907,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::hash_types::Txid" if is_ref => Some(" }[..]).unwrap()"), "bitcoin::hash_types::Txid" => Some(".data[..]).unwrap()"), "bitcoin::hash_types::BlockHash" if !is_ref => Some(".data[..]).unwrap()"), - "ln::channelmanager::PaymentHash" if !is_ref => Some(".data)"), - "ln::channelmanager::PaymentHash" if is_ref => Some(" })"), - "ln::channelmanager::PaymentPreimage" if !is_ref => Some(".data)"), - "ln::channelmanager::PaymentPreimage" if is_ref => Some(" })"), - "ln::channelmanager::PaymentSecret" => Some(".data)"), + "lightning::ln::channelmanager::PaymentHash" if !is_ref => Some(".data)"), + "lightning::ln::channelmanager::PaymentHash" if is_ref => Some(" })"), + "lightning::ln::channelmanager::PaymentPreimage" if !is_ref => Some(".data)"), + "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some(" })"), + "lightning::ln::channelmanager::PaymentSecret" => Some(".data)"), // List of traits we map (possibly during processing of other files): "crate::util::logger::Logger" => Some(""), @@ -913,7 +936,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // Override the default since Records contain an fmt with a lifetime: // TODO: We should include the other record fields - "util::logger::Record" => Some(("std::ffi::CString::new(format!(\"{}\", ", ".args)).unwrap()")), + "lightning::util::logger::Record" => Some(("std::ffi::CString::new(format!(\"{}\", ", ".args)).unwrap()")), _ => None, }.map(|s| s.to_owned()) } @@ -962,14 +985,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::hash_types::BlockHash" if is_ref => Some(""), "bitcoin::hash_types::BlockHash" => Some("crate::c_types::ThirtyTwoBytes { data: "), "bitcoin::secp256k1::Message" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "), - "ln::channelmanager::PaymentHash" if is_ref => Some("&"), - "ln::channelmanager::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "), - "ln::channelmanager::PaymentPreimage" if is_ref => Some("&"), - "ln::channelmanager::PaymentPreimage" => Some("crate::c_types::ThirtyTwoBytes { data: "), - "ln::channelmanager::PaymentSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "), + "lightning::ln::channelmanager::PaymentHash" if is_ref => Some("&"), + "lightning::ln::channelmanager::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "), + "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some("&"), + "lightning::ln::channelmanager::PaymentPreimage" => Some("crate::c_types::ThirtyTwoBytes { data: "), + "lightning::ln::channelmanager::PaymentSecret" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "), // Override the default since Records contain an fmt with a lifetime: - "util::logger::Record" => Some("local_"), + "lightning::util::logger::Record" => Some("local_"), _ => None, }.map(|s| s.to_owned()) @@ -1020,14 +1043,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "bitcoin::hash_types::BlockHash" if is_ref => Some(".as_inner()"), "bitcoin::hash_types::BlockHash" => Some(".into_inner() }"), "bitcoin::secp256k1::Message" if !is_ref => Some(".as_ref().clone() }"), - "ln::channelmanager::PaymentHash" if is_ref => Some(".0"), - "ln::channelmanager::PaymentHash" => Some(".0 }"), - "ln::channelmanager::PaymentPreimage" if is_ref => Some(".0"), - "ln::channelmanager::PaymentPreimage" => Some(".0 }"), - "ln::channelmanager::PaymentSecret" if !is_ref => Some(".0 }"), + "lightning::ln::channelmanager::PaymentHash" if is_ref => Some(".0"), + "lightning::ln::channelmanager::PaymentHash" => Some(".0 }"), + "lightning::ln::channelmanager::PaymentPreimage" if is_ref => Some(".0"), + "lightning::ln::channelmanager::PaymentPreimage" => Some(".0 }"), + "lightning::ln::channelmanager::PaymentSecret" if !is_ref => Some(".0 }"), // Override the default since Records contain an fmt with a lifetime: - "util::logger::Record" => Some(".as_ptr()"), + "lightning::util::logger::Record" => Some(".as_ptr()"), _ => None, }.map(|s| s.to_owned()) @@ -1035,7 +1058,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { fn empty_val_check_suffix_from_path(&self, full_path: &str) -> Option<&str> { match full_path { - "ln::channelmanager::PaymentSecret" => Some(".data == [0; 32]"), + "lightning::ln::channelmanager::PaymentSecret" => Some(".data == [0; 32]"), "bitcoin::secp256k1::key::PublicKey" => Some(".is_null()"), "bitcoin::secp256k1::Signature" => Some(".is_null()"), _ => None @@ -1264,7 +1287,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // If we're printing a generic argument, it needs to reference the crate, otherwise // the original crate: } else if self.maybe_resolve_path(&path, None).as_ref() == Some(&resolved) { - write!(w, "{}::{}", self.orig_crate, resolved).unwrap(); + write!(w, "{}", resolved).unwrap(); } else { write!(w, "crate::{}", resolved).unwrap(); } diff --git a/genbindings.sh b/genbindings.sh index 0d03950..67489a6 100755 --- a/genbindings.sh +++ b/genbindings.sh @@ -32,7 +32,7 @@ mv lightning-c-bindings/src/bitcoin ./ rm -rf lightning-c-bindings/src -mkdir -p lightning-c-bindings/src/c_types/ +mkdir -p lightning-c-bindings/src/{c_types,lightning} mv ./mod.rs lightning-c-bindings/src/c_types/ mv ./bitcoin lightning-c-bindings/src/ @@ -44,11 +44,20 @@ OUT_CPP="$(pwd)/lightning-c-bindings/include/lightningpp.hpp" BIN="$(pwd)/c-bindings-gen/target/release/c-bindings-gen" pushd "$LIGHTNING_PATH" -RUSTC_BOOTSTRAP=1 cargo rustc $FEATURES_ARGS --profile=check -- -Zunstable-options --pretty=expanded | - RUST_BACKTRACE=1 "$BIN" "$OUT/" lightning "$OUT_TEMPL" "$OUT_F" "$OUT_CPP" -popd +RUSTC_BOOTSTRAP=1 cargo rustc $FEATURES_ARGS --profile=check -- -Zunstable-options --pretty=expanded > /tmp/lightning-crate-source.txt HOST_PLATFORM="$(rustc --version --verbose | grep "host:")" +if [ "$HOST_PLATFORM" = "host: x86_64-apple-darwin" ]; then + # OSX sed is for some reason not compatible with GNU sed + sed -E -i '' 's/#!\[crate_name = "(.*)"\]/pub mod \1 {/' /tmp/lightning-crate-source.txt +else + sed -E -i 's/#!\[crate_name = "(.*)"\]/pub mod \1 {/' /tmp/lightning-crate-source.txt +fi +echo "}" >> /tmp/lightning-crate-source.txt + +cat /tmp/lightning-crate-source.txt | RUST_BACKTRACE=1 "$BIN" "$OUT/" lightning "$OUT_TEMPL" "$OUT_F" "$OUT_CPP" +popd + if [ "$HOST_PLATFORM" = "host: x86_64-apple-darwin" ]; then # OSX sed is for some reason not compatible with GNU sed sed -i '' 's|lightning = { .*|lightning = { path = "'"$LIGHTNING_PATH"'", features = ['"$FEATURES"'] }|' lightning-c-bindings/Cargo.toml -- 2.30.2