@@ -1559,25 +1559,33 @@ impl Builder {
1559
1559
}
1560
1560
1561
1561
/// Generate the Rust bindings using the options built up thus far.
1562
- pub fn generate ( mut self ) -> Result < Bindings , BindgenError > {
1562
+ pub fn generate ( self ) -> Result < Bindings , BindgenError > {
1563
+ let mut options = self . options . clone ( ) ;
1563
1564
// Add any extra arguments from the environment to the clang command line.
1564
- self . options . clang_args . extend ( get_extra_clang_args ( ) ) ;
1565
+ options. clang_args . extend ( get_extra_clang_args ( ) ) ;
1565
1566
1566
1567
// Transform input headers to arguments on the clang command line.
1567
- self . options . clang_args . extend (
1568
- self . options . input_headers
1569
- [ ..self . options . input_headers . len ( ) . saturating_sub ( 1 ) ]
1568
+ options. clang_args . extend (
1569
+ options. input_headers
1570
+ [ ..options. input_headers . len ( ) . saturating_sub ( 1 ) ]
1570
1571
. iter ( )
1571
1572
. flat_map ( |header| [ "-include" . into ( ) , header. to_string ( ) ] ) ,
1572
1573
) ;
1573
1574
1574
1575
let input_unsaved_files =
1575
- std:: mem:: take ( & mut self . options . input_header_contents )
1576
+ std:: mem:: take ( & mut options. input_header_contents )
1576
1577
. into_iter ( )
1577
1578
. map ( |( name, contents) | clang:: UnsavedFile :: new ( name, contents) )
1578
1579
. collect :: < Vec < _ > > ( ) ;
1579
1580
1580
- Bindings :: generate ( self . options , input_unsaved_files)
1581
+ match Bindings :: generate ( options, input_unsaved_files) {
1582
+ GenerateResult :: Ok ( bindings) => Ok ( bindings) ,
1583
+ GenerateResult :: ShouldRestart { header } => self
1584
+ . header ( header)
1585
+ . generate_inline_functions ( false )
1586
+ . generate ( ) ,
1587
+ GenerateResult :: Err ( err) => Err ( err) ,
1588
+ }
1581
1589
}
1582
1590
1583
1591
/// Preprocess and dump the input header files to disk.
@@ -2282,6 +2290,18 @@ fn ensure_libclang_is_loaded() {
2282
2290
#[ cfg( not( feature = "runtime" ) ) ]
2283
2291
fn ensure_libclang_is_loaded ( ) { }
2284
2292
2293
+ #[ derive( Debug ) ]
2294
+ enum GenerateResult {
2295
+ Ok ( Bindings ) ,
2296
+ /// Error variant raised when bindgen requires to run again with a newly generated header
2297
+ /// input.
2298
+ #[ allow( dead_code) ]
2299
+ ShouldRestart {
2300
+ header : String ,
2301
+ } ,
2302
+ Err ( BindgenError ) ,
2303
+ }
2304
+
2285
2305
/// Error type for rust-bindgen.
2286
2306
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
2287
2307
#[ non_exhaustive]
@@ -2375,7 +2395,7 @@ impl Bindings {
2375
2395
pub ( crate ) fn generate (
2376
2396
mut options : BindgenOptions ,
2377
2397
input_unsaved_files : Vec < clang:: UnsavedFile > ,
2378
- ) -> Result < Bindings , BindgenError > {
2398
+ ) -> GenerateResult {
2379
2399
ensure_libclang_is_loaded ( ) ;
2380
2400
2381
2401
#[ cfg( feature = "runtime" ) ]
@@ -2496,17 +2516,22 @@ impl Bindings {
2496
2516
let path = Path :: new ( h) ;
2497
2517
if let Ok ( md) = std:: fs:: metadata ( path) {
2498
2518
if md. is_dir ( ) {
2499
- return Err ( BindgenError :: FolderAsHeader ( path. into ( ) ) ) ;
2519
+ return GenerateResult :: Err (
2520
+ BindgenError :: FolderAsHeader ( path. into ( ) ) . into ( ) ,
2521
+ ) ;
2500
2522
}
2501
2523
if !can_read ( & md. permissions ( ) ) {
2502
- return Err ( BindgenError :: InsufficientPermissions (
2503
- path. into ( ) ,
2504
- ) ) ;
2524
+ return GenerateResult :: Err (
2525
+ BindgenError :: InsufficientPermissions ( path. into ( ) )
2526
+ . into ( ) ,
2527
+ ) ;
2505
2528
}
2506
2529
let h = h. clone ( ) ;
2507
2530
options. clang_args . push ( h) ;
2508
2531
} else {
2509
- return Err ( BindgenError :: NotExist ( path. into ( ) ) ) ;
2532
+ return GenerateResult :: Err (
2533
+ BindgenError :: NotExist ( path. into ( ) ) . into ( ) ,
2534
+ ) ;
2510
2535
}
2511
2536
}
2512
2537
@@ -2534,12 +2559,14 @@ impl Bindings {
2534
2559
2535
2560
{
2536
2561
let _t = time:: Timer :: new ( "parse" ) . with_output ( time_phases) ;
2537
- parse ( & mut context) ?;
2562
+ if let Err ( err) = parse ( & mut context) {
2563
+ return GenerateResult :: Err ( err) ;
2564
+ }
2538
2565
}
2539
2566
2540
2567
let ( module, options, warnings) = codegen:: codegen ( context) ;
2541
2568
2542
- Ok ( Bindings {
2569
+ GenerateResult :: Ok ( Bindings {
2543
2570
options,
2544
2571
warnings,
2545
2572
module,
0 commit comments