From 7129d896a218a035c177930c11b954734f9f180c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 3 May 2018 04:21:08 +0200 Subject: [PATCH 1/4] lib: Add and document an API to add per-module raw lines. --- src/lib.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c715b9c2fb..9073800f5d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,6 +85,7 @@ use parse::{ClangItemParser, ParseError}; use regex_set::RegexSet; use std::borrow::Cow; +use std::collections::HashMap; use std::fs::{File, OpenOptions}; use std::io::{self, Write}; use std::iter; @@ -766,11 +767,25 @@ impl Builder { /// Add a string to prepend to the generated bindings. The string is passed /// through without any modification. - pub fn raw_line>(mut self, arg: T) -> Builder { + pub fn raw_line>(mut self, arg: T) -> Self { self.options.raw_lines.push(arg.into()); self } + /// Add a given line to the beginning of module `mod`. + pub fn module_raw_line(mut self, mod_: T, line: U) -> Self + where + T: Into, + U: Into, + { + self.options + .module_lines + .entry(mod_.into()) + .or_insert_with(Vec::new) + .push(line.into()); + self + } + /// Add an argument to be passed straight through to clang. pub fn clang_arg>(mut self, arg: T) -> Builder { self.options.clang_args.push(arg.into()); @@ -1300,9 +1315,15 @@ struct BindgenOptions { /// Whether we should convert float types to f32/f64 types. convert_floats: bool, - /// The set of raw lines to prepend to the generated Rust code. + /// The set of raw lines to prepend to the top-level module of generated + /// Rust code. raw_lines: Vec, + /// The set of raw lines to prepend to each of the modules. + /// + /// This only makes sense if the `enable_cxx_namespaces` option is set. + module_lines: HashMap>, + /// The set of arguments to pass straight through to Clang. clang_args: Vec, @@ -1448,6 +1469,7 @@ impl Default for BindgenOptions { msvc_mangling: false, convert_floats: true, raw_lines: vec![], + module_lines: HashMap::default(), clang_args: vec![], input_header: None, input_unsaved_files: vec![], From c209aefc362e25e6c5953ceab7e815a621a629f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 3 May 2018 04:33:09 +0200 Subject: [PATCH 2/4] codegen: Actually honor the new option for module_lines. Only when modules are enabled of course. --- src/codegen/mod.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 04e28db238..fd48ff2bbb 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -422,6 +422,18 @@ impl CodeGenerator for Module { let mut found_any = false; let inner_items = result.inner(|result| { result.push(root_import(ctx, item)); + + let path = item.namespace_aware_canonical_path(ctx).join("::"); + if let Some(raw_lines) = ctx.options().module_lines.get(&path) { + for raw_line in raw_lines { + found_any = true; + // FIXME(emilio): The use of `Term` is an abuse, but we abuse it + // in a bunch more places. + let line = Term::new(raw_line, Span::call_site()); + result.push(quote! { #line }); + } + } + codegen_self(result, &mut found_any); }); @@ -431,16 +443,15 @@ impl CodeGenerator for Module { } let name = item.canonical_name(ctx); - - result.push(if name == "root" { + let ident = ctx.rust_ident(name); + result.push(if item.id() == ctx.root_module() { quote! { #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] - pub mod root { + pub mod #ident { #( #inner_items )* } } } else { - let ident = ctx.rust_ident(name); quote! { pub mod #ident { #( #inner_items )* From f7b0b170a0e3aee7d7da3527fca904b11ed99a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 3 May 2018 04:42:19 +0200 Subject: [PATCH 3/4] Add tests for the new option. --- bindgen-integration/build.rs | 1 + bindgen-integration/src/lib.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/bindgen-integration/build.rs b/bindgen-integration/build.rs index ed5b928150..f7e8b4eb8c 100644 --- a/bindgen-integration/build.rs +++ b/bindgen-integration/build.rs @@ -38,6 +38,7 @@ fn main() { .enable_cxx_namespaces() .rustified_enum(".*") .raw_line("pub use self::root::*;") + .module_raw_line("root::testing", "pub type Bar = i32;") .header("cpp/Test.h") .clang_args(&["-x", "c++", "-std=c++11"]) .parse_callbacks(Box::new(MacroCallback {macros: macros.clone()})) diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index 176da3bb20..74b4df4f42 100755 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -8,6 +8,9 @@ use std::ffi::CStr; use std::os::raw::c_int; use std::mem; +#[allow(unused)] +use bindings::testing::Bar; // This type is generated from module_raw_line. + #[test] fn test_static_array() { let mut test = unsafe { bindings::Test_COUNTDOWN.as_ptr() }; From 786ed31d471ba01a30343efdc6b341959801b939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 3 May 2018 04:46:48 +0200 Subject: [PATCH 4/4] lib: Add a more-convenient API to add multiple lines to the same module. --- src/lib.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 9073800f5d..2c90405624 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -786,6 +786,21 @@ impl Builder { self } + /// Add a given set of lines to the beginning of module `mod`. + pub fn module_raw_lines(mut self, mod_: T, lines: I) -> Self + where + T: Into, + I: IntoIterator, + I::Item: Into, + { + self.options + .module_lines + .entry(mod_.into()) + .or_insert_with(Vec::new) + .extend(lines.into_iter().map(Into::into)); + self + } + /// Add an argument to be passed straight through to clang. pub fn clang_arg>(mut self, arg: T) -> Builder { self.options.clang_args.push(arg.into());