hack: Add a BINDGEN_USE_BINARY=/path/to/bindgen.
diff --git a/src/lib.rs b/src/lib.rs
index ce0d5d4..3d25982 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1327,6 +1327,15 @@
 
     /// Generate the Rust bindings using the options built up thus far.
     pub fn generate(mut self) -> Result<Bindings, ()> {
+        if let Some(bin) = env::var_os("BINDGEN_USE_BINARY") {
+            let output = Command::new(bin)
+                .args(self.command_line_flags())
+                .env_remove("BINDGEN_USE_BINARY")
+                .output()
+                .expect("Failed to run BINDGEN_USE_BINARY");
+            return Ok(Bindings(BindingsInner::Eager(String::from_utf8(output.stdout).expect("Bindgen should only generate valid utf-8"))));
+        }
+
         // Add any extra arguments from the environment to the clang command line.
         if let Some(extra_clang_args) =
             env::var("BINDGEN_EXTRA_CLANG_ARGS").ok()
@@ -1951,9 +1960,15 @@
 
 /// Generated Rust bindings.
 #[derive(Debug)]
-pub struct Bindings {
-    options: BindgenOptions,
-    module: proc_macro2::TokenStream,
+pub struct Bindings(BindingsInner);
+
+#[derive(Debug)]
+enum BindingsInner {
+    Lazy {
+        options: BindgenOptions,
+        module: proc_macro2::TokenStream,
+    },
+    Eager(String),
 }
 
 pub(crate) const HOST_TARGET: &'static str =
@@ -2166,16 +2181,20 @@
 
         let (items, options) = codegen::codegen(context);
 
-        Ok(Bindings {
+        Ok(Bindings(BindingsInner::Lazy {
             options,
             module: quote! {
                 #( #items )*
             },
-        })
+        }))
     }
 
     /// Convert these bindings into source text (with raw lines prepended).
     pub fn to_string(&self) -> String {
+        if let BindingsInner::Eager(ref s) = self.0 {
+            return s.clone()
+        }
+
         let mut bytes = vec![];
         self.write(Box::new(&mut bytes) as Box<dyn Write>)
             .expect("writing to a vec cannot fail");
@@ -2196,7 +2215,12 @@
 
     /// Write these bindings as source text to the given `Write`able.
     pub fn write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()> {
-        if !self.options.disable_header_comment {
+        let (options, module) = match self.0 {
+            BindingsInner::Eager(ref s) => return writer.write_all(s.as_bytes()),
+            BindingsInner::Lazy { ref options, ref module } => (options, module),
+        };
+
+        if !options.disable_header_comment {
             let version = option_env!("CARGO_PKG_VERSION");
             let header = format!(
                 "/* automatically generated by rust-bindgen {} */\n\n",
@@ -2205,18 +2229,18 @@
             writer.write_all(header.as_bytes())?;
         }
 
-        for line in self.options.raw_lines.iter() {
+        for line in options.raw_lines.iter() {
             writer.write_all(line.as_bytes())?;
             writer.write_all("\n".as_bytes())?;
         }
 
-        if !self.options.raw_lines.is_empty() {
+        if !options.raw_lines.is_empty() {
             writer.write_all("\n".as_bytes())?;
         }
 
-        let bindings = self.module.to_string();
+        let bindings = module.to_string();
 
-        match self.rustfmt_generated_string(&bindings) {
+        match self.rustfmt_generated_string(&bindings, options) {
             Ok(rustfmt_bindings) => {
                 writer.write_all(rustfmt_bindings.as_bytes())?;
             }
@@ -2232,9 +2256,9 @@
     }
 
     /// Gets the rustfmt path to rustfmt the generated bindings.
-    fn rustfmt_path<'a>(&'a self) -> io::Result<Cow<'a, PathBuf>> {
-        debug_assert!(self.options.rustfmt_bindings);
-        if let Some(ref p) = self.options.rustfmt_path {
+    fn rustfmt_path<'a>(options: &'a BindgenOptions) -> io::Result<Cow<'a, PathBuf>> {
+        debug_assert!(options.rustfmt_bindings);
+        if let Some(ref p) = options.rustfmt_path {
             return Ok(Cow::Borrowed(p));
         }
         if let Ok(rustfmt) = env::var("RUSTFMT") {
@@ -2257,21 +2281,22 @@
     fn rustfmt_generated_string<'a>(
         &self,
         source: &'a str,
+        options: &BindgenOptions,
     ) -> io::Result<Cow<'a, str>> {
         let _t = time::Timer::new("rustfmt_generated_string")
-            .with_output(self.options.time_phases);
+            .with_output(options.time_phases);
 
-        if !self.options.rustfmt_bindings {
+        if !options.rustfmt_bindings {
             return Ok(Cow::Borrowed(source));
         }
 
-        let rustfmt = self.rustfmt_path()?;
+        let rustfmt = Self::rustfmt_path(options)?;
         let mut cmd = Command::new(&*rustfmt);
 
         cmd.stdin(Stdio::piped()).stdout(Stdio::piped());
 
-        if let Some(path) = self
-            .options
+        if let Some(path) =
+            options
             .rustfmt_configuration_file
             .as_ref()
             .and_then(|f| f.to_str())