Skip to content

Commit d4167cb

Browse files
committed
Switch to single precompiled header in macro fallback
It appears that Clang only supports a single precompiled header at a time. Because the macro fallback depends on the ability to provide multiple precompiled headers at once, this commit changes the code to include all provided headers into a single header to precompile and then pass to the TranslationUnit. This should resolve the issue where the macro fallback would not function as intended when multiple headers were provided as input.
1 parent 2013b8c commit d4167cb

File tree

2 files changed

+79
-51
lines changed

2 files changed

+79
-51
lines changed

bindgen/clang.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,7 +1908,8 @@ impl Drop for TranslationUnit {
19081908
/// Translation unit used for macro fallback parsing
19091909
pub(crate) struct FallbackTranslationUnit {
19101910
file_path: String,
1911-
pch_paths: Vec<String>,
1911+
header_path: String,
1912+
pch_path: String,
19121913
idx: Box<Index>,
19131914
tu: TranslationUnit,
19141915
}
@@ -1923,7 +1924,8 @@ impl FallbackTranslationUnit {
19231924
/// Create a new fallback translation unit
19241925
pub(crate) fn new(
19251926
file: String,
1926-
pch_paths: Vec<String>,
1927+
header_path: String,
1928+
pch_path: String,
19271929
c_args: &[Box<str>],
19281930
) -> Option<Self> {
19291931
// Create empty file
@@ -1944,7 +1946,8 @@ impl FallbackTranslationUnit {
19441946
)?;
19451947
Some(FallbackTranslationUnit {
19461948
file_path: file,
1947-
pch_paths,
1949+
header_path,
1950+
pch_path,
19481951
tu: f_translation_unit,
19491952
idx: f_index,
19501953
})
@@ -1982,9 +1985,8 @@ impl FallbackTranslationUnit {
19821985
impl Drop for FallbackTranslationUnit {
19831986
fn drop(&mut self) {
19841987
let _ = std::fs::remove_file(&self.file_path);
1985-
for pch in self.pch_paths.iter() {
1986-
let _ = std::fs::remove_file(pch);
1987-
}
1988+
let _ = std::fs::remove_file(&self.header_path);
1989+
let _ = std::fs::remove_file(&self.pch_path);
19881990
}
19891991
}
19901992

bindgen/ir/context.rs

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use quote::ToTokens;
2929
use std::borrow::Cow;
3030
use std::cell::{Cell, RefCell};
3131
use std::collections::{BTreeSet, HashMap as StdHashMap};
32+
use std::fs::OpenOptions;
33+
use std::io::Write;
3234
use std::mem;
3335
use std::path::Path;
3436

@@ -2081,55 +2083,79 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20812083

20822084
let index = clang::Index::new(false, false);
20832085

2084-
let mut c_args = Vec::new();
2085-
let mut pch_paths = Vec::new();
2086-
for input_header in self.options().input_headers.iter() {
2087-
let path = Path::new(input_header.as_ref());
2088-
let header_name = path
2089-
.file_name()
2090-
.and_then(|hn| hn.to_str())
2091-
.map(|s| s.to_owned());
2092-
let header_path = path
2093-
.parent()
2094-
.and_then(|hp| hp.to_str())
2095-
.map(|s| s.to_owned());
2096-
2097-
let (header, pch) = if let (Some(ref hp), Some(hn)) =
2098-
(header_path, header_name)
2099-
{
2100-
let header_path = if hp.is_empty() { "." } else { hp };
2101-
let header = format!("{header_path}/{hn}");
2102-
let pch_path = if let Some(ref path) =
2103-
self.options().clang_macro_fallback_build_dir
2104-
{
2105-
path.as_os_str().to_str()?
2106-
} else {
2107-
header_path
2108-
};
2109-
(header, format!("{pch_path}/{hn}.pch"))
2110-
} else {
2111-
return None;
2112-
};
2113-
2114-
let mut tu = clang::TranslationUnit::parse(
2115-
&index,
2116-
&header,
2117-
&[
2118-
"-x".to_owned().into_boxed_str(),
2119-
"c-header".to_owned().into_boxed_str(),
2120-
],
2121-
&[],
2122-
clang_sys::CXTranslationUnit_ForSerialization,
2086+
let (header_names, header_paths, header_contents) =
2087+
self.options.input_headers.iter().try_fold(
2088+
(Vec::new(), Vec::new(), String::new()),
2089+
|(
2090+
mut header_names_to_compile,
2091+
mut header_paths,
2092+
mut header_contents,
2093+
),
2094+
next| {
2095+
let path = Path::new(next.as_ref());
2096+
if let Some(header_path) = path.parent() {
2097+
header_paths
2098+
.push(header_path.as_os_str().to_str()?);
2099+
} else {
2100+
header_paths.push(".");
2101+
}
2102+
let header_name = path.file_name()?.to_str()?;
2103+
header_names_to_compile
2104+
.push(header_name.split(".h").next()?.to_string());
2105+
header_contents +=
2106+
format!("\n#include <{header_name}>").as_str();
2107+
Some((
2108+
header_names_to_compile,
2109+
header_paths,
2110+
header_contents,
2111+
))
2112+
},
21232113
)?;
2124-
tu.save(&pch).ok()?;
2114+
let header_to_precompile = format!(
2115+
"{}/{}",
2116+
match self.options().clang_macro_fallback_build_dir {
2117+
Some(ref path) => path.as_os_str().to_str()?,
2118+
None => ".",
2119+
},
2120+
header_names.join("-") + ".h"
2121+
);
2122+
let pch = header_to_precompile.clone() + ".pch";
2123+
2124+
let mut header_to_precompile_file = OpenOptions::new()
2125+
.create(true)
2126+
.truncate(true)
2127+
.write(true)
2128+
.open(&header_to_precompile)
2129+
.ok()?;
2130+
header_to_precompile_file
2131+
.write_all(header_contents.as_bytes())
2132+
.ok()?;
21252133

2126-
c_args.push("-include-pch".to_string().into_boxed_str());
2127-
c_args.push(pch.clone().into_boxed_str());
2128-
pch_paths.push(pch);
2134+
let mut c_args = Vec::new();
2135+
c_args.push("-x".to_string().into_boxed_str());
2136+
c_args.push("c-header".to_string().into_boxed_str());
2137+
for header_path in header_paths {
2138+
c_args.push("-I".to_string().into_boxed_str());
2139+
c_args.push(header_path.to_string().into_boxed_str());
21292140
}
2130-
2141+
let mut tu = clang::TranslationUnit::parse(
2142+
&index,
2143+
&header_to_precompile,
2144+
&c_args,
2145+
&[],
2146+
clang_sys::CXTranslationUnit_ForSerialization,
2147+
)?;
2148+
tu.save(&pch).ok()?;
2149+
2150+
let c_args = vec![
2151+
"-include-pch".to_string().into_boxed_str(),
2152+
pch.clone().into_boxed_str(),
2153+
];
21312154
self.fallback_tu = Some(clang::FallbackTranslationUnit::new(
2132-
file, pch_paths, &c_args,
2155+
file,
2156+
header_to_precompile,
2157+
pch,
2158+
&c_args,
21332159
)?);
21342160
}
21352161

0 commit comments

Comments
 (0)