@@ -615,6 +615,10 @@ impl Builder {
615
615
output_vector. push ( "--sort-semantically" . into ( ) ) ;
616
616
}
617
617
618
+ if self . options . merge_extern_blocks {
619
+ output_vector. push ( "--merge-extern-blocks" . into ( ) ) ;
620
+ }
621
+
618
622
// Add clang arguments
619
623
620
624
output_vector. push ( "--" . into ( ) ) ;
@@ -1542,14 +1546,20 @@ impl Builder {
1542
1546
self
1543
1547
}
1544
1548
1545
- /// If true, enables the sorting of the output in a predefined manner
1549
+ /// If true, enables the sorting of the output in a predefined manner.
1546
1550
///
1547
1551
/// TODO: Perhaps move the sorting order out into a config
1548
1552
pub fn sort_semantically ( mut self , doit : bool ) -> Self {
1549
1553
self . options . sort_semantically = doit;
1550
1554
self
1551
1555
}
1552
1556
1557
+ /// If true, merges extern blocks.
1558
+ pub fn merge_extern_blocks ( mut self , doit : bool ) -> Self {
1559
+ self . options . merge_extern_blocks = doit;
1560
+ self
1561
+ }
1562
+
1553
1563
/// Generate the Rust bindings using the options built up thus far.
1554
1564
pub fn generate ( mut self ) -> Result < Bindings , BindgenError > {
1555
1565
// Add any extra arguments from the environment to the clang command line.
@@ -2095,8 +2105,11 @@ struct BindgenOptions {
2095
2105
/// Emit vtable functions.
2096
2106
vtable_generation : bool ,
2097
2107
2098
- /// Sort the code generation
2108
+ /// Sort the code generation.
2099
2109
sort_semantically : bool ,
2110
+
2111
+ /// Deduplicate `extern` blocks.
2112
+ merge_extern_blocks : bool ,
2100
2113
}
2101
2114
2102
2115
/// 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 {}
2107
2120
impl BindgenOptions {
2108
2121
/// Whether any of the enabled options requires `syn`.
2109
2122
fn require_syn ( & self ) -> bool {
2110
- self . sort_semantically
2123
+ self . sort_semantically || self . merge_extern_blocks
2111
2124
}
2112
2125
2113
2126
fn build ( & mut self ) {
@@ -2258,6 +2271,7 @@ impl Default for BindgenOptions {
2258
2271
force_explicit_padding : false ,
2259
2272
vtable_generation : false ,
2260
2273
sort_semantically : false ,
2274
+ merge_extern_blocks : false ,
2261
2275
}
2262
2276
}
2263
2277
}
@@ -2563,6 +2577,59 @@ impl Bindings {
2563
2577
. unwrap ( )
2564
2578
. 1 ;
2565
2579
2580
+ if options. merge_extern_blocks {
2581
+ // Here we will store all the items after deduplication.
2582
+ let mut items = Vec :: new ( ) ;
2583
+
2584
+ // Keep all the extern blocks in a different `Vec` for faster search.
2585
+ let mut foreign_mods = Vec :: < syn:: ItemForeignMod > :: new ( ) ;
2586
+ for item in syn_parsed_items {
2587
+ match item {
2588
+ syn:: Item :: ForeignMod ( syn:: ItemForeignMod {
2589
+ attrs,
2590
+ abi,
2591
+ brace_token,
2592
+ items : foreign_items,
2593
+ } ) => {
2594
+ let mut exists = false ;
2595
+ for foreign_mod in & mut foreign_mods {
2596
+ // Check if there is a extern block with the same ABI and
2597
+ // attributes.
2598
+ if foreign_mod. attrs == attrs &&
2599
+ foreign_mod. abi == abi
2600
+ {
2601
+ // Merge the items of the two blocks.
2602
+ foreign_mod
2603
+ . items
2604
+ . extend_from_slice ( & foreign_items) ;
2605
+ exists = true ;
2606
+ break ;
2607
+ }
2608
+ }
2609
+ // If no existing extern block had the same ABI and attributes, store
2610
+ // it.
2611
+ if !exists {
2612
+ foreign_mods. push ( syn:: ItemForeignMod {
2613
+ attrs,
2614
+ abi,
2615
+ brace_token,
2616
+ items : foreign_items,
2617
+ } ) ;
2618
+ }
2619
+ }
2620
+ // If the item is not an extern block, we don't have to do anything.
2621
+ _ => items. push ( item) ,
2622
+ }
2623
+ }
2624
+
2625
+ // Move all the extern blocks alongiside the rest of the items.
2626
+ for foreign_mod in foreign_mods {
2627
+ items. push ( syn:: Item :: ForeignMod ( foreign_mod) ) ;
2628
+ }
2629
+
2630
+ syn_parsed_items = items;
2631
+ }
2632
+
2566
2633
if options. sort_semantically {
2567
2634
syn_parsed_items. sort_by_key ( |item| match item {
2568
2635
syn:: Item :: Type ( _) => 0 ,
0 commit comments