@@ -592,6 +592,10 @@ impl Builder {
592
592
output_vector. push ( "--sort-semantically" . into ( ) ) ;
593
593
}
594
594
595
+ if self . options . deduplicate_extern_blocks {
596
+ output_vector. push ( "--deduplicate-extern-blocks" . into ( ) ) ;
597
+ }
598
+
595
599
// Add clang arguments
596
600
597
601
output_vector. push ( "--" . into ( ) ) ;
@@ -1481,14 +1485,20 @@ impl Builder {
1481
1485
self
1482
1486
}
1483
1487
1484
- /// If true, enables the sorting of the output in a predefined manner
1488
+ /// If true, enables the sorting of the output in a predefined manner.
1485
1489
///
1486
1490
/// TODO: Perhaps move the sorting order out into a config
1487
1491
pub fn sort_semantically ( mut self , doit : bool ) -> Self {
1488
1492
self . options . sort_semantically = doit;
1489
1493
self
1490
1494
}
1491
1495
1496
+ /// If true, deduplicates extern blocks.
1497
+ pub fn deduplicate_extern_blocks ( mut self , doit : bool ) -> Self {
1498
+ self . options . deduplicate_extern_blocks = doit;
1499
+ self
1500
+ }
1501
+
1492
1502
/// Generate the Rust bindings using the options built up thus far.
1493
1503
pub fn generate ( mut self ) -> Result < Bindings , BindgenError > {
1494
1504
// Add any extra arguments from the environment to the clang command line.
@@ -2019,8 +2029,11 @@ struct BindgenOptions {
2019
2029
/// Emit vtable functions.
2020
2030
vtable_generation : bool ,
2021
2031
2022
- /// Sort the code generation
2032
+ /// Sort the code generation.
2023
2033
sort_semantically : bool ,
2034
+
2035
+ /// Deduplicate `extern` blocks.
2036
+ deduplicate_extern_blocks : bool ,
2024
2037
}
2025
2038
2026
2039
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -2031,7 +2044,7 @@ impl ::std::panic::UnwindSafe for BindgenOptions {}
2031
2044
impl BindgenOptions {
2032
2045
/// Whether any of the enabled options requires `syn`.
2033
2046
fn require_syn ( & self ) -> bool {
2034
- self . sort_semantically
2047
+ self . sort_semantically || self . deduplicate_extern_blocks
2035
2048
}
2036
2049
2037
2050
fn build ( & mut self ) {
@@ -2175,6 +2188,7 @@ impl Default for BindgenOptions {
2175
2188
force_explicit_padding : false ,
2176
2189
vtable_generation : false ,
2177
2190
sort_semantically : false ,
2191
+ deduplicate_extern_blocks : false ,
2178
2192
}
2179
2193
}
2180
2194
}
@@ -2480,6 +2494,59 @@ impl Bindings {
2480
2494
. unwrap ( )
2481
2495
. 1 ;
2482
2496
2497
+ if options. deduplicate_extern_blocks {
2498
+ // Here we will store all the items after deduplication.
2499
+ let mut items = Vec :: new ( ) ;
2500
+
2501
+ // Keep all the extern blocks in a different `Vec` for faster search.
2502
+ let mut foreign_mods = Vec :: < syn:: ItemForeignMod > :: new ( ) ;
2503
+ for item in syn_parsed_items {
2504
+ match item {
2505
+ syn:: Item :: ForeignMod ( syn:: ItemForeignMod {
2506
+ attrs,
2507
+ abi,
2508
+ brace_token,
2509
+ items : foreign_items,
2510
+ } ) => {
2511
+ let mut exists = false ;
2512
+ for foreign_mod in & mut foreign_mods {
2513
+ // Check if there is a extern block with the same ABI and
2514
+ // attributes.
2515
+ if foreign_mod. attrs == attrs &&
2516
+ foreign_mod. abi == abi
2517
+ {
2518
+ // Merge the items of the two blocks.
2519
+ foreign_mod
2520
+ . items
2521
+ . extend_from_slice ( & foreign_items) ;
2522
+ exists = true ;
2523
+ break ;
2524
+ }
2525
+ }
2526
+ // If no existing extern block had the same ABI and attributes, store
2527
+ // it.
2528
+ if !exists {
2529
+ foreign_mods. push ( syn:: ItemForeignMod {
2530
+ attrs,
2531
+ abi,
2532
+ brace_token,
2533
+ items : foreign_items,
2534
+ } ) ;
2535
+ }
2536
+ }
2537
+ // If the item is not an extern block, we don't have to do anything.
2538
+ _ => items. push ( item) ,
2539
+ }
2540
+ }
2541
+
2542
+ // Move all the extern blocks alongiside the rest of the items.
2543
+ for foreign_mod in foreign_mods {
2544
+ items. push ( syn:: Item :: ForeignMod ( foreign_mod) ) ;
2545
+ }
2546
+
2547
+ syn_parsed_items = items;
2548
+ }
2549
+
2483
2550
if options. sort_semantically {
2484
2551
syn_parsed_items. sort_by_key ( |item| match item {
2485
2552
syn:: Item :: Type ( _) => 0 ,
0 commit comments