diff --git a/Cargo.lock b/Cargo.lock index 4e88c224f5..4827e15da6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,6 +52,7 @@ dependencies = [ "rustc-hash", "shlex", "syn 2.0.90", + "tempfile", ] [[package]] diff --git a/bindgen/Cargo.toml b/bindgen/Cargo.toml index c01f8f0c44..7cb5f0a506 100644 --- a/bindgen/Cargo.toml +++ b/bindgen/Cargo.toml @@ -41,6 +41,7 @@ regex = { workspace = true, features = ["std", "unicode-perl"] } rustc-hash.workspace = true shlex.workspace = true syn = { workspace = true, features = ["full", "extra-traits", "visit-mut"] } +tempfile.workspace = true [features] default = ["logging", "prettyplease", "runtime"] diff --git a/bindgen/clang.rs b/bindgen/clang.rs index 04fe3e1538..3fa866d78c 100644 --- a/bindgen/clang.rs +++ b/bindgen/clang.rs @@ -7,6 +7,8 @@ use crate::ir::context::BindgenContext; use clang_sys::*; use std::cmp; +use std::path::{Path, PathBuf}; +use tempfile::TempDir; use std::ffi::{CStr, CString}; use std::fmt; @@ -246,11 +248,10 @@ impl Cursor { pub(crate) fn is_toplevel(&self) -> bool { let mut semantic_parent = self.fallible_semantic_parent(); - while semantic_parent.is_some() && - (semantic_parent.unwrap().kind() == CXCursor_Namespace || - semantic_parent.unwrap().kind() == - CXCursor_NamespaceAlias || - semantic_parent.unwrap().kind() == CXCursor_NamespaceRef) + while semantic_parent.is_some() + && (semantic_parent.unwrap().kind() == CXCursor_Namespace + || semantic_parent.unwrap().kind() == CXCursor_NamespaceAlias + || semantic_parent.unwrap().kind() == CXCursor_NamespaceRef) { semantic_parent = semantic_parent.unwrap().fallible_semantic_parent(); @@ -267,9 +268,9 @@ impl Cursor { pub(crate) fn is_template_like(&self) -> bool { matches!( self.kind(), - CXCursor_ClassTemplate | - CXCursor_ClassTemplatePartialSpecialization | - CXCursor_TypeAliasTemplateDecl + CXCursor_ClassTemplate + | CXCursor_ClassTemplatePartialSpecialization + | CXCursor_TypeAliasTemplateDecl ) } @@ -296,9 +297,9 @@ impl Cursor { /// Is the referent a fully specialized template specialization without any /// remaining free template arguments? pub(crate) fn is_fully_specialized_template(&self) -> bool { - self.is_template_specialization() && - self.kind() != CXCursor_ClassTemplatePartialSpecialization && - self.num_template_args().unwrap_or(0) > 0 + self.is_template_specialization() + && self.kind() != CXCursor_ClassTemplatePartialSpecialization + && self.num_template_args().unwrap_or(0) > 0 } /// Is the referent a template specialization that still has remaining free @@ -324,9 +325,9 @@ impl Cursor { pub(crate) fn is_template_parameter(&self) -> bool { matches!( self.kind(), - CXCursor_TemplateTemplateParameter | - CXCursor_TemplateTypeParameter | - CXCursor_NonTypeTemplateParameter + CXCursor_TemplateTemplateParameter + | CXCursor_TemplateTypeParameter + | CXCursor_NonTypeTemplateParameter ) } @@ -664,9 +665,9 @@ impl Cursor { // inline function without a definition, and it's not a defaulted // function, we can reasonably safely conclude that it's a deleted // function. - self.is_inlined_function() && - self.definition().is_none() && - !self.is_defaulted_function() + self.is_inlined_function() + && self.definition().is_none() + && !self.is_defaulted_function() } /// Is the referent a bit field declaration? @@ -788,11 +789,11 @@ impl Cursor { let found_attr = &mut found_attrs[idx]; if !*found_attr { // `attr.name` and` attr.token_kind` are checked against unexposed attributes only. - if attr.kind == Some(kind) || - (kind == CXCursor_UnexposedAttr && - cur.tokens().iter().any(|t| { - t.kind == attr.token_kind && - t.spelling() == attr.name + if attr.kind == Some(kind) + || (kind == CXCursor_UnexposedAttr + && cur.tokens().iter().any(|t| { + t.kind == attr.token_kind + && t.spelling() == attr.name })) { *found_attr = true; @@ -1408,12 +1409,12 @@ impl Type { /// to. pub(crate) fn pointee_type(&self) -> Option { match self.kind() { - CXType_Pointer | - CXType_RValueReference | - CXType_LValueReference | - CXType_MemberPointer | - CXType_BlockPointer | - CXType_ObjCObjectPointer => { + CXType_Pointer + | CXType_RValueReference + | CXType_LValueReference + | CXType_MemberPointer + | CXType_BlockPointer + | CXType_ObjCObjectPointer => { let ret = Type { x: unsafe { clang_getPointeeType(self.x) }, }; @@ -1516,12 +1517,12 @@ impl Type { // Yep, the spelling of this containing type-parameter is extremely // nasty... But can happen in . Unfortunately I couldn't // reduce it enough :( - self.template_args().is_some_and(|args| args.len() > 0) && - !matches!( + self.template_args().is_some_and(|args| args.len() > 0) + && !matches!( self.declaration().kind(), - CXCursor_ClassTemplatePartialSpecialization | - CXCursor_TypeAliasTemplateDecl | - CXCursor_TemplateTemplateParameter + CXCursor_ClassTemplatePartialSpecialization + | CXCursor_TypeAliasTemplateDecl + | CXCursor_TemplateTemplateParameter ) } @@ -1546,9 +1547,9 @@ impl Type { .is_match(spelling.as_ref()) } - self.kind() == CXType_Unexposed && - (hacky_parse_associated_type(self.spelling()) || - hacky_parse_associated_type( + self.kind() == CXType_Unexposed + && (hacky_parse_associated_type(self.spelling()) + || hacky_parse_associated_type( self.canonical_type().spelling(), )) } @@ -1822,12 +1823,15 @@ impl TranslationUnit { /// Parse a source file into a translation unit. pub(crate) fn parse( ix: &Index, - file: &str, + file: Option<&Path>, cmd_args: &[Box], unsaved: &[UnsavedFile], opts: CXTranslationUnit_Flags, ) -> Option { - let fname = CString::new(file).unwrap(); + let fname = match file { + Some(file) => path_to_cstring(file), + None => CString::new(vec![]).unwrap(), + }; let _c_args: Vec = cmd_args .iter() .map(|s| CString::new(s.as_bytes()).unwrap()) @@ -1879,10 +1883,8 @@ impl TranslationUnit { } /// Save a translation unit to the given file. - pub(crate) fn save(&mut self, file: &str) -> Result<(), CXSaveError> { - let Ok(file) = CString::new(file) else { - return Err(CXSaveError_Unknown); - }; + pub(crate) fn save(&mut self, file: &Path) -> Result<(), CXSaveError> { + let file = path_to_cstring(file); let ret = unsafe { clang_saveTranslationUnit( self.x, @@ -1913,8 +1915,9 @@ impl Drop for TranslationUnit { /// Translation unit used for macro fallback parsing pub(crate) struct FallbackTranslationUnit { - file_path: String, - pch_path: String, + temp_dir: TempDir, + file_path: PathBuf, + pch_path: PathBuf, idx: Box, tu: TranslationUnit, } @@ -1928,8 +1931,9 @@ impl fmt::Debug for FallbackTranslationUnit { impl FallbackTranslationUnit { /// Create a new fallback translation unit pub(crate) fn new( - file: String, - pch_path: String, + temp_dir: TempDir, + file: PathBuf, + pch_path: PathBuf, c_args: &[Box], ) -> Option { // Create empty file @@ -1943,12 +1947,13 @@ impl FallbackTranslationUnit { let f_index = Box::new(Index::new(true, false)); let f_translation_unit = TranslationUnit::parse( &f_index, - &file, + Some(&file), c_args, &[], CXTranslationUnit_None, )?; Some(FallbackTranslationUnit { + temp_dir, file_path: file, pch_path, tu: f_translation_unit, @@ -1985,13 +1990,6 @@ impl FallbackTranslationUnit { } } -impl Drop for FallbackTranslationUnit { - fn drop(&mut self) { - let _ = std::fs::remove_file(&self.file_path); - let _ = std::fs::remove_file(&self.pch_path); - } -} - /// A diagnostic message generated while parsing a translation unit. pub(crate) struct Diagnostic { x: CXDiagnostic, @@ -2032,9 +2030,9 @@ pub(crate) struct UnsavedFile { } impl UnsavedFile { - /// Construct a new unsaved file with the given `name` and `contents`. - pub(crate) fn new(name: &str, contents: &str) -> UnsavedFile { - let name = CString::new(name.as_bytes()).unwrap(); + /// Construct a new unsaved file with the given `path` and `contents`. + pub(crate) fn new(path: &Path, contents: &str) -> UnsavedFile { + let name = path_to_cstring(path); let contents = CString::new(contents.as_bytes()).unwrap(); let x = CXUnsavedFile { Filename: name.as_ptr(), @@ -2309,8 +2307,8 @@ impl EvalResult { { let mut found_cant_eval = false; cursor.visit(|c| { - if c.kind() == CXCursor_TypeRef && - c.cur_type().canonical_type().kind() == CXType_Unexposed + if c.kind() == CXCursor_TypeRef + && c.cur_type().canonical_type().kind() == CXType_Unexposed { found_cant_eval = true; return CXChildVisit_Break; @@ -2446,3 +2444,7 @@ impl TargetInfo { } } } + +fn path_to_cstring(path: &Path) -> CString { + CString::new(path.to_string_lossy().as_bytes()).unwrap() +} diff --git a/bindgen/ir/context.rs b/bindgen/ir/context.rs index 78790d61c4..2fb9c696bd 100644 --- a/bindgen/ir/context.rs +++ b/bindgen/ir/context.rs @@ -31,6 +31,7 @@ use std::cell::{Cell, RefCell}; use std::collections::{BTreeSet, HashMap as StdHashMap}; use std::mem; use std::path::Path; +use tempfile::TempDir; /// An identifier for some kind of IR item. #[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)] @@ -252,9 +253,9 @@ where T: Copy + Into, { fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_partialord && - ctx.lookup_can_derive_partialeq_or_partialord(*self) == - CanDerive::Yes + ctx.options().derive_partialord + && ctx.lookup_can_derive_partialeq_or_partialord(*self) + == CanDerive::Yes } } @@ -263,9 +264,9 @@ where T: Copy + Into, { fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_partialeq && - ctx.lookup_can_derive_partialeq_or_partialord(*self) == - CanDerive::Yes + ctx.options().derive_partialeq + && ctx.lookup_can_derive_partialeq_or_partialord(*self) + == CanDerive::Yes } } @@ -274,10 +275,10 @@ where T: Copy + Into, { fn can_derive_eq(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_eq && - ctx.lookup_can_derive_partialeq_or_partialord(*self) == - CanDerive::Yes && - !ctx.lookup_has_float(*self) + ctx.options().derive_eq + && ctx.lookup_can_derive_partialeq_or_partialord(*self) + == CanDerive::Yes + && !ctx.lookup_has_float(*self) } } @@ -286,10 +287,10 @@ where T: Copy + Into, { fn can_derive_ord(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_ord && - ctx.lookup_can_derive_partialeq_or_partialord(*self) == - CanDerive::Yes && - !ctx.lookup_has_float(*self) + ctx.options().derive_ord + && ctx.lookup_can_derive_partialeq_or_partialord(*self) + == CanDerive::Yes + && !ctx.lookup_has_float(*self) } } @@ -555,7 +556,7 @@ impl BindgenContext { clang::TranslationUnit::parse( &index, - "", + None, &options.clang_args, input_unsaved_files, parse_options, @@ -702,11 +703,11 @@ If you encounter an error missing from this list, please file an issue or a PR!" ) { debug!("BindgenContext::add_item({item:?}, declaration: {declaration:?}, loc: {location:?}"); debug_assert!( - declaration.is_some() || - !item.kind().is_type() || - item.kind().expect_type().is_builtin_or_type_param() || - item.kind().expect_type().is_opaque(self, &item) || - item.kind().expect_type().is_unresolved_ref(), + declaration.is_some() + || !item.kind().is_type() + || item.kind().expect_type().is_builtin_or_type_param() + || item.kind().expect_type().is_opaque(self, &item) + || item.kind().expect_type().is_unresolved_ref(), "Adding a type without declaration?" ); @@ -1067,10 +1068,10 @@ If you encounter an error missing from this list, please file an issue or a PR!" }; match *ty.kind() { - TypeKind::Comp(..) | - TypeKind::TemplateAlias(..) | - TypeKind::Enum(..) | - TypeKind::Alias(..) => {} + TypeKind::Comp(..) + | TypeKind::TemplateAlias(..) + | TypeKind::Enum(..) + | TypeKind::Alias(..) => {} _ => continue, } @@ -1665,9 +1666,9 @@ If you encounter an error missing from this list, please file an issue or a PR!" for child in children.iter().rev() { match child.kind() { - clang_sys::CXCursor_TypeRef | - clang_sys::CXCursor_TypedefDecl | - clang_sys::CXCursor_TypeAliasDecl => { + clang_sys::CXCursor_TypeRef + | clang_sys::CXCursor_TypedefDecl + | clang_sys::CXCursor_TypeAliasDecl => { // The `with_id` ID will potentially end up unused if we give up // on this type (for example, because it has const value // template args), so if we pass `with_id` as the parent, it is @@ -1691,8 +1692,8 @@ If you encounter an error missing from this list, please file an issue or a PR!" child, )?; - if num_expected_template_args == 0 || - child.has_at_least_num_children( + if num_expected_template_args == 0 + || child.has_at_least_num_children( num_expected_template_args, ) { @@ -1865,8 +1866,8 @@ If you encounter an error missing from this list, please file an issue or a PR!" // * we have already parsed and resolved this type, and // there's nothing left to do. if let Some(location) = location { - if decl.cursor().is_template_like() && - *ty != decl.cursor().cur_type() + if decl.cursor().is_template_like() + && *ty != decl.cursor().cur_type() { // For specialized type aliases, there's no way to get the // template parameters as of this writing (for a struct @@ -1878,10 +1879,10 @@ If you encounter an error missing from this list, please file an issue or a PR!" // exposed. // // This is _tricky_, I know :( - if decl.cursor().kind() == - CXCursor_TypeAliasTemplateDecl && - !location.contains_cursor(CXCursor_TypeRef) && - ty.canonical_type().is_valid_and_exposed() + if decl.cursor().kind() + == CXCursor_TypeAliasTemplateDecl + && !location.contains_cursor(CXCursor_TypeRef) + && ty.canonical_type().is_valid_and_exposed() { return None; } @@ -2040,20 +2041,18 @@ If you encounter an error missing from this list, please file an issue or a PR!" &mut self, ) -> Option<&mut clang::FallbackTranslationUnit> { if self.fallback_tu.is_none() { - let file = format!( - "{}/.macro_eval.c", - match self.options().clang_macro_fallback_build_dir { - Some(ref path) => path.as_os_str().to_str()?, - None => ".", - } - ); + let temp_dir = TempDir::new().unwrap(); + + let file = temp_dir.path().join(".macro_eval.c"); let index = clang::Index::new(false, false); let mut header_names_to_compile = Vec::new(); let mut header_paths = Vec::new(); let mut header_includes = Vec::new(); - let single_header = self.options().input_headers.last().cloned()?; + let single_header = + Path::new(&self.options().input_headers.last()?.as_ref()) + .to_owned(); for input_header in &self.options.input_headers [..self.options.input_headers.len() - 1] { @@ -2072,14 +2071,9 @@ If you encounter an error missing from this list, please file an issue or a PR!" header_names_to_compile .push(header_name.split(".h").next()?.to_string()); } - let pch = format!( - "{}/{}", - match self.options().clang_macro_fallback_build_dir { - Some(ref path) => path.as_os_str().to_str()?, - None => ".", - }, - header_names_to_compile.join("-") + "-precompile.h.pch" - ); + let pch = temp_dir + .path() + .join(header_names_to_compile.join("-") + "-precompile.h.pch"); let mut c_args = self.options.fallback_clang_args.clone(); c_args.push("-x".to_string().into_boxed_str()); @@ -2093,7 +2087,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" } let mut tu = clang::TranslationUnit::parse( &index, - &single_header, + Some(&single_header), &c_args, &[], clang_sys::CXTranslationUnit_ForSerialization, @@ -2102,7 +2096,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" let mut c_args = vec![ "-include-pch".to_string().into_boxed_str(), - pch.clone().into_boxed_str(), + pch.to_string_lossy().into_owned().into_boxed_str(), ]; let mut skip_next = false; for arg in self.options.fallback_clang_args.iter() { @@ -2114,8 +2108,9 @@ If you encounter an error missing from this list, please file an issue or a PR!" c_args.push(arg.clone()) } } - self.fallback_tu = - Some(clang::FallbackTranslationUnit::new(file, pch, &c_args)?); + self.fallback_tu = Some(clang::FallbackTranslationUnit::new( + temp_dir, file, pch, &c_args, + )?); } self.fallback_tu.as_mut() @@ -2374,9 +2369,9 @@ If you encounter an error missing from this list, please file an issue or a PR!" /// Is the given type a type from that corresponds to a Rust primitive type? pub(crate) fn is_stdint_type(&self, name: &str) -> bool { match name { - "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" | - "uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" | - "intptr_t" | "ptrdiff_t" => true, + "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" + | "uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" + | "intptr_t" | "ptrdiff_t" => true, "size_t" | "ssize_t" => self.options.size_t_is_usize, _ => false, } @@ -2404,11 +2399,11 @@ If you encounter an error missing from this list, please file an issue or a PR!" .filter(|&(_, item)| { // If nothing is explicitly allowlisted, then everything is fair // game. - if self.options().allowlisted_types.is_empty() && - self.options().allowlisted_functions.is_empty() && - self.options().allowlisted_vars.is_empty() && - self.options().allowlisted_files.is_empty() && - self.options().allowlisted_items.is_empty() + if self.options().allowlisted_types.is_empty() + && self.options().allowlisted_functions.is_empty() + && self.options().allowlisted_vars.is_empty() + && self.options().allowlisted_files.is_empty() + && self.options().allowlisted_items.is_empty() { return true; } @@ -2461,19 +2456,19 @@ If you encounter an error missing from this list, please file an issue or a PR!" // make the #[derive] analysis not be lame. if !self.options().allowlist_recursively { match *ty.kind() { - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Array(..) | - TypeKind::Vector(..) | - TypeKind::Pointer(..) | - TypeKind::Reference(..) | - TypeKind::Function(..) | - TypeKind::ResolvedTypeRef(..) | - TypeKind::Opaque | - TypeKind::TypeParam => return true, + TypeKind::Void + | TypeKind::NullPtr + | TypeKind::Int(..) + | TypeKind::Float(..) + | TypeKind::Complex(..) + | TypeKind::Array(..) + | TypeKind::Vector(..) + | TypeKind::Pointer(..) + | TypeKind::Reference(..) + | TypeKind::Function(..) + | TypeKind::ResolvedTypeRef(..) + | TypeKind::Opaque + | TypeKind::TypeParam => return true, _ => {} } if self.is_stdint_type(&name) { @@ -2784,9 +2779,9 @@ If you encounter an error missing from this list, please file an issue or a PR!" fn compute_cannot_derive_partialord_partialeq_or_eq(&mut self) { let _t = self.timer("compute_cannot_derive_partialord_partialeq_or_eq"); assert!(self.cannot_derive_partialeq_or_partialord.is_none()); - if self.options.derive_partialord || - self.options.derive_partialeq || - self.options.derive_eq + if self.options.derive_partialord + || self.options.derive_partialeq + || self.options.derive_eq { self.cannot_derive_partialeq_or_partialord = Some(analyze::(( @@ -2833,8 +2828,8 @@ If you encounter an error missing from this list, please file an issue or a PR!" // derive `Copy` or not. let id = id.into(); - !self.lookup_has_type_param_in_array(id) && - !self.cannot_derive_copy.as_ref().unwrap().contains(&id) + !self.lookup_has_type_param_in_array(id) + && !self.cannot_derive_copy.as_ref().unwrap().contains(&id) } /// Compute whether the type has type parameter in array. @@ -3061,15 +3056,15 @@ impl TemplateParameters for PartialType { // Wouldn't it be nice if libclang would reliably give us this // information‽ match self.decl().kind() { - clang_sys::CXCursor_ClassTemplate | - clang_sys::CXCursor_FunctionTemplate | - clang_sys::CXCursor_TypeAliasTemplateDecl => { + clang_sys::CXCursor_ClassTemplate + | clang_sys::CXCursor_FunctionTemplate + | clang_sys::CXCursor_TypeAliasTemplateDecl => { let mut num_params = 0; self.decl().visit(|c| { match c.kind() { - clang_sys::CXCursor_TemplateTypeParameter | - clang_sys::CXCursor_TemplateTemplateParameter | - clang_sys::CXCursor_NonTypeTemplateParameter => { + clang_sys::CXCursor_TemplateTypeParameter + | clang_sys::CXCursor_TemplateTemplateParameter + | clang_sys::CXCursor_NonTypeTemplateParameter => { num_params += 1; } _ => {} diff --git a/bindgen/lib.rs b/bindgen/lib.rs index 1a15d51d67..dfff8004f1 100644 --- a/bindgen/lib.rs +++ b/bindgen/lib.rs @@ -371,7 +371,7 @@ impl Builder { std::mem::take(&mut self.options.input_header_contents) .into_iter() .map(|(name, contents)| { - clang::UnsavedFile::new(name.as_ref(), contents.as_ref()) + clang::UnsavedFile::new((*name).as_ref(), contents.as_ref()) }) .collect::>(); diff --git a/bindgen/options/cli.rs b/bindgen/options/cli.rs index 8c4c05bc84..91bfd3cd6b 100644 --- a/bindgen/options/cli.rs +++ b/bindgen/options/cli.rs @@ -459,9 +459,6 @@ struct BindgenCommand { /// Enable fallback for clang macro parsing. #[arg(long)] clang_macro_fallback: bool, - /// Set path for temporary files generated by fallback for clang macro parsing. - #[arg(long)] - clang_macro_fallback_build_dir: Option, /// Use DSTs to represent structures with flexible array members. #[arg(long)] flexarray_dst: bool, @@ -635,7 +632,6 @@ where override_abi, wrap_unsafe_ops, clang_macro_fallback, - clang_macro_fallback_build_dir, flexarray_dst, with_derive_custom, with_derive_custom_struct, @@ -932,7 +928,6 @@ where override_abi => |b, (abi, regex)| b.override_abi(abi, regex), wrap_unsafe_ops, clang_macro_fallback => |b, _| b.clang_macro_fallback(), - clang_macro_fallback_build_dir, flexarray_dst, wrap_static_fns, wrap_static_fns_path, diff --git a/bindgen/options/mod.rs b/bindgen/options/mod.rs index 9d1d195980..9e455ec21f 100644 --- a/bindgen/options/mod.rs +++ b/bindgen/options/mod.rs @@ -2153,22 +2153,4 @@ options! { }, as_args: "--clang-macro-fallback", } - /// Path to use for temporary files created by clang macro fallback code like precompiled - /// headers. - clang_macro_fallback_build_dir: Option { - methods: { - /// Set a path to a directory to which `.c` and `.h.pch` files should be written for the - /// purpose of using clang to evaluate macros that can't be easily parsed. - /// - /// The default location for `.h.pch` files is the directory that the corresponding - /// `.h` file is located in. The default for the temporary `.c` file used for clang - /// parsing is the current working directory. Both of these defaults are overridden - /// by this option. - pub fn clang_macro_fallback_build_dir>(mut self, path: P) -> Self { - self.options.clang_macro_fallback_build_dir = Some(path.as_ref().to_owned()); - self - } - }, - as_args: "--clang-macro-fallback-build-dir", - } }