diff options
author | Christian Poveda <31802960+pvdrz@users.noreply.github.com> | 2022-09-23 02:04:28 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-23 09:04:28 +0200 |
commit | 4b006da21bd7a6701c8e7f658085569830207c9c (patch) | |
tree | 109bfd3b7f98b005f2806a0cd4593071e66a8bb6 /src | |
parent | 04c0cd0ff45ff3f47d845c2b3b983e2dc06b9ca3 (diff) |
Add option to deduplicate extern blocks (#2258)
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 73 | ||||
-rw-r--r-- | src/options.rs | 7 |
2 files changed, 77 insertions, 3 deletions
@@ -615,6 +615,10 @@ impl Builder { output_vector.push("--sort-semantically".into()); } + if self.options.merge_extern_blocks { + output_vector.push("--merge-extern-blocks".into()); + } + // Add clang arguments output_vector.push("--".into()); @@ -1542,7 +1546,7 @@ impl Builder { self } - /// If true, enables the sorting of the output in a predefined manner + /// If true, enables the sorting of the output in a predefined manner. /// /// TODO: Perhaps move the sorting order out into a config pub fn sort_semantically(mut self, doit: bool) -> Self { @@ -1550,6 +1554,12 @@ impl Builder { self } + /// If true, merges extern blocks. + pub fn merge_extern_blocks(mut self, doit: bool) -> Self { + self.options.merge_extern_blocks = doit; + self + } + /// Generate the Rust bindings using the options built up thus far. pub fn generate(mut self) -> Result<Bindings, BindgenError> { // Add any extra arguments from the environment to the clang command line. @@ -2095,8 +2105,11 @@ struct BindgenOptions { /// Emit vtable functions. vtable_generation: bool, - /// Sort the code generation + /// Sort the code generation. sort_semantically: bool, + + /// Deduplicate `extern` blocks. + merge_extern_blocks: bool, } /// TODO(emilio): This is sort of a lie (see the error message that results from @@ -2107,7 +2120,7 @@ impl ::std::panic::UnwindSafe for BindgenOptions {} impl BindgenOptions { /// Whether any of the enabled options requires `syn`. fn require_syn(&self) -> bool { - self.sort_semantically + self.sort_semantically || self.merge_extern_blocks } fn build(&mut self) { @@ -2258,6 +2271,7 @@ impl Default for BindgenOptions { force_explicit_padding: false, vtable_generation: false, sort_semantically: false, + merge_extern_blocks: false, } } } @@ -2563,6 +2577,59 @@ impl Bindings { .unwrap() .1; + if options.merge_extern_blocks { + // Here we will store all the items after deduplication. + let mut items = Vec::new(); + + // Keep all the extern blocks in a different `Vec` for faster search. + let mut foreign_mods = Vec::<syn::ItemForeignMod>::new(); + for item in syn_parsed_items { + match item { + syn::Item::ForeignMod(syn::ItemForeignMod { + attrs, + abi, + brace_token, + items: foreign_items, + }) => { + let mut exists = false; + for foreign_mod in &mut foreign_mods { + // Check if there is a extern block with the same ABI and + // attributes. + if foreign_mod.attrs == attrs && + foreign_mod.abi == abi + { + // Merge the items of the two blocks. + foreign_mod + .items + .extend_from_slice(&foreign_items); + exists = true; + break; + } + } + // If no existing extern block had the same ABI and attributes, store + // it. + if !exists { + foreign_mods.push(syn::ItemForeignMod { + attrs, + abi, + brace_token, + items: foreign_items, + }); + } + } + // If the item is not an extern block, we don't have to do anything. + _ => items.push(item), + } + } + + // Move all the extern blocks alongiside the rest of the items. + for foreign_mod in foreign_mods { + items.push(syn::Item::ForeignMod(foreign_mod)); + } + + syn_parsed_items = items; + } + if options.sort_semantically { syn_parsed_items.sort_by_key(|item| match item { syn::Item::Type(_) => 0, diff --git a/src/options.rs b/src/options.rs index 1e87b6eb..f707ab9b 100644 --- a/src/options.rs +++ b/src/options.rs @@ -560,6 +560,9 @@ where Arg::new("sort-semantically") .long("sort-semantically") .help("Enables sorting of code generation in a predefined manner."), + Arg::new("merge-extern-blocks") + .long("merge-extern-blocks") + .help("Deduplicates extern blocks."), Arg::new("V") .long("version") .help("Prints the version, and exits"), @@ -1076,5 +1079,9 @@ where builder = builder.sort_semantically(true); } + if matches.is_present("merge-extern-blocks") { + builder = builder.merge_extern_blocks(true); + } + Ok((builder, output, verbose)) } |